|  |  | @ -26,10 +26,19 @@ import "dexie-export-import"; | 
			
		
	
		
			
				
					|  |  |  | import { PlatformServiceFactory } from "./PlatformServiceFactory"; | 
			
		
	
		
			
				
					|  |  |  | import { db, accountsDBPromise } from "../db/index"; | 
			
		
	
		
			
				
					|  |  |  | import { Contact, ContactMethod } from "../db/tables/contacts"; | 
			
		
	
		
			
				
					|  |  |  | import { Settings, MASTER_SETTINGS_KEY, BoundingBox } from "../db/tables/settings"; | 
			
		
	
		
			
				
					|  |  |  | import { | 
			
		
	
		
			
				
					|  |  |  |   Settings, | 
			
		
	
		
			
				
					|  |  |  |   MASTER_SETTINGS_KEY, | 
			
		
	
		
			
				
					|  |  |  |   BoundingBox, | 
			
		
	
		
			
				
					|  |  |  | } from "../db/tables/settings"; | 
			
		
	
		
			
				
					|  |  |  | import { Account } from "../db/tables/accounts"; | 
			
		
	
		
			
				
					|  |  |  | import { logger } from "../utils/logger"; | 
			
		
	
		
			
				
					|  |  |  | import { mapColumnsToValues, parseJsonField, generateUpdateStatement, generateInsertStatement } from "../db/databaseUtil"; | 
			
		
	
		
			
				
					|  |  |  | import { | 
			
		
	
		
			
				
					|  |  |  |   mapColumnsToValues, | 
			
		
	
		
			
				
					|  |  |  |   parseJsonField, | 
			
		
	
		
			
				
					|  |  |  |   generateUpdateStatement, | 
			
		
	
		
			
				
					|  |  |  |   generateInsertStatement, | 
			
		
	
		
			
				
					|  |  |  | } from "../db/databaseUtil"; | 
			
		
	
		
			
				
					|  |  |  | import { importFromMnemonic } from "../libs/util"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
	
		
			
				
					|  |  | @ -186,12 +195,18 @@ export async function getSqliteContacts(): Promise<Contact[]> { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     let contacts: Contact[] = []; | 
			
		
	
		
			
				
					|  |  |  |     if (result?.values?.length) { | 
			
		
	
		
			
				
					|  |  |  |       const preContacts = mapColumnsToValues(result.columns, result.values) as unknown as Contact[]; | 
			
		
	
		
			
				
					|  |  |  |       const preContacts = mapColumnsToValues( | 
			
		
	
		
			
				
					|  |  |  |         result.columns, | 
			
		
	
		
			
				
					|  |  |  |         result.values, | 
			
		
	
		
			
				
					|  |  |  |       ) as unknown as Contact[]; | 
			
		
	
		
			
				
					|  |  |  |       // This is redundant since absurd-sql auto-parses JSON strings to objects.
 | 
			
		
	
		
			
				
					|  |  |  |       // But we started it, and it should be known everywhere, so we're keeping it.
 | 
			
		
	
		
			
				
					|  |  |  |       contacts = preContacts.map((contact) => { | 
			
		
	
		
			
				
					|  |  |  |         if (contact.contactMethods) { | 
			
		
	
		
			
				
					|  |  |  |           contact.contactMethods = parseJsonField(contact.contactMethods, []) as ContactMethod[]; | 
			
		
	
		
			
				
					|  |  |  |           contact.contactMethods = parseJsonField( | 
			
		
	
		
			
				
					|  |  |  |             contact.contactMethods, | 
			
		
	
		
			
				
					|  |  |  |             [], | 
			
		
	
		
			
				
					|  |  |  |           ) as ContactMethod[]; | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |         return contact; | 
			
		
	
		
			
				
					|  |  |  |       }); | 
			
		
	
	
		
			
				
					|  |  | @ -275,16 +290,21 @@ export async function getSqliteSettings(): Promise<Settings[]> { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     let settings: Settings[] = []; | 
			
		
	
		
			
				
					|  |  |  |     if (result?.values?.length) { | 
			
		
	
		
			
				
					|  |  |  |       const presettings = | 
			
		
	
		
			
				
					|  |  |  |         mapColumnsToValues(result.columns, result.values) as Settings[]; | 
			
		
	
		
			
				
					|  |  |  |       const presettings = mapColumnsToValues( | 
			
		
	
		
			
				
					|  |  |  |         result.columns, | 
			
		
	
		
			
				
					|  |  |  |         result.values, | 
			
		
	
		
			
				
					|  |  |  |       ) as Settings[]; | 
			
		
	
		
			
				
					|  |  |  |       // This is redundant since absurd-sql auto-parses JSON strings to objects.
 | 
			
		
	
		
			
				
					|  |  |  |       // But we started it, and it should be known everywhere, so we're keeping it.
 | 
			
		
	
		
			
				
					|  |  |  |       settings = presettings.map((setting) => { | 
			
		
	
		
			
				
					|  |  |  |         if (setting.searchBoxes) { | 
			
		
	
		
			
				
					|  |  |  |           setting.searchBoxes = parseJsonField(setting.searchBoxes, []) as Array<{ name: string, bbox: BoundingBox }>; | 
			
		
	
		
			
				
					|  |  |  |           setting.searchBoxes = parseJsonField( | 
			
		
	
		
			
				
					|  |  |  |             setting.searchBoxes, | 
			
		
	
		
			
				
					|  |  |  |             [], | 
			
		
	
		
			
				
					|  |  |  |           ) as Array<{ name: string; bbox: BoundingBox }>; | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |         return setting; | 
			
		
	
		
			
				
					|  |  |  |       }) | 
			
		
	
		
			
				
					|  |  |  |       }); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     logger.info( | 
			
		
	
	
		
			
				
					|  |  | @ -557,7 +577,9 @@ function compareSettings( | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   // Find settings that exist in Dexie but not in SQLite
 | 
			
		
	
		
			
				
					|  |  |  |   for (const dexieSetting of dexieSettings) { | 
			
		
	
		
			
				
					|  |  |  |     const sqliteSetting = sqliteSettings.find((s) => s.accountDid == dexieSetting.accountDid); | 
			
		
	
		
			
				
					|  |  |  |     const sqliteSetting = sqliteSettings.find( | 
			
		
	
		
			
				
					|  |  |  |       (s) => s.accountDid == dexieSetting.accountDid, | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  |     if (!sqliteSetting) { | 
			
		
	
		
			
				
					|  |  |  |       added.push(dexieSetting); | 
			
		
	
		
			
				
					|  |  |  |     } else if (!settingsEqual(dexieSetting, sqliteSetting)) { | 
			
		
	
	
		
			
				
					|  |  | @ -569,7 +591,9 @@ function compareSettings( | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   // Find settings that exist in SQLite but not in Dexie
 | 
			
		
	
		
			
				
					|  |  |  |   for (const sqliteSetting of sqliteSettings) { | 
			
		
	
		
			
				
					|  |  |  |     const dexieSetting = dexieSettings.find((s) => s.accountDid == sqliteSetting.accountDid); | 
			
		
	
		
			
				
					|  |  |  |     const dexieSetting = dexieSettings.find( | 
			
		
	
		
			
				
					|  |  |  |       (s) => s.accountDid == sqliteSetting.accountDid, | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  |     if (!dexieSetting) { | 
			
		
	
		
			
				
					|  |  |  |       missing.push(sqliteSetting); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
	
		
			
				
					|  |  | @ -654,22 +678,29 @@ function compareAccounts(dexieAccounts: Account[], sqliteDids: string[]) { | 
			
		
	
		
			
				
					|  |  |  |  * ``` | 
			
		
	
		
			
				
					|  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  | function contactsEqual(contact1: Contact, contact2: Contact): boolean { | 
			
		
	
		
			
				
					|  |  |  |   const ifEmpty = (arg: any, def: any) => !!arg ? arg : def; | 
			
		
	
		
			
				
					|  |  |  |   const ifEmpty = (arg: any, def: any) => (arg ? arg : def); | 
			
		
	
		
			
				
					|  |  |  |   const contact1Methods = | 
			
		
	
		
			
				
					|  |  |  |     contact1.contactMethods && Array.isArray(contact1.contactMethods) && contact1.contactMethods.length > 0 | 
			
		
	
		
			
				
					|  |  |  |     ? JSON.stringify(contact1.contactMethods) | 
			
		
	
		
			
				
					|  |  |  |     : "[]"; | 
			
		
	
		
			
				
					|  |  |  |     contact1.contactMethods && | 
			
		
	
		
			
				
					|  |  |  |     Array.isArray(contact1.contactMethods) && | 
			
		
	
		
			
				
					|  |  |  |     contact1.contactMethods.length > 0 | 
			
		
	
		
			
				
					|  |  |  |       ? JSON.stringify(contact1.contactMethods) | 
			
		
	
		
			
				
					|  |  |  |       : "[]"; | 
			
		
	
		
			
				
					|  |  |  |   const contact2Methods = | 
			
		
	
		
			
				
					|  |  |  |     contact2.contactMethods && Array.isArray(contact2.contactMethods) && contact2.contactMethods.length > 0 | 
			
		
	
		
			
				
					|  |  |  |     ? JSON.stringify(contact2.contactMethods) | 
			
		
	
		
			
				
					|  |  |  |     : "[]"; | 
			
		
	
		
			
				
					|  |  |  |     contact2.contactMethods && | 
			
		
	
		
			
				
					|  |  |  |     Array.isArray(contact2.contactMethods) && | 
			
		
	
		
			
				
					|  |  |  |     contact2.contactMethods.length > 0 | 
			
		
	
		
			
				
					|  |  |  |       ? JSON.stringify(contact2.contactMethods) | 
			
		
	
		
			
				
					|  |  |  |       : "[]"; | 
			
		
	
		
			
				
					|  |  |  |   return ( | 
			
		
	
		
			
				
					|  |  |  |     ifEmpty(contact1.did, "") == ifEmpty(contact2.did, "") && | 
			
		
	
		
			
				
					|  |  |  |     ifEmpty(contact1.name, "") == ifEmpty(contact2.name, "") && | 
			
		
	
		
			
				
					|  |  |  |     ifEmpty(contact1.notes, "") == ifEmpty(contact2.notes, "") && | 
			
		
	
		
			
				
					|  |  |  |     ifEmpty(contact1.profileImageUrl, "") == ifEmpty(contact2.profileImageUrl, "") && | 
			
		
	
		
			
				
					|  |  |  |     ifEmpty(contact1.publicKeyBase64, "") == ifEmpty(contact2.publicKeyBase64, "") && | 
			
		
	
		
			
				
					|  |  |  |     ifEmpty(contact1.nextPubKeyHashB64, "") == ifEmpty(contact2.nextPubKeyHashB64, "") && | 
			
		
	
		
			
				
					|  |  |  |     ifEmpty(contact1.profileImageUrl, "") == | 
			
		
	
		
			
				
					|  |  |  |       ifEmpty(contact2.profileImageUrl, "") && | 
			
		
	
		
			
				
					|  |  |  |     ifEmpty(contact1.publicKeyBase64, "") == | 
			
		
	
		
			
				
					|  |  |  |       ifEmpty(contact2.publicKeyBase64, "") && | 
			
		
	
		
			
				
					|  |  |  |     ifEmpty(contact1.nextPubKeyHashB64, "") == | 
			
		
	
		
			
				
					|  |  |  |       ifEmpty(contact2.nextPubKeyHashB64, "") && | 
			
		
	
		
			
				
					|  |  |  |     !!contact1.seesMe == !!contact2.seesMe && | 
			
		
	
		
			
				
					|  |  |  |     !!contact1.registered == !!contact2.registered && | 
			
		
	
		
			
				
					|  |  |  |     contact1Methods == contact2Methods | 
			
		
	
	
		
			
				
					|  |  | @ -762,18 +793,21 @@ function settingsEqual(settings1: Settings, settings2: Settings): boolean { | 
			
		
	
		
			
				
					|  |  |  |  * } | 
			
		
	
		
			
				
					|  |  |  |  * ``` | 
			
		
	
		
			
				
					|  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  | function accountsEqual(account1: Account, account2: Account): boolean { | 
			
		
	
		
			
				
					|  |  |  |   return ( | 
			
		
	
		
			
				
					|  |  |  |     account1.id === account2.id && | 
			
		
	
		
			
				
					|  |  |  |     account1.dateCreated === account2.dateCreated && | 
			
		
	
		
			
				
					|  |  |  |     account1.derivationPath === account2.derivationPath && | 
			
		
	
		
			
				
					|  |  |  |     account1.did === account2.did && | 
			
		
	
		
			
				
					|  |  |  |     account1.identity === account2.identity && | 
			
		
	
		
			
				
					|  |  |  |     account1.mnemonic === account2.mnemonic && | 
			
		
	
		
			
				
					|  |  |  |     account1.passkeyCredIdHex === account2.passkeyCredIdHex && | 
			
		
	
		
			
				
					|  |  |  |     account1.publicKeyHex === account2.publicKeyHex | 
			
		
	
		
			
				
					|  |  |  |   ); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | //
 | 
			
		
	
		
			
				
					|  |  |  | // unused
 | 
			
		
	
		
			
				
					|  |  |  | //
 | 
			
		
	
		
			
				
					|  |  |  | // function accountsEqual(account1: Account, account2: Account): boolean {
 | 
			
		
	
		
			
				
					|  |  |  | //   return (
 | 
			
		
	
		
			
				
					|  |  |  | //     account1.id === account2.id &&
 | 
			
		
	
		
			
				
					|  |  |  | //     account1.dateCreated === account2.dateCreated &&
 | 
			
		
	
		
			
				
					|  |  |  | //     account1.derivationPath === account2.derivationPath &&
 | 
			
		
	
		
			
				
					|  |  |  | //     account1.did === account2.did &&
 | 
			
		
	
		
			
				
					|  |  |  | //     account1.identity === account2.identity &&
 | 
			
		
	
		
			
				
					|  |  |  | //     account1.mnemonic === account2.mnemonic &&
 | 
			
		
	
		
			
				
					|  |  |  | //     account1.passkeyCredIdHex === account2.passkeyCredIdHex &&
 | 
			
		
	
		
			
				
					|  |  |  | //     account1.publicKeyHex === account2.publicKeyHex
 | 
			
		
	
		
			
				
					|  |  |  | //   );
 | 
			
		
	
		
			
				
					|  |  |  | // }
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  * Generates YAML-formatted comparison data | 
			
		
	
	
		
			
				
					|  |  | @ -801,58 +835,64 @@ export function generateComparisonYaml(comparison: DataComparison): string { | 
			
		
	
		
			
				
					|  |  |  |   const yaml = { | 
			
		
	
		
			
				
					|  |  |  |     summary: { | 
			
		
	
		
			
				
					|  |  |  |       dexieContacts: comparison.dexieContacts.length, | 
			
		
	
		
			
				
					|  |  |  |       sqliteContacts: comparison.sqliteContacts.filter(c => c.did).length, | 
			
		
	
		
			
				
					|  |  |  |       sqliteContacts: comparison.sqliteContacts.filter((c) => c.did).length, | 
			
		
	
		
			
				
					|  |  |  |       dexieSettings: comparison.dexieSettings.length, | 
			
		
	
		
			
				
					|  |  |  |       sqliteSettings: comparison.sqliteSettings.filter(s => s.accountDid || s.activeDid).length, | 
			
		
	
		
			
				
					|  |  |  |       sqliteSettings: comparison.sqliteSettings.filter( | 
			
		
	
		
			
				
					|  |  |  |         (s) => s.accountDid || s.activeDid, | 
			
		
	
		
			
				
					|  |  |  |       ).length, | 
			
		
	
		
			
				
					|  |  |  |       dexieAccounts: comparison.dexieAccounts.length, | 
			
		
	
		
			
				
					|  |  |  |       sqliteAccounts: comparison.sqliteAccounts.filter(a => a).length, | 
			
		
	
		
			
				
					|  |  |  |       sqliteAccounts: comparison.sqliteAccounts.filter((a) => a).length, | 
			
		
	
		
			
				
					|  |  |  |     }, | 
			
		
	
		
			
				
					|  |  |  |     differences: { | 
			
		
	
		
			
				
					|  |  |  |       contacts: { | 
			
		
	
		
			
				
					|  |  |  |         added: comparison.differences.contacts.added.length, | 
			
		
	
		
			
				
					|  |  |  |         modified: comparison.differences.contacts.modified.length, | 
			
		
	
		
			
				
					|  |  |  |         unmodified: comparison.differences.contacts.unmodified.length, | 
			
		
	
		
			
				
					|  |  |  |         missing: comparison.differences.contacts.missing.filter(c => c.did).length, | 
			
		
	
		
			
				
					|  |  |  |         missing: comparison.differences.contacts.missing.filter((c) => c.did) | 
			
		
	
		
			
				
					|  |  |  |           .length, | 
			
		
	
		
			
				
					|  |  |  |       }, | 
			
		
	
		
			
				
					|  |  |  |       settings: { | 
			
		
	
		
			
				
					|  |  |  |         added: comparison.differences.settings.added.length, | 
			
		
	
		
			
				
					|  |  |  |         modified: comparison.differences.settings.modified.length, | 
			
		
	
		
			
				
					|  |  |  |         unmodified: comparison.differences.settings.unmodified.length, | 
			
		
	
		
			
				
					|  |  |  |         missing: comparison.differences.settings.missing.filter(s => s.accountDid || s.activeDid).length, | 
			
		
	
		
			
				
					|  |  |  |         missing: comparison.differences.settings.missing.filter( | 
			
		
	
		
			
				
					|  |  |  |           (s) => s.accountDid || s.activeDid, | 
			
		
	
		
			
				
					|  |  |  |         ).length, | 
			
		
	
		
			
				
					|  |  |  |       }, | 
			
		
	
		
			
				
					|  |  |  |       accounts: { | 
			
		
	
		
			
				
					|  |  |  |         added: comparison.differences.accounts.added.length, | 
			
		
	
		
			
				
					|  |  |  |         unmodified: comparison.differences.accounts.unmodified.length, | 
			
		
	
		
			
				
					|  |  |  |         missing: comparison.differences.accounts.missing.filter(a => a).length, | 
			
		
	
		
			
				
					|  |  |  |         missing: comparison.differences.accounts.missing.filter((a) => a) | 
			
		
	
		
			
				
					|  |  |  |           .length, | 
			
		
	
		
			
				
					|  |  |  |       }, | 
			
		
	
		
			
				
					|  |  |  |     }, | 
			
		
	
		
			
				
					|  |  |  |     details: { | 
			
		
	
		
			
				
					|  |  |  |       contacts: { | 
			
		
	
		
			
				
					|  |  |  |         dexie: comparison.dexieContacts.map((c) => ({ | 
			
		
	
		
			
				
					|  |  |  |           did: c.did, | 
			
		
	
		
			
				
					|  |  |  |           name: c.name || '<empty>', | 
			
		
	
		
			
				
					|  |  |  |           name: c.name || "<empty>", | 
			
		
	
		
			
				
					|  |  |  |           contactMethods: (c.contactMethods || []).length, | 
			
		
	
		
			
				
					|  |  |  |         })), | 
			
		
	
		
			
				
					|  |  |  |         sqlite: comparison.sqliteContacts | 
			
		
	
		
			
				
					|  |  |  |           .filter(c => c.did) | 
			
		
	
		
			
				
					|  |  |  |           .filter((c) => c.did) | 
			
		
	
		
			
				
					|  |  |  |           .map((c) => ({ | 
			
		
	
		
			
				
					|  |  |  |             did: c.did, | 
			
		
	
		
			
				
					|  |  |  |             name: c.name || '<empty>', | 
			
		
	
		
			
				
					|  |  |  |             name: c.name || "<empty>", | 
			
		
	
		
			
				
					|  |  |  |             contactMethods: (c.contactMethods || []).length, | 
			
		
	
		
			
				
					|  |  |  |           })), | 
			
		
	
		
			
				
					|  |  |  |       }, | 
			
		
	
		
			
				
					|  |  |  |       settings: { | 
			
		
	
		
			
				
					|  |  |  |         dexie: comparison.dexieSettings.map((s) => ({ | 
			
		
	
		
			
				
					|  |  |  |           id: s.id, | 
			
		
	
		
			
				
					|  |  |  |           type: s.id === MASTER_SETTINGS_KEY ? 'master' : 'account', | 
			
		
	
		
			
				
					|  |  |  |           type: s.id === MASTER_SETTINGS_KEY ? "master" : "account", | 
			
		
	
		
			
				
					|  |  |  |           did: s.activeDid || s.accountDid, | 
			
		
	
		
			
				
					|  |  |  |           isRegistered: s.isRegistered || false, | 
			
		
	
		
			
				
					|  |  |  |         })), | 
			
		
	
		
			
				
					|  |  |  |         sqlite: comparison.sqliteSettings | 
			
		
	
		
			
				
					|  |  |  |           .filter(s => s.accountDid || s.activeDid) | 
			
		
	
		
			
				
					|  |  |  |           .filter((s) => s.accountDid || s.activeDid) | 
			
		
	
		
			
				
					|  |  |  |           .map((s) => ({ | 
			
		
	
		
			
				
					|  |  |  |             id: s.id, | 
			
		
	
		
			
				
					|  |  |  |             type: s.id === MASTER_SETTINGS_KEY ? 'master' : 'account', | 
			
		
	
		
			
				
					|  |  |  |             type: s.id === MASTER_SETTINGS_KEY ? "master" : "account", | 
			
		
	
		
			
				
					|  |  |  |             did: s.activeDid || s.accountDid, | 
			
		
	
		
			
				
					|  |  |  |             isRegistered: s.isRegistered || false, | 
			
		
	
		
			
				
					|  |  |  |           })), | 
			
		
	
	
		
			
				
					|  |  | @ -1043,16 +1083,18 @@ export async function migrateSettings(): Promise<MigrationResult> { | 
			
		
	
		
			
				
					|  |  |  |     // 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; | 
			
		
	
		
			
				
					|  |  |  |       let sqliteSettingRaw: | 
			
		
	
		
			
				
					|  |  |  |         | { columns: string[]; values: unknown[][] } | 
			
		
	
		
			
				
					|  |  |  |         | undefined; | 
			
		
	
		
			
				
					|  |  |  |       if (!setting.accountDid) { | 
			
		
	
		
			
				
					|  |  |  |         sqliteSettingRaw = await platformService.dbQuery( | 
			
		
	
		
			
				
					|  |  |  |           "SELECT * FROM settings WHERE accountDid is null" | 
			
		
	
		
			
				
					|  |  |  |           "SELECT * FROM settings WHERE accountDid is null", | 
			
		
	
		
			
				
					|  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |       } else { | 
			
		
	
		
			
				
					|  |  |  |         sqliteSettingRaw = await platformService.dbQuery( | 
			
		
	
		
			
				
					|  |  |  |           "SELECT * FROM settings WHERE accountDid = ?", | 
			
		
	
		
			
				
					|  |  |  |           [setting.accountDid] | 
			
		
	
		
			
				
					|  |  |  |         ) | 
			
		
	
		
			
				
					|  |  |  |           [setting.accountDid], | 
			
		
	
		
			
				
					|  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |       logger.info("[MigrationService] Migrating one set of settings:", { | 
			
		
	
		
			
				
					|  |  |  |         setting, | 
			
		
	
	
		
			
				
					|  |  | @ -1060,9 +1102,11 @@ export async function migrateSettings(): Promise<MigrationResult> { | 
			
		
	
		
			
				
					|  |  |  |       }); | 
			
		
	
		
			
				
					|  |  |  |       if (sqliteSettingRaw?.values?.length) { | 
			
		
	
		
			
				
					|  |  |  |         // should cover the master settings, were accountDid is null
 | 
			
		
	
		
			
				
					|  |  |  |         const sqliteSettings = 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) { | 
			
		
	
	
		
			
				
					|  |  | @ -1076,16 +1120,16 @@ export async function migrateSettings(): Promise<MigrationResult> { | 
			
		
	
		
			
				
					|  |  |  |           sqliteSetting as unknown as Record<string, unknown>, | 
			
		
	
		
			
				
					|  |  |  |           "settings", | 
			
		
	
		
			
				
					|  |  |  |           conditional, | 
			
		
	
		
			
				
					|  |  |  |           preparams | 
			
		
	
		
			
				
					|  |  |  |           preparams, | 
			
		
	
		
			
				
					|  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |         await platformService.dbExec(sql, params) | 
			
		
	
		
			
				
					|  |  |  |         await platformService.dbExec(sql, params); | 
			
		
	
		
			
				
					|  |  |  |         result.settingsMigrated++; | 
			
		
	
		
			
				
					|  |  |  |       } else { | 
			
		
	
		
			
				
					|  |  |  |         // insert new setting
 | 
			
		
	
		
			
				
					|  |  |  |         delete setting.activeDid; // ensure we don't set the activeDid (since master settings are an update and don't hit this case)
 | 
			
		
	
		
			
				
					|  |  |  |         const { sql, params } = generateInsertStatement( | 
			
		
	
		
			
				
					|  |  |  |           setting as unknown as Record<string, unknown>, | 
			
		
	
		
			
				
					|  |  |  |           "settings" | 
			
		
	
		
			
				
					|  |  |  |           "settings", | 
			
		
	
		
			
				
					|  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |         await platformService.dbExec(sql, params); | 
			
		
	
		
			
				
					|  |  |  |         result.settingsMigrated++; | 
			
		
	
	
		
			
				
					|  |  | @ -1095,11 +1139,18 @@ export async function migrateSettings(): Promise<MigrationResult> { | 
			
		
	
		
			
				
					|  |  |  |     // Wait for all migrations to complete
 | 
			
		
	
		
			
				
					|  |  |  |     const updatedSettings = await Promise.all(migrationPromises); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     logger.info("[MigrationService] Finished migrating settings", updatedSettings, result); | 
			
		
	
		
			
				
					|  |  |  |     logger.info( | 
			
		
	
		
			
				
					|  |  |  |       "[MigrationService] Finished migrating settings", | 
			
		
	
		
			
				
					|  |  |  |       updatedSettings, | 
			
		
	
		
			
				
					|  |  |  |       result, | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     return result; | 
			
		
	
		
			
				
					|  |  |  |   } catch (error) { | 
			
		
	
		
			
				
					|  |  |  |     logger.error("[MigrationService] Complete settings migration failed:", error); | 
			
		
	
		
			
				
					|  |  |  |     logger.error( | 
			
		
	
		
			
				
					|  |  |  |       "[MigrationService] Complete settings migration failed:", | 
			
		
	
		
			
				
					|  |  |  |       error, | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  |     const errorMessage = `Settings migration failed: ${error}`; | 
			
		
	
		
			
				
					|  |  |  |     result.errors.push(errorMessage); | 
			
		
	
		
			
				
					|  |  |  |     result.success = false; | 
			
		
	
	
		
			
				
					|  |  | @ -1158,12 +1209,17 @@ export async function migrateAccounts(): Promise<MigrationResult> { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // Group accounts by DID and keep only the most recent one
 | 
			
		
	
		
			
				
					|  |  |  |     const accountsByDid = new Map<string, Account>(); | 
			
		
	
		
			
				
					|  |  |  |     dexieAccounts.forEach(account => { | 
			
		
	
		
			
				
					|  |  |  |     dexieAccounts.forEach((account) => { | 
			
		
	
		
			
				
					|  |  |  |       const existingAccount = accountsByDid.get(account.did); | 
			
		
	
		
			
				
					|  |  |  |       if (!existingAccount || new Date(account.dateCreated) > new Date(existingAccount.dateCreated)) { | 
			
		
	
		
			
				
					|  |  |  |       if ( | 
			
		
	
		
			
				
					|  |  |  |         !existingAccount || | 
			
		
	
		
			
				
					|  |  |  |         new Date(account.dateCreated) > new Date(existingAccount.dateCreated) | 
			
		
	
		
			
				
					|  |  |  |       ) { | 
			
		
	
		
			
				
					|  |  |  |         accountsByDid.set(account.did, account); | 
			
		
	
		
			
				
					|  |  |  |         if (existingAccount) { | 
			
		
	
		
			
				
					|  |  |  |           result.warnings.push(`Found duplicate account for DID ${account.did}, keeping most recent`); | 
			
		
	
		
			
				
					|  |  |  |           result.warnings.push( | 
			
		
	
		
			
				
					|  |  |  |             `Found duplicate account for DID ${account.did}, keeping most recent`, | 
			
		
	
		
			
				
					|  |  |  |           ); | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |     }); | 
			
		
	
	
		
			
				
					|  |  | @ -1174,30 +1230,34 @@ export async function migrateAccounts(): Promise<MigrationResult> { | 
			
		
	
		
			
				
					|  |  |  |         // Check if account already exists
 | 
			
		
	
		
			
				
					|  |  |  |         const existingResult = await platformService.dbQuery( | 
			
		
	
		
			
				
					|  |  |  |           "SELECT did FROM accounts WHERE did = ?", | 
			
		
	
		
			
				
					|  |  |  |           [did] | 
			
		
	
		
			
				
					|  |  |  |           [did], | 
			
		
	
		
			
				
					|  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         if (existingResult?.values?.length) { | 
			
		
	
		
			
				
					|  |  |  |           result.warnings.push(`Account with DID ${did} already exists, skipping`); | 
			
		
	
		
			
				
					|  |  |  |           result.warnings.push( | 
			
		
	
		
			
				
					|  |  |  |             `Account with DID ${did} already exists, skipping`, | 
			
		
	
		
			
				
					|  |  |  |           ); | 
			
		
	
		
			
				
					|  |  |  |           continue; | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |         if (account.mnemonic) { | 
			
		
	
		
			
				
					|  |  |  |           await importFromMnemonic(account.mnemonic, account.derivationPath); | 
			
		
	
		
			
				
					|  |  |  |           result.accountsMigrated++; | 
			
		
	
		
			
				
					|  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |           result.errors.push(`Account with DID ${did} has no mnemonic, skipping`); | 
			
		
	
		
			
				
					|  |  |  |           result.errors.push( | 
			
		
	
		
			
				
					|  |  |  |             `Account with DID ${did} has no mnemonic, skipping`, | 
			
		
	
		
			
				
					|  |  |  |           ); | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         logger.info("[MigrationService] Successfully migrated account", { | 
			
		
	
		
			
				
					|  |  |  |           did, | 
			
		
	
		
			
				
					|  |  |  |           dateCreated: account.dateCreated | 
			
		
	
		
			
				
					|  |  |  |           dateCreated: account.dateCreated, | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  |       } catch (error) { | 
			
		
	
		
			
				
					|  |  |  |         const errorMessage = `Failed to migrate account ${did}: ${error}`; | 
			
		
	
		
			
				
					|  |  |  |         result.errors.push(errorMessage); | 
			
		
	
		
			
				
					|  |  |  |         logger.error("[MigrationService] Account migration failed:", { | 
			
		
	
		
			
				
					|  |  |  |           error, | 
			
		
	
		
			
				
					|  |  |  |           did | 
			
		
	
		
			
				
					|  |  |  |           did, | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
	
		
			
				
					|  |  | @ -1211,7 +1271,10 @@ export async function migrateAccounts(): Promise<MigrationResult> { | 
			
		
	
		
			
				
					|  |  |  |     const errorMessage = `Account migration failed: ${error}`; | 
			
		
	
		
			
				
					|  |  |  |     result.errors.push(errorMessage); | 
			
		
	
		
			
				
					|  |  |  |     result.success = false; | 
			
		
	
		
			
				
					|  |  |  |     logger.error("[MigrationService] Complete account migration failed:", error); | 
			
		
	
		
			
				
					|  |  |  |     logger.error( | 
			
		
	
		
			
				
					|  |  |  |       "[MigrationService] Complete account migration failed:", | 
			
		
	
		
			
				
					|  |  |  |       error, | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  |     return result; | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
	
		
			
				
					|  |  | 
 |