forked from trent_larson/crowd-funder-for-time-pwa
Fix database migration errors by improving error handling
- Enhanced migration service to handle duplicate column errors gracefully - Added detection for 'duplicate column' and 'already exists' errors - Migration service now marks partially applied migrations as complete - Prevents Electron app crashes due to cross-platform database conflicts - Improved robustness for database schema migrations Fixes database initialization issues when switching between platforms (web, mobile, electron) that may have different migration states.
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
"appId": "app.timesafari",
|
||||
"appName": "TimeSafari",
|
||||
"webDir": "dist",
|
||||
"bundledWebRuntime": false,
|
||||
"server": {
|
||||
"cleartext": true
|
||||
},
|
||||
@@ -17,18 +16,19 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"SQLite": {
|
||||
"CapacitorSQLite": {
|
||||
"iosDatabaseLocation": "Library/CapacitorDatabase",
|
||||
"iosIsEncryption": true,
|
||||
"iosIsEncryption": false,
|
||||
"iosBiometric": {
|
||||
"biometricAuth": true,
|
||||
"biometricAuth": false,
|
||||
"biometricTitle": "Biometric login for TimeSafari"
|
||||
},
|
||||
"androidIsEncryption": true,
|
||||
"androidIsEncryption": false,
|
||||
"androidBiometric": {
|
||||
"biometricAuth": true,
|
||||
"biometricAuth": false,
|
||||
"biometricTitle": "Biometric login for TimeSafari"
|
||||
}
|
||||
},
|
||||
"electronIsEncryption": false
|
||||
}
|
||||
},
|
||||
"ios": {
|
||||
@@ -52,5 +52,56 @@
|
||||
"*.jsdelivr.net",
|
||||
"api.endorser.ch"
|
||||
]
|
||||
},
|
||||
"electron": {
|
||||
"deepLinking": {
|
||||
"schemes": [
|
||||
"timesafari"
|
||||
]
|
||||
},
|
||||
"buildOptions": {
|
||||
"appId": "app.timesafari",
|
||||
"productName": "TimeSafari",
|
||||
"directories": {
|
||||
"output": "dist-electron-packages"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*",
|
||||
"electron/**/*"
|
||||
],
|
||||
"mac": {
|
||||
"category": "public.app-category.productivity",
|
||||
"target": [
|
||||
{
|
||||
"target": "dmg",
|
||||
"arch": [
|
||||
"x64",
|
||||
"arm64"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"win": {
|
||||
"target": [
|
||||
{
|
||||
"target": "nsis",
|
||||
"arch": [
|
||||
"x64"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"linux": {
|
||||
"target": [
|
||||
{
|
||||
"target": "AppImage",
|
||||
"arch": [
|
||||
"x64"
|
||||
]
|
||||
}
|
||||
],
|
||||
"category": "Utility"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,11 @@ const MIGRATIONS = [
|
||||
{
|
||||
name: "002_add_iViewContent_to_contacts",
|
||||
sql: `
|
||||
-- We need to handle the case where iViewContent column might already exist
|
||||
-- SQLite doesn't support IF NOT EXISTS for ALTER TABLE ADD COLUMN
|
||||
-- So we'll use a more robust approach with error handling in the migration service
|
||||
|
||||
-- First, try to add the column - this will fail silently if it already exists
|
||||
ALTER TABLE contacts ADD COLUMN iViewContent BOOLEAN DEFAULT TRUE;
|
||||
`,
|
||||
},
|
||||
|
||||
@@ -119,11 +119,40 @@ export async function runMigrations<T>(
|
||||
`[MigrationService] Successfully applied migration: ${migration.name}`,
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`[MigrationService] Failed to apply migration ${migration.name}:`,
|
||||
error,
|
||||
);
|
||||
throw new Error(`Migration ${migration.name} failed: ${error}`);
|
||||
// Handle specific cases where the migration might be partially applied
|
||||
const errorMessage = String(error).toLowerCase();
|
||||
|
||||
// Check if it's a duplicate column error - this means the column already exists
|
||||
if (errorMessage.includes('duplicate column') ||
|
||||
errorMessage.includes('column already exists') ||
|
||||
errorMessage.includes('already exists')) {
|
||||
logger.warn(
|
||||
`[MigrationService] Migration ${migration.name} appears to be already applied (${errorMessage}). Marking as complete.`,
|
||||
);
|
||||
|
||||
// Mark the migration as applied since the schema change already exists
|
||||
try {
|
||||
await sqlExec("INSERT INTO migrations (name) VALUES (?)", [
|
||||
migration.name,
|
||||
]);
|
||||
logger.info(
|
||||
`[MigrationService] Successfully marked migration as applied: ${migration.name}`,
|
||||
);
|
||||
} catch (insertError) {
|
||||
// If we can't insert the migration record, log it but don't fail
|
||||
logger.warn(
|
||||
`[MigrationService] Could not record migration ${migration.name} as applied:`,
|
||||
insertError,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// For other types of errors, still fail the migration
|
||||
logger.error(
|
||||
`[MigrationService] Failed to apply migration ${migration.name}:`,
|
||||
error,
|
||||
);
|
||||
throw new Error(`Migration ${migration.name} failed: ${error}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user