@ -24,7 +24,7 @@
import { PlatformServiceFactory } from "./PlatformServiceFactory" ;
import { PlatformServiceFactory } from "./PlatformServiceFactory" ;
import { db , accountsDBPromise } from "../db/index" ;
import { db , accountsDBPromise } from "../db/index" ;
import { Contact , ContactMethod } from "../db/tables/contacts" ;
import { Contact , ContactMethod } from "../db/tables/contacts" ;
import { Settings } from "../db/tables/settings" ;
import { Settings , MASTER_SETTINGS_KEY } from "../db/tables/settings" ;
import { Account } from "../db/tables/accounts" ;
import { Account } from "../db/tables/accounts" ;
import { logger } from "../utils/logger" ;
import { logger } from "../utils/logger" ;
import { parseJsonField } from "../db/databaseUtil" ;
import { parseJsonField } from "../db/databaseUtil" ;
@ -285,12 +285,13 @@ export async function getSqliteSettings(): Promise<Settings[]> {
return [ ] ;
return [ ] ;
}
}
const settings = result . values . map ( ( row ) = > {
const settings = result . values
. map ( ( row ) = > {
const setting = parseJsonField ( row , { } ) as Settings ;
const setting = parseJsonField ( row , { } ) as Settings ;
return {
return {
id : setting.id ,
id : setting.id ,
accountDid : setting.accountDid || "" ,
accountDid : setting.accountDid || null ,
activeDid : setting.activeDid || "" ,
activeDid : setting.activeDid || null ,
apiServer : setting.apiServer || "" ,
apiServer : setting.apiServer || "" ,
filterFeedByNearby : setting.filterFeedByNearby || false ,
filterFeedByNearby : setting.filterFeedByNearby || false ,
filterFeedByVisible : setting.filterFeedByVisible || false ,
filterFeedByVisible : setting.filterFeedByVisible || false ,
@ -320,6 +321,10 @@ export async function getSqliteSettings(): Promise<Settings[]> {
warnIfTestServer : setting.warnIfTestServer || false ,
warnIfTestServer : setting.warnIfTestServer || false ,
webPushServer : setting.webPushServer || "" ,
webPushServer : setting.webPushServer || "" ,
} as Settings ;
} as Settings ;
} )
. filter ( ( setting ) = > {
// Only include settings that have either accountDid or activeDid set
return setting . accountDid || setting . activeDid ;
} ) ;
} ) ;
logger . info (
logger . info (
@ -837,94 +842,78 @@ function accountsEqual(account1: Account, account2: Account): boolean {
* /
* /
export function generateComparisonYaml ( comparison : DataComparison ) : string {
export function generateComparisonYaml ( comparison : DataComparison ) : string {
const yaml = {
const yaml = {
comparison : {
summary : {
summary : {
dexieContacts : comparison.dexieContacts.length ,
dexieContacts : comparison.dexieContacts.length ,
sqliteContacts : comparison.sqliteContacts.length ,
sqliteContacts : comparison.sqliteContacts.filter ( c = > c . did ) . length ,
dexieSettings : comparison.dexieSettings.length ,
dexieSettings : comparison.dexieSettings.length ,
sqliteSettings : comparison.sqliteSettings.length ,
sqliteSettings : comparison.sqliteSettings.filter ( s = > s . accountDid || s . activeDid ) . length ,
dexieAccounts : comparison.dexieAccounts.length ,
dexieAccounts : comparison.dexieAccounts.length ,
sqliteAccounts : comparison.sqliteAccounts.length ,
sqliteAccounts : comparison.sqliteAccounts.filter ( a = > a . did ) . length ,
} ,
} ,
differences : {
differences : {
contacts : {
contacts : {
added : comparison.differences.contacts.added.length ,
added : comparison.differences.contacts.added.length ,
modified : comparison.differences.contacts.modified.length ,
modified : comparison.differences.contacts.modified.length ,
missing : comparison.differences.contacts.missing.length ,
missing : comparison.differences.contacts.missing.filter ( c = > c . did ) . length ,
} ,
} ,
settings : {
settings : {
added : comparison.differences.settings.added.length ,
added : comparison.differences.settings.added.length ,
modified : comparison.differences.settings.modified.length ,
modified : comparison.differences.settings.modified.length ,
missing : comparison.differences.settings.missing.length ,
missing : comparison.differences.settings.missing.filter ( s = > s . accountDid || s . activeDid ) . length ,
} ,
} ,
accounts : {
accounts : {
added : comparison.differences.accounts.added.length ,
added : comparison.differences.accounts.added.length ,
modified : comparison.differences.accounts.modified.length ,
modified : comparison.differences.accounts.modified.length ,
missing : comparison.differences.accounts.missing.length ,
missing : comparison.differences.accounts.missing.filter ( a = > a . did ) . length ,
} ,
} ,
} ,
} ,
details : {
contacts : {
contacts : {
dexie : comparison.dexieContacts.map ( ( c ) = > ( {
dexie : comparison.dexieContacts.map ( ( c ) = > ( {
did : c.did ,
did : c.did ,
name : c.name ,
name : c.name || '<empty>' ,
notes : c.notes ,
contactMethods : ( c . contactMethods || [ ] ) . length ,
profileImageUrl : c.profileImageUrl ,
seesMe : c.seesMe ,
registered : c.registered ,
contactMethods : c.contactMethods ,
} ) ) ,
} ) ) ,
sqlite : comparison.sqliteContacts.map ( ( c ) = > ( {
sqlite : comparison.sqliteContacts
. filter ( c = > c . did )
. map ( ( c ) = > ( {
did : c.did ,
did : c.did ,
name : c.name ,
name : c.name || '<empty>' ,
notes : c.notes ,
contactMethods : ( c . contactMethods || [ ] ) . length ,
profileImageUrl : c.profileImageUrl ,
seesMe : c.seesMe ,
registered : c.registered ,
contactMethods : c.contactMethods ,
} ) ) ,
} ) ) ,
} ,
} ,
settings : {
settings : {
dexie : comparison.dexieSettings.map ( ( s ) = > ( {
dexie : comparison.dexieSettings.map ( ( s ) = > ( {
id : s.id ,
id : s.id ,
accountDid : s.accountDid ,
type : s . id === MASTER_SETTINGS_KEY ? 'master' : 'account' ,
activeDid : s.activeDid ,
did : s.activeDid || s . accountDid ,
firstName : s.firstName ,
isRegistered : s.isRegistered || false ,
isRegistered : s.isRegistered ,
profileImageUrl : s.profileImageUrl ,
showShortcutBvc : s.showShortcutBvc ,
searchBoxes : s.searchBoxes ,
} ) ) ,
} ) ) ,
sqlite : comparison.sqliteSettings.map ( ( s ) = > ( {
sqlite : comparison.sqliteSettings
. filter ( s = > s . accountDid || s . activeDid )
. map ( ( s ) = > ( {
id : s.id ,
id : s.id ,
accountDid : s.accountDid ,
type : s . id === MASTER_SETTINGS_KEY ? 'master' : 'account' ,
activeDid : s.activeDid ,
did : s.activeDid || s . accountDid ,
firstName : s.firstName ,
isRegistered : s.isRegistered || false ,
isRegistered : s.isRegistered ,
profileImageUrl : s.profileImageUrl ,
showShortcutBvc : s.showShortcutBvc ,
searchBoxes : s.searchBoxes ,
} ) ) ,
} ) ) ,
} ,
} ,
accounts : {
accounts : {
dexie : comparison.dexieAccounts.map ( ( a ) = > ( {
dexie : comparison.dexieAccounts.map ( ( a ) = > ( {
id : a.id ,
id : a.id ,
dateCreated : a.dateCreated ,
derivationPath : a.derivationPath ,
did : a.did ,
did : a.did ,
identity : a.identity ,
dateCreated : a.dateCreated ,
mnemonic : a.mnemonic ,
hasIdentity : ! ! a . identity ,
passkeyCredIdHex : a.passkeyCredIdHex ,
hasMnemonic : ! ! a . mnemonic ,
publicKeyHex : a.publicKeyHex ,
} ) ) ,
} ) ) ,
sqlite : comparison.sqliteAccounts.map ( ( a ) = > ( {
sqlite : comparison.sqliteAccounts
. filter ( a = > a . did )
. map ( ( a ) = > ( {
id : a.id ,
id : a.id ,
dateCreated : a.dateCreated ,
derivationPath : a.derivationPath ,
did : a.did ,
did : a.did ,
identity : a.identity ,
dateCreated : a.dateCreated ,
mnemonic : a.mnemonic ,
hasIdentity : ! ! a . identity ,
passkeyCredIdHex : a.passkeyCredIdHex ,
hasMnemonic : ! ! a . mnemonic ,
publicKeyHex : a.publicKeyHex ,
} ) ) ,
} ) ) ,
} ,
} ,
} ,
} ,
@ -1111,19 +1100,36 @@ export async function migrateSettings(
[ dexieSetting . id ] ,
[ dexieSetting . id ] ,
) ;
) ;
if ( existingResult ? . values ? . length ) {
// Prepare the data object, handling DIDs based on whether this is the master settings
if ( overwriteExisting ) {
const settingData : Record < string , unknown > = { } ;
// Update existing setting with only the specified fields
const updateData : Record < string , unknown > = { } ;
fieldsToMigrate . forEach ( ( field ) = > {
fieldsToMigrate . forEach ( ( field ) = > {
if ( dexieSetting [ field as keyof Settings ] !== undefined ) {
if ( dexieSetting [ field as keyof Settings ] !== undefined ) {
update Data [ field ] = dexieSetting [ field as keyof Settings ] ;
setting Data[ field ] = dexieSetting [ field as keyof Settings ] ;
}
}
} ) ;
} ) ;
if ( Object . keys ( updateData ) . length > 0 ) {
// Handle DIDs based on whether this is the master settings
if ( dexieSetting . id === MASTER_SETTINGS_KEY ) {
// Master settings should only use activeDid
if ( dexieSetting . activeDid ) {
settingData . activeDid = dexieSetting . activeDid ;
}
// Ensure accountDid is null for master settings
settingData . accountDid = null ;
} else {
// Non-master settings should only use accountDid
if ( dexieSetting . accountDid ) {
settingData . accountDid = dexieSetting . accountDid ;
}
// Ensure activeDid is null for non-master settings
settingData . activeDid = null ;
}
if ( existingResult ? . values ? . length ) {
if ( overwriteExisting ) {
// Update existing setting
const { sql , params } = generateUpdateStatement (
const { sql , params } = generateUpdateStatement (
updateData as unknown as Record < string , unknown > ,
settingData ,
"settings" ,
"settings" ,
"id = ?" ,
"id = ?" ,
[ dexieSetting . id ] ,
[ dexieSetting . id ] ,
@ -1133,7 +1139,6 @@ export async function migrateSettings(
logger . info (
logger . info (
` [MigrationService] Updated settings: ${ dexieSetting . id } ` ,
` [MigrationService] Updated settings: ${ dexieSetting . id } ` ,
) ;
) ;
}
} else {
} else {
result . warnings . push (
result . warnings . push (
` Settings ${ dexieSetting . id } already exists, skipping ` ,
` Settings ${ dexieSetting . id } already exists, skipping ` ,
@ -1141,8 +1146,9 @@ export async function migrateSettings(
}
}
} else {
} else {
// Insert new setting
// Insert new setting
settingData . id = dexieSetting . id ;
const { sql , params } = generateInsertStatement (
const { sql , params } = generateInsertStatement (
dexieSetting as unknown as Record < string , unknown > ,
settingData ,
"settings" ,
"settings" ,
) ;
) ;
await platformService . dbExec ( sql , params ) ;
await platformService . dbExec ( sql , params ) ;