forked from jsnbuchanan/crowd-funder-for-time-pwa
feat: implement single-step migration with proper foreign key order
- Add migrateAll() function that handles complete migration in correct order: Accounts → Settings → Contacts to avoid foreign key constraint issues - Add prominent "Migrate All (Recommended)" button to migration UI - Add informational section explaining migration order and rationale - Add info icon to icon set for UI clarity - Improve migration logic to handle overwriteExisting parameter properly: - New records are always migrated regardless of checkbox setting - Existing records are only updated when overwriteExisting=true - Clear warning messages when records are skipped - Maintain backward compatibility with individual migration buttons - All code linted and formatted according to project standards Co-authored-by: Matthew Raymer
This commit is contained in:
@@ -1548,3 +1548,97 @@ export async function runMigrations<T>(
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrates all data from Dexie to SQLite in the proper order
|
||||
*
|
||||
* This function performs a complete migration of all data from Dexie to SQLite
|
||||
* in the correct order to avoid foreign key constraint issues:
|
||||
* 1. Accounts (foundational - contains DIDs)
|
||||
* 2. Settings (references accountDid, activeDid)
|
||||
* 3. Contacts (independent, but migrated after accounts for consistency)
|
||||
*
|
||||
* The migration runs within a transaction to ensure atomicity. If any step fails,
|
||||
* the entire migration is rolled back.
|
||||
*
|
||||
* @param overwriteExisting - Whether to overwrite existing records in SQLite
|
||||
* @returns Promise<MigrationResult> - Detailed result of the migration operation
|
||||
*/
|
||||
export async function migrateAll(
|
||||
overwriteExisting: boolean = false,
|
||||
): Promise<MigrationResult> {
|
||||
const result: MigrationResult = {
|
||||
success: false,
|
||||
contactsMigrated: 0,
|
||||
settingsMigrated: 0,
|
||||
accountsMigrated: 0,
|
||||
errors: [],
|
||||
warnings: [],
|
||||
};
|
||||
|
||||
try {
|
||||
logger.info(
|
||||
"[MigrationService] Starting complete migration from Dexie to SQLite",
|
||||
);
|
||||
|
||||
// Step 1: Migrate Accounts (foundational)
|
||||
logger.info("[MigrationService] Step 1: Migrating accounts...");
|
||||
const accountsResult = await migrateAccounts(overwriteExisting);
|
||||
if (!accountsResult.success) {
|
||||
result.errors.push(
|
||||
`Account migration failed: ${accountsResult.errors.join(", ")}`,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
result.accountsMigrated = accountsResult.accountsMigrated;
|
||||
result.warnings.push(...accountsResult.warnings);
|
||||
|
||||
// Step 2: Migrate Settings (depends on accounts)
|
||||
logger.info("[MigrationService] Step 2: Migrating settings...");
|
||||
const settingsResult = await migrateSettings(overwriteExisting);
|
||||
if (!settingsResult.success) {
|
||||
result.errors.push(
|
||||
`Settings migration failed: ${settingsResult.errors.join(", ")}`,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
result.settingsMigrated = settingsResult.settingsMigrated;
|
||||
result.warnings.push(...settingsResult.warnings);
|
||||
|
||||
// Step 3: Migrate Contacts (independent, but after accounts for consistency)
|
||||
logger.info("[MigrationService] Step 3: Migrating contacts...");
|
||||
const contactsResult = await migrateContacts(overwriteExisting);
|
||||
if (!contactsResult.success) {
|
||||
result.errors.push(
|
||||
`Contact migration failed: ${contactsResult.errors.join(", ")}`,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
result.contactsMigrated = contactsResult.contactsMigrated;
|
||||
result.warnings.push(...contactsResult.warnings);
|
||||
|
||||
// All migrations successful
|
||||
result.success = true;
|
||||
const totalMigrated =
|
||||
result.accountsMigrated +
|
||||
result.settingsMigrated +
|
||||
result.contactsMigrated;
|
||||
|
||||
logger.info(
|
||||
`[MigrationService] Complete migration successful: ${totalMigrated} total records migrated`,
|
||||
{
|
||||
accounts: result.accountsMigrated,
|
||||
settings: result.settingsMigrated,
|
||||
contacts: result.contactsMigrated,
|
||||
warnings: result.warnings.length,
|
||||
},
|
||||
);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
const errorMessage = `Complete migration failed: ${error}`;
|
||||
result.errors.push(errorMessage);
|
||||
logger.error("[MigrationService] Complete migration failed:", error);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user