refactor(electron): WIP - use window.CapacitorSQLite API for all DB ops in ElectronPlatformService
- Remove connection object and connection pool logic - Call all database methods directly on window.CapacitorSQLite with db name - Refactor migrations, queries, and exec to match Capacitor SQLite Electron API - Ensure preload script exposes both window.electron and window.CapacitorSQLite - Fixes runtime errors related to missing query/run methods on connection - Improves security and cross-platform compatibility Co-authored-by: Matthew Raymer
This commit is contained in:
@@ -40,52 +40,71 @@ if (electronIsDev) {
|
||||
// Run Application
|
||||
(async () => {
|
||||
try {
|
||||
// Wait for electron app to be ready.
|
||||
await app.whenReady();
|
||||
// Wait for electron app to be ready.
|
||||
await app.whenReady();
|
||||
|
||||
// Security - Set Content-Security-Policy based on whether or not we are in dev mode.
|
||||
setupContentSecurityPolicy(myCapacitorApp.getCustomURLScheme());
|
||||
// Security - Set Content-Security-Policy based on whether or not we are in dev mode.
|
||||
setupContentSecurityPolicy(myCapacitorApp.getCustomURLScheme());
|
||||
|
||||
// Initialize SQLite and register handlers BEFORE app initialization
|
||||
console.log('[Main] Starting SQLite initialization...');
|
||||
// Initialize our app, build windows, and load content first
|
||||
console.log('[Electron Main Process] Starting app initialization...');
|
||||
await myCapacitorApp.init();
|
||||
console.log('[Electron Main Process] App initialization complete');
|
||||
|
||||
// Get the main window and wait for it to be ready
|
||||
const mainWindow = myCapacitorApp.getMainWindow();
|
||||
if (!mainWindow) {
|
||||
throw new Error('Main window not available after app initialization');
|
||||
}
|
||||
|
||||
// Wait for window to be ready
|
||||
await new Promise<void>((resolve) => {
|
||||
if (mainWindow.isVisible()) {
|
||||
resolve();
|
||||
} else {
|
||||
mainWindow.once('show', () => resolve());
|
||||
}
|
||||
});
|
||||
|
||||
// Now initialize SQLite after window is ready
|
||||
console.log('[Electron Main Process] Starting SQLite initialization...');
|
||||
try {
|
||||
// Register handlers first to prevent "no handler" errors
|
||||
setupSQLiteHandlers();
|
||||
console.log('[Main] SQLite handlers registered');
|
||||
console.log('[Electron Main Process] SQLite handlers registered');
|
||||
|
||||
// Then initialize the plugin
|
||||
await initializeSQLite();
|
||||
console.log('[Main] SQLite plugin initialized successfully');
|
||||
console.log('[Electron Main Process] SQLite plugin initialized successfully');
|
||||
|
||||
// Send SQLite ready signal since window is ready
|
||||
if (!mainWindow.isDestroyed()) {
|
||||
mainWindow.webContents.send('sqlite-ready');
|
||||
console.log('[Electron Main Process] Sent SQLite ready signal to renderer');
|
||||
} else {
|
||||
console.warn('[Electron Main Process] Could not send SQLite ready signal - window was destroyed');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Main] Failed to initialize SQLite:', error);
|
||||
console.error('[Electron Main Process] Failed to initialize SQLite:', error);
|
||||
// Notify renderer about database status
|
||||
if (!mainWindow.isDestroyed()) {
|
||||
mainWindow.webContents.send('database-status', {
|
||||
status: 'error',
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
});
|
||||
}
|
||||
// Don't proceed with app initialization if SQLite fails
|
||||
throw new Error(`SQLite initialization failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
}
|
||||
|
||||
// Initialize our app, build windows, and load content.
|
||||
console.log('[Main] Starting app initialization...');
|
||||
await myCapacitorApp.init();
|
||||
console.log('[Main] App initialization complete');
|
||||
|
||||
// Check for updates if we are in a packaged app.
|
||||
// Check for updates if we are in a packaged app.
|
||||
if (!electronIsDev) {
|
||||
console.log('[Main] Checking for updates...');
|
||||
autoUpdater.checkForUpdatesAndNotify();
|
||||
console.log('[Electron Main Process] Checking for updates...');
|
||||
autoUpdater.checkForUpdatesAndNotify();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Main] Fatal error during app initialization:', error);
|
||||
// Ensure we notify the user before quitting
|
||||
const mainWindow = myCapacitorApp.getMainWindow();
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
mainWindow.webContents.send('app-error', {
|
||||
type: 'initialization',
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
});
|
||||
// Give the window time to show the error
|
||||
setTimeout(() => app.quit(), 5000);
|
||||
} else {
|
||||
app.quit();
|
||||
}
|
||||
console.error('[Electron Main Process] Fatal error during initialization:', error);
|
||||
app.quit();
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
@@ -41,12 +41,12 @@ const createSQLiteProxy = () => {
|
||||
} catch (error) {
|
||||
lastError = error instanceof Error ? error : new Error(String(error));
|
||||
if (attempt < MAX_RETRIES) {
|
||||
logger.warn(`SQLite operation failed (attempt ${attempt}/${MAX_RETRIES}), retrying...`, error);
|
||||
logger.warn(`[CapacitorSQLite] SQLite operation failed (attempt ${attempt}/${MAX_RETRIES}), retrying...`, error);
|
||||
await new Promise(resolve => setTimeout(resolve, RETRY_DELAY));
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Error(`SQLite operation failed after ${MAX_RETRIES} attempts: ${lastError?.message || 'Unknown error'}`);
|
||||
throw new Error(`[CapacitorSQLite] SQLite operation failed after ${MAX_RETRIES} attempts: ${lastError?.message || 'Unknown error'}`);
|
||||
};
|
||||
|
||||
const wrapOperation = (method: string) => {
|
||||
@@ -65,8 +65,8 @@ const createSQLiteProxy = () => {
|
||||
}
|
||||
return await withRetry(ipcRenderer.invoke, 'sqlite-' + method, ...args);
|
||||
} catch (error) {
|
||||
logger.error(`SQLite ${method} failed:`, error);
|
||||
throw new Error(`Database operation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
logger.error(`[CapacitorSQLite] SQLite ${method} failed:`, error);
|
||||
throw new Error(`[CapacitorSQLite] Database operation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -85,13 +85,24 @@ const createSQLiteProxy = () => {
|
||||
};
|
||||
};
|
||||
|
||||
// Expose only the CapacitorSQLite proxy
|
||||
// Expose the Electron IPC API
|
||||
contextBridge.exposeInMainWorld('electron', {
|
||||
ipcRenderer: {
|
||||
on: (channel: string, func: (...args: unknown[]) => void) => ipcRenderer.on(channel, (event, ...args) => func(...args)),
|
||||
once: (channel: string, func: (...args: unknown[]) => void) => ipcRenderer.once(channel, (event, ...args) => func(...args)),
|
||||
send: (channel: string, data: unknown) => ipcRenderer.send(channel, data),
|
||||
invoke: (channel: string, ...args: unknown[]) => ipcRenderer.invoke(channel, ...args),
|
||||
},
|
||||
// Add other APIs as needed
|
||||
});
|
||||
|
||||
// Expose CapacitorSQLite proxy as before
|
||||
contextBridge.exposeInMainWorld('CapacitorSQLite', createSQLiteProxy());
|
||||
|
||||
// Log startup
|
||||
logger.log('Script starting...');
|
||||
logger.log('[CapacitorSQLite] Preload script starting...');
|
||||
|
||||
// Handle window load
|
||||
window.addEventListener('load', () => {
|
||||
logger.log('Script complete');
|
||||
logger.log('[CapacitorSQLite] Preload script complete');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user