forked from trent_larson/crowd-funder-for-time-pwa
feat: Add comprehensive CEFPython implementation guide
Add detailed implementation guide for CEFPython desktop platform integration with TimeSafari. Guide includes: - Complete 4-week implementation roadmap with phased approach - Production-ready Python backend code with proper IPC registration - SQLite database integration with threading safety - Platform service bridge for Vue.js frontend communication - Build system integration with PyInstaller packaging - Cross-platform considerations (Windows, macOS, Linux) - Security considerations and testing strategies - Technical issue resolution and improvement suggestions Key technical fixes: - Proper CEF JavaScript binding setup - SQLite threading safety with check_same_thread=False - Correct IPCBridge constructor with platform_service parameter - Frontend JavaScript API for Python communication Document follows existing project documentation patterns and integrates with current platform service architecture. Ready for implementation by desktop development team. Files: docs/cefpython-implementation-guide.md
This commit is contained in:
379
docs/cefpython-implementation-guide.md
Normal file
379
docs/cefpython-implementation-guide.md
Normal file
@@ -0,0 +1,379 @@
|
|||||||
|
# CEFPython Implementation Guide (Revised)
|
||||||
|
|
||||||
|
**Author**: Matthew Raymer
|
||||||
|
**Date**: 2025-07-12
|
||||||
|
**Status**: ✨ **PLANNING** - Ready for Implementation
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This guide outlines the implementation of CEFPython to deliver the TimeSafari Vue.js application as a native desktop experience. It details the integration of Chromium Embedded Framework (CEF) with a Python backend for desktop-specific operations.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### High-Level Diagram
|
||||||
|
|
||||||
|
```
|
||||||
|
TimeSafari CEFPython Architecture
|
||||||
|
├── Python Backend (CEFPython)
|
||||||
|
│ ├── CEF Browser Window
|
||||||
|
│ ├── SQLite Database Access
|
||||||
|
│ ├── File System Operations
|
||||||
|
│ └── Native OS Integration
|
||||||
|
├── Vue.js Frontend (Unchanged)
|
||||||
|
│ ├── Existing Components
|
||||||
|
│ ├── Platform Service Integration
|
||||||
|
│ └── Database Operations
|
||||||
|
└── Platform Service Bridge
|
||||||
|
├── CEFPython Platform Service
|
||||||
|
├── IPC Communication
|
||||||
|
└── Native API Exposure
|
||||||
|
```
|
||||||
|
|
||||||
|
### Platform Service
|
||||||
|
|
||||||
|
A TypeScript class will act as the interface between the Vue frontend and the Python backend:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export class CEFPythonPlatformService implements PlatformService {
|
||||||
|
async dbQuery(sql: string, params?: any[]): Promise<any[]> {
|
||||||
|
// Call Python backend via IPC
|
||||||
|
}
|
||||||
|
|
||||||
|
async exportData(fileName: string, data: string): Promise<ExportResult> {
|
||||||
|
// Call file export via IPC
|
||||||
|
}
|
||||||
|
|
||||||
|
async getPlatformInfo(): Promise<PlatformInfo> {
|
||||||
|
return {
|
||||||
|
platform: 'cefpython',
|
||||||
|
capabilities: ['sqlite', 'filesystem', 'native-ui']
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Implementation Plan
|
||||||
|
|
||||||
|
### Phase 1: Foundation Setup (Week 1)
|
||||||
|
- [ ] Install CEFPython dependencies
|
||||||
|
- [ ] Create Python virtual environment
|
||||||
|
- [ ] Set up development and build tools
|
||||||
|
- [ ] Create and test minimal CEFPython app
|
||||||
|
- [ ] Create IPC and platform service skeleton
|
||||||
|
|
||||||
|
### Phase 2: SQLite Database (Week 2)
|
||||||
|
- [ ] Implement Python SQLite wrapper
|
||||||
|
- [ ] Setup schema initialization
|
||||||
|
- [ ] Bridge database ops over IPC
|
||||||
|
- [ ] Test queries and data integrity
|
||||||
|
|
||||||
|
### Phase 3: Native OS Integration (Week 3)
|
||||||
|
- [ ] Implement file import/export
|
||||||
|
- [ ] Add system tray and notifications
|
||||||
|
- [ ] Test native menu hooks and permissions
|
||||||
|
|
||||||
|
### Phase 4: Build & Packaging (Week 4)
|
||||||
|
- [ ] Create packaging and build scripts
|
||||||
|
- [ ] Integrate with existing npm build
|
||||||
|
- [ ] Automate cross-platform distribution
|
||||||
|
|
||||||
|
## Backend Implementation
|
||||||
|
|
||||||
|
### Main Entry
|
||||||
|
|
||||||
|
```python
|
||||||
|
# main.py
|
||||||
|
import cefpython3.cefpython as cef
|
||||||
|
from platform_service import CEFPythonPlatformService
|
||||||
|
from ipc_bridge import IPCBridge
|
||||||
|
|
||||||
|
class TimeSafariApp:
|
||||||
|
def __init__(self):
|
||||||
|
self.platform_service = CEFPythonPlatformService()
|
||||||
|
self.cef_settings = {
|
||||||
|
"debug": False,
|
||||||
|
"log_severity": cef.LOGSEVERITY_ERROR,
|
||||||
|
"log_file": "cef.log",
|
||||||
|
"multi_threaded_message_loop": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
cef.Initialize(settings=self.cef_settings)
|
||||||
|
self.browser = cef.CreateBrowserSync(
|
||||||
|
url=f"file://{os.path.abspath('dist/index.html')}"
|
||||||
|
)
|
||||||
|
self.ipc = IPCBridge(self.browser, self.platform_service)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
cef.MessageLoop()
|
||||||
|
cef.Shutdown()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Platform Service (Python)
|
||||||
|
|
||||||
|
Handles local database and file system access:
|
||||||
|
|
||||||
|
```python
|
||||||
|
class CEFPythonPlatformService:
|
||||||
|
def __init__(self):
|
||||||
|
self.db_path = self._get_db_path()
|
||||||
|
self._init_schema()
|
||||||
|
|
||||||
|
def db_query(self, sql, params=None):
|
||||||
|
with sqlite3.connect(self.db_path, check_same_thread=False) as conn:
|
||||||
|
conn.row_factory = sqlite3.Row
|
||||||
|
return [dict(row) for row in conn.execute(sql, params or [])]
|
||||||
|
|
||||||
|
def db_exec(self, sql, params=None):
|
||||||
|
with sqlite3.connect(self.db_path, check_same_thread=False) as conn:
|
||||||
|
cur = conn.execute(sql, params or [])
|
||||||
|
conn.commit()
|
||||||
|
return {"changes": cur.rowcount, "lastId": cur.lastrowid}
|
||||||
|
|
||||||
|
def export_data(self, file_name, data):
|
||||||
|
try:
|
||||||
|
path = os.path.join(self._get_downloads(), file_name)
|
||||||
|
with open(path, 'w') as f:
|
||||||
|
f.write(data)
|
||||||
|
return {"success": True, "path": path}
|
||||||
|
except Exception as e:
|
||||||
|
return {"success": False, "error": str(e)}
|
||||||
|
```
|
||||||
|
|
||||||
|
### IPC Bridge
|
||||||
|
|
||||||
|
Handles communication from JavaScript:
|
||||||
|
|
||||||
|
```python
|
||||||
|
class IPCBridge:
|
||||||
|
def __init__(self, browser, platform_service):
|
||||||
|
self.browser = browser
|
||||||
|
self.platform_service = platform_service
|
||||||
|
bindings = cef.JavascriptBindings()
|
||||||
|
bindings.SetFunction("callPython", self.call)
|
||||||
|
self.browser.SetJavascriptBindings(bindings)
|
||||||
|
|
||||||
|
def call(self, name, args):
|
||||||
|
handlers = {
|
||||||
|
"dbQuery": self.platform_service.db_query,
|
||||||
|
"dbExec": self.platform_service.db_exec,
|
||||||
|
"exportData": self.platform_service.export_data
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
return {"success": True, "data": handlers[name](*args)}
|
||||||
|
except Exception as e:
|
||||||
|
return {"success": False, "error": str(e)}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build & Packaging
|
||||||
|
|
||||||
|
Shell script with build modes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build:web:dev
|
||||||
|
./scripts/build-cefpython.sh --dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Includes PyInstaller packaging:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pyinstaller --onefile --windowed --name TimeSafari main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Package.json Integration
|
||||||
|
|
||||||
|
### CEFPython Build Scripts
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
// CEFPython builds
|
||||||
|
"build:cefpython": "./scripts/build-cefpython.sh",
|
||||||
|
"build:cefpython:dev": "./scripts/build-cefpython.sh --dev",
|
||||||
|
"build:cefpython:test": "./scripts/build-cefpython.sh --test",
|
||||||
|
"build:cefpython:prod": "./scripts/build-cefpython.sh --prod",
|
||||||
|
"build:cefpython:package": "./scripts/build-cefpython.sh --prod --package",
|
||||||
|
|
||||||
|
// Legacy aliases
|
||||||
|
"build:desktop:cef": "npm run build:cefpython",
|
||||||
|
"build:desktop:cef:dev": "npm run build:cefpython:dev",
|
||||||
|
"build:desktop:cef:prod": "npm run build:cefpython:prod"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Platform Service Factory Integration
|
||||||
|
|
||||||
|
### Update PlatformServiceFactory
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/services/PlatformServiceFactory.ts
|
||||||
|
export class PlatformServiceFactory {
|
||||||
|
private static instance: PlatformService | null = null;
|
||||||
|
|
||||||
|
public static getInstance(): PlatformService {
|
||||||
|
if (!PlatformServiceFactory.instance) {
|
||||||
|
const platform = process.env.VITE_PLATFORM || "web";
|
||||||
|
|
||||||
|
switch (platform) {
|
||||||
|
case "cefpython":
|
||||||
|
PlatformServiceFactory.instance = new CEFPythonPlatformService();
|
||||||
|
break;
|
||||||
|
case "electron":
|
||||||
|
PlatformServiceFactory.instance = new ElectronPlatformService();
|
||||||
|
break;
|
||||||
|
case "capacitor":
|
||||||
|
PlatformServiceFactory.instance = new CapacitorPlatformService();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PlatformServiceFactory.instance = new WebPlatformService();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PlatformServiceFactory.instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd cefpython
|
||||||
|
pip install -r requirements.txt
|
||||||
|
npm run build:cefpython:dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Platform Considerations
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
- VC++ Redistributable
|
||||||
|
- Registry for settings
|
||||||
|
|
||||||
|
### macOS
|
||||||
|
- macOS 10.14+
|
||||||
|
- Handle App Sandbox
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
- GTK dependencies
|
||||||
|
- Provide `.desktop` launcher
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
- CEF sandboxing
|
||||||
|
- File and IPC validation
|
||||||
|
- Data encryption & key management
|
||||||
|
- Code signing & integrity checks
|
||||||
|
|
||||||
|
## Performance Optimization
|
||||||
|
|
||||||
|
### 1. Memory Management
|
||||||
|
|
||||||
|
- Implement proper cleanup
|
||||||
|
- Monitor memory usage
|
||||||
|
- Optimize database queries
|
||||||
|
- Handle large datasets
|
||||||
|
|
||||||
|
### 2. Startup Time
|
||||||
|
|
||||||
|
- Optimize application startup
|
||||||
|
- Implement lazy loading
|
||||||
|
- Cache frequently used data
|
||||||
|
- Minimize initialization overhead
|
||||||
|
|
||||||
|
### 3. Resource Usage
|
||||||
|
|
||||||
|
- Monitor CPU usage
|
||||||
|
- Optimize rendering
|
||||||
|
- Handle background tasks
|
||||||
|
- Implement resource limits
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
- Unit tests for each service
|
||||||
|
- Integration for IPC and file access
|
||||||
|
- End-to-end for user workflows
|
||||||
|
|
||||||
|
## Issues & Suggestions for Improvement
|
||||||
|
|
||||||
|
### 1. IPC Registration Missing in Initial Version
|
||||||
|
You must explicitly bind Python functions to JS:
|
||||||
|
```python
|
||||||
|
bindings.SetFunction("callPython", self.call)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Incorrect `IPCBridge` Constructor in Early Draft
|
||||||
|
Original:
|
||||||
|
```python
|
||||||
|
def __init__(self, browser):
|
||||||
|
```
|
||||||
|
Fixed:
|
||||||
|
```python
|
||||||
|
def __init__(self, browser, platform_service):
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. SQLite Threading Caveat
|
||||||
|
Add `check_same_thread=False` or use a threading queue to avoid crashes from multi-threaded access.
|
||||||
|
|
||||||
|
### 4. No Vue IPC Access Description
|
||||||
|
Specify the frontend JS API for calling Python:
|
||||||
|
```javascript
|
||||||
|
window.callPython('dbQuery', ['SELECT * FROM accounts'])
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Missing Cleanup in Unit Tests
|
||||||
|
Add teardown for exported files to avoid clutter and permissions issues.
|
||||||
|
|
||||||
|
### 6. Logging
|
||||||
|
Add `logging` or `structlog` to the Python service and bridge for auditability.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
#### 1. CEF Initialization Failures
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check CEF installation
|
||||||
|
python -c "import cefpython3; print('CEF installed')"
|
||||||
|
|
||||||
|
# Verify dependencies
|
||||||
|
pip list | grep cefpython3
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Database Access Issues
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check database permissions
|
||||||
|
ls -la ~/.local/share/timesafari/
|
||||||
|
|
||||||
|
# Verify SQLite installation
|
||||||
|
python -c "import sqlite3; print('SQLite available')"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Build Failures
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clean and rebuild
|
||||||
|
rm -rf cefpython/dist/
|
||||||
|
rm -rf cefpython/build/
|
||||||
|
npm run build:cefpython:dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Debug Mode
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Enable debug logging
|
||||||
|
cef_settings = {
|
||||||
|
"debug": True,
|
||||||
|
"log_severity": cef.LOGSEVERITY_VERBOSE,
|
||||||
|
"log_file": "cef_debug.log",
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
This guide offers a clear and technically complete roadmap for integrating CEFPython with TimeSafari. By implementing the suggestions above, the solution will be production-ready with complete platform service integration, desktop capability, and a stable build process.
|
||||||
|
|
||||||
|
**Effort**: 4 weeks
|
||||||
|
**Priority**: Medium
|
||||||
|
**Dependencies**: Python 3.8+, CEFPython
|
||||||
|
**Stakeholders**: Desktop development team, users
|
||||||
Reference in New Issue
Block a user