diff --git a/src/assets/icons.json b/src/assets/icons.json index b457aa3c..434421e6 100644 --- a/src/assets/icons.json +++ b/src/assets/icons.json @@ -66,5 +66,10 @@ "strokeLinejoin": "round", "strokeWidth": "2", "d": "M12 6v6m0 0v6m0-6h6m-6 0H6" + }, + "info": { + "fillRule": "evenodd", + "d": "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z", + "clipRule": "evenodd" } } \ No newline at end of file diff --git a/src/constants/app.ts b/src/constants/app.ts index a08cb15a..b8dadbd4 100644 --- a/src/constants/app.ts +++ b/src/constants/app.ts @@ -51,7 +51,7 @@ export const IMAGE_TYPE_PROFILE = "profile"; export const PASSKEYS_ENABLED = !!import.meta.env.VITE_PASSKEYS_ENABLED || false; -export const USE_DEXIE_DB = false; +export const USE_DEXIE_DB = true; /** * The possible values for "group" and "type" are in App.vue. diff --git a/src/services/migrationService.ts b/src/services/migrationService.ts index 36e8d32c..3802d166 100644 --- a/src/services/migrationService.ts +++ b/src/services/migrationService.ts @@ -1548,3 +1548,97 @@ export async function runMigrations( 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 - Detailed result of the migration operation + */ +export async function migrateAll( + overwriteExisting: boolean = false, +): Promise { + 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; + } +} diff --git a/src/views/DatabaseMigration.vue b/src/views/DatabaseMigration.vue index eac93822..6d2144a1 100644 --- a/src/views/DatabaseMigration.vue +++ b/src/views/DatabaseMigration.vue @@ -64,6 +64,27 @@ Compare Databases + + +
+