diff --git a/src/services/indexedDBMigrationService.ts b/src/services/indexedDBMigrationService.ts index 5aaa1241..f6061b8f 100644 --- a/src/services/indexedDBMigrationService.ts +++ b/src/services/indexedDBMigrationService.ts @@ -898,6 +898,10 @@ export function generateComparisonYaml(comparison: DataComparison): string { * } * ``` */ +/** + * + * I recommend using the existing contact import view to migrate contacts. + * export async function migrateContacts( overwriteExisting: boolean = false, ): Promise { @@ -976,6 +980,8 @@ export async function migrateContacts( return result; } } + * + */ /** * Migrates specific settings fields from Dexie to SQLite database @@ -991,13 +997,12 @@ export async function migrateContacts( * * @async * @function migrateSettings - * @param {boolean} [overwriteExisting=false] - Whether to overwrite existing settings in SQLite * @returns {Promise} Detailed results of the migration operation * @throws {Error} If the migration process fails completely * @example * ```typescript * try { - * const result = await migrateSettings(true); // Overwrite existing + * const result = await migrateSettings(); * if (result.success) { * console.log(`Successfully migrated ${result.settingsMigrated} settings`); * } else { @@ -1008,12 +1013,8 @@ export async function migrateContacts( * } * ``` */ -export async function migrateSettings( - overwriteExisting: boolean = false, -): Promise { - logger.info("[MigrationService] Starting settings migration", { - overwriteExisting, - }); +export async function migrateSettings(): Promise { + logger.info("[MigrationService] Starting settings migration"); const result: MigrationResult = { success: true, @@ -1026,19 +1027,34 @@ export async function migrateSettings( try { const dexieSettings = await getDexieSettings(); + logger.info("[MigrationService] Migrating settings", { + dexieSettings: dexieSettings.length, + }); const platformService = PlatformServiceFactory.getInstance(); - // loop through dexieSettings, - // load the one with the matching accountDid from sqlite, - // and if one doesn't exist then insert it, - // otherwise, update the fields - dexieSettings.forEach(async (setting) => { - const sqliteSettingRaw = await platformService.dbQuery( - "SELECT * FROM settings WHERE accountDid = ?", - [setting.accountDid] - ); + + // Create an array of promises for all settings migrations + const migrationPromises = dexieSettings.map(async (setting) => { + logger.info("[MigrationService] Starting to migrate settings", setting); + let sqliteSettingRaw: { columns: string[], values: unknown[][] } | undefined; + if (!setting.accountDid) { + sqliteSettingRaw = await platformService.dbQuery( + "SELECT * FROM settings WHERE accountDid is null" + ); + } else { + sqliteSettingRaw = await platformService.dbQuery( + "SELECT * FROM settings WHERE accountDid = ?", + [setting.accountDid] + ) + } + logger.info("[MigrationService] Migrating one set of settings:", { + setting, + sqliteSettingRaw, + }); if (sqliteSettingRaw?.values?.length) { // should cover the master settings, were accountDid is null - const sqliteSetting = mapColumnsToValues(sqliteSettingRaw.columns, sqliteSettingRaw.values) as unknown as Settings; + const sqliteSettings = mapColumnsToValues(sqliteSettingRaw.columns, sqliteSettingRaw.values) as unknown as Settings[]; + const sqliteSetting = sqliteSettings[0]; + console.log('sqliteSetting', sqliteSetting) let conditional: string; let preparams: unknown[]; if (!setting.accountDid) { @@ -1054,7 +1070,7 @@ export async function migrateSettings( conditional, preparams ); - await platformService.dbExec(sql, params); + await platformService.dbExec(sql, params) result.settingsMigrated++; } else { // insert new setting @@ -1068,12 +1084,17 @@ export async function migrateSettings( } }); + // Wait for all migrations to complete + const updatedSettings = await Promise.all(migrationPromises); + + logger.info("[MigrationService] Finished migrating settings", updatedSettings, result); + return result; } catch (error) { + logger.error("[MigrationService] Complete settings migration failed:", error); const errorMessage = `Settings migration failed: ${error}`; result.errors.push(errorMessage); result.success = false; - logger.error("[MigrationService] Complete settings migration failed:", error); return result; } } @@ -1083,7 +1104,7 @@ export async function migrateSettings( * * This function transfers all accounts from the Dexie database to the * SQLite database. It handles both new accounts (INSERT) and existing - * accounts (UPDATE) based on the overwriteExisting parameter. + * accounts (UPDATE). * * For accounts with mnemonic data, the function uses importFromMnemonic * to ensure proper key derivation and identity creation during migration. @@ -1100,7 +1121,7 @@ export async function migrateSettings( * @example * ```typescript * try { - * const result = await migrateAccounts(true); // Overwrite existing + * const result = await migrateAccounts(); * if (result.success) { * console.log(`Successfully migrated ${result.accountsMigrated} accounts`); * } else { @@ -1199,12 +1220,9 @@ export async function migrateAccounts(): Promise { * 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 { +export async function migrateAll(): Promise { const result: MigrationResult = { success: false, contactsMigrated: 0, @@ -1233,7 +1251,7 @@ export async function migrateAll( // Step 2: Migrate Settings (depends on accounts) logger.info("[MigrationService] Step 2: Migrating settings..."); - const settingsResult = await migrateSettings(overwriteExisting); + const settingsResult = await migrateSettings(); if (!settingsResult.success) { result.errors.push( `Settings migration failed: ${settingsResult.errors.join(", ")}`, @@ -1244,16 +1262,17 @@ export async function migrateAll( 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); + // ... but which is better done through the contact import view + // logger.info("[MigrationService] Step 3: Migrating contacts..."); + // const contactsResult = await migrateContacts(); + // 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; diff --git a/src/views/DatabaseMigration.vue b/src/views/DatabaseMigration.vue index 95917e12..bfd3caed 100644 --- a/src/views/DatabaseMigration.vue +++ b/src/views/DatabaseMigration.vue @@ -19,8 +19,9 @@ + +

@@ -52,6 +53,7 @@

+ -->
- Beware: you have unexpected existing data in the SQLite database that will be overwritten. Talk with Trent. + Beware: you have unexpected existing data in the new database that will be overwritten. Talk with Trent.

| null = null; - private overwriteExisting = true; private successMessage = ""; useClipboard = useClipboard; @@ -1075,7 +1075,7 @@ export default class DatabaseMigration extends Vue { window.alert('Copied to clipboard!'); } } catch (error) { - console.error('Failed to copy to clipboard:', error); + logger.error('Failed to copy to clipboard:', error); if (typeof window !== 'undefined') { window.alert('Failed to copy to clipboard'); } @@ -1141,7 +1141,7 @@ export default class DatabaseMigration extends Vue { this.clearMessages(); try { - const result: MigrationResult = await migrateAll(this.overwriteExisting); + const result: MigrationResult = await migrateAll(); if (result.success) { const totalMigrated = @@ -1209,8 +1209,7 @@ export default class DatabaseMigration extends Vue { /** * Migrates contacts from Dexie to SQLite database * - * This method transfers contacts from the Dexie database to SQLite, - * with options to overwrite existing records. + * This method transfers contacts from the Dexie database to SQLite. * * @async * @returns {Promise} @@ -1230,8 +1229,7 @@ export default class DatabaseMigration extends Vue { /** * Migrates settings from Dexie to SQLite database * - * This method transfers settings from the Dexie database to SQLite, - * with options to overwrite existing records. + * This method transfers settings from the Dexie database to SQLite. * * @async * @returns {Promise} @@ -1241,9 +1239,7 @@ export default class DatabaseMigration extends Vue { this.clearMessages(); try { - const result: MigrationResult = await migrateSettings( - this.overwriteExisting, - ); + const result: MigrationResult = await migrateSettings(); if (result.success) { this.successMessage = `Successfully migrated ${result.settingsMigrated} settings.`; @@ -1276,8 +1272,7 @@ export default class DatabaseMigration extends Vue { * Migrates accounts from Dexie to SQLite database * * This method transfers accounts from the Dexie database to SQLite, - * with options to overwrite existing records. For accounts with mnemonic - * data, it uses the importFromMnemonic utility for proper key derivation. + * For accounts with mnemonic data, it uses the importFromMnemonic utility for proper key derivation. * * @async * @returns {Promise}