|
@ -37,7 +37,20 @@ export async function updateDefaultSettings( |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
export async function updateAccountSettings( |
|
|
export async function insertDidSpecificSettings( |
|
|
|
|
|
did: string, |
|
|
|
|
|
settings: Partial<Settings> = {}, |
|
|
|
|
|
): Promise<boolean> { |
|
|
|
|
|
const platform = PlatformServiceFactory.getInstance(); |
|
|
|
|
|
const { sql, params } = generateInsertStatement( |
|
|
|
|
|
{ ...settings, accountDid: did }, // make sure accountDid is set to the given value
|
|
|
|
|
|
"settings", |
|
|
|
|
|
); |
|
|
|
|
|
const result = await platform.dbExec(sql, params); |
|
|
|
|
|
return result.changes === 1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export async function updateDidSpecificSettings( |
|
|
accountDid: string, |
|
|
accountDid: string, |
|
|
settingsChanges: Settings, |
|
|
settingsChanges: Settings, |
|
|
): Promise<boolean> { |
|
|
): Promise<boolean> { |
|
@ -96,9 +109,6 @@ export async function retrieveSettingsForActiveAccount(): Promise<Settings> { |
|
|
const defaultSettings = await retrieveSettingsForDefaultAccount(); |
|
|
const defaultSettings = await retrieveSettingsForDefaultAccount(); |
|
|
// If no active DID, return defaults
|
|
|
// If no active DID, return defaults
|
|
|
if (!defaultSettings.activeDid) { |
|
|
if (!defaultSettings.activeDid) { |
|
|
logConsoleAndDb( |
|
|
|
|
|
"[databaseUtil] No active DID found, returning default settings", |
|
|
|
|
|
); |
|
|
|
|
|
return defaultSettings; |
|
|
return defaultSettings; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -111,9 +121,7 @@ export async function retrieveSettingsForActiveAccount(): Promise<Settings> { |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
if (!result?.values?.length) { |
|
|
if (!result?.values?.length) { |
|
|
logConsoleAndDb( |
|
|
// we created DID-specific settings when generated or imported, so this shouldn't happen
|
|
|
`[databaseUtil] No account-specific settings found for ${defaultSettings.activeDid}`, |
|
|
|
|
|
); |
|
|
|
|
|
return defaultSettings; |
|
|
return defaultSettings; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -122,6 +130,7 @@ export async function retrieveSettingsForActiveAccount(): Promise<Settings> { |
|
|
result.columns, |
|
|
result.columns, |
|
|
result.values, |
|
|
result.values, |
|
|
)[0] as Settings; |
|
|
)[0] as Settings; |
|
|
|
|
|
|
|
|
const overrideSettingsFiltered = Object.fromEntries( |
|
|
const overrideSettingsFiltered = Object.fromEntries( |
|
|
Object.entries(overrideSettings).filter(([_, v]) => v !== null), |
|
|
Object.entries(overrideSettings).filter(([_, v]) => v !== null), |
|
|
); |
|
|
); |
|
@ -131,17 +140,7 @@ export async function retrieveSettingsForActiveAccount(): Promise<Settings> { |
|
|
|
|
|
|
|
|
// Handle searchBoxes parsing
|
|
|
// Handle searchBoxes parsing
|
|
|
if (settings.searchBoxes) { |
|
|
if (settings.searchBoxes) { |
|
|
try { |
|
|
settings.searchBoxes = parseJsonField(settings.searchBoxes, []); |
|
|
// @ts-expect-error - the searchBoxes field is a string in the DB
|
|
|
|
|
|
settings.searchBoxes = JSON.parse(settings.searchBoxes); |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
logConsoleAndDb( |
|
|
|
|
|
`[databaseUtil] Failed to parse searchBoxes for ${defaultSettings.activeDid}: ${error}`, |
|
|
|
|
|
true, |
|
|
|
|
|
); |
|
|
|
|
|
// Reset to empty array on parse failure
|
|
|
|
|
|
settings.searchBoxes = []; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return settings; |
|
|
return settings; |
|
@ -241,6 +240,7 @@ export function generateInsertStatement( |
|
|
const values = Object.values(model).filter((value) => value !== undefined); |
|
|
const values = Object.values(model).filter((value) => value !== undefined); |
|
|
const placeholders = values.map(() => "?").join(", "); |
|
|
const placeholders = values.map(() => "?").join(", "); |
|
|
const insertSql = `INSERT INTO ${tableName} (${columns.join(", ")}) VALUES (${placeholders})`; |
|
|
const insertSql = `INSERT INTO ${tableName} (${columns.join(", ")}) VALUES (${placeholders})`; |
|
|
|
|
|
|
|
|
return { |
|
|
return { |
|
|
sql: insertSql, |
|
|
sql: insertSql, |
|
|
params: values, |
|
|
params: values, |
|
@ -312,3 +312,115 @@ export function mapColumnsToValues( |
|
|
return obj; |
|
|
return obj; |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Debug function to inspect raw settings data in the database |
|
|
|
|
|
* This helps diagnose issues with data corruption or malformed JSON |
|
|
|
|
|
* @param did Optional DID to inspect specific account settings |
|
|
|
|
|
* @author Matthew Raymer |
|
|
|
|
|
*/ |
|
|
|
|
|
export async function debugSettingsData(did?: string): Promise<void> { |
|
|
|
|
|
try { |
|
|
|
|
|
const platform = PlatformServiceFactory.getInstance(); |
|
|
|
|
|
|
|
|
|
|
|
// Get all settings records
|
|
|
|
|
|
const allSettings = await platform.dbQuery("SELECT * FROM settings"); |
|
|
|
|
|
|
|
|
|
|
|
logConsoleAndDb( |
|
|
|
|
|
`[DEBUG] Total settings records: ${allSettings?.values?.length || 0}`, |
|
|
|
|
|
false, |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
if (allSettings?.values?.length) { |
|
|
|
|
|
allSettings.values.forEach((row, index) => { |
|
|
|
|
|
const settings = mapColumnsToValues(allSettings.columns, [row])[0]; |
|
|
|
|
|
logConsoleAndDb(`[DEBUG] Settings record ${index + 1}:`, false); |
|
|
|
|
|
logConsoleAndDb(`[DEBUG] - ID: ${settings.id}`, false); |
|
|
|
|
|
logConsoleAndDb(`[DEBUG] - accountDid: ${settings.accountDid}`, false); |
|
|
|
|
|
logConsoleAndDb(`[DEBUG] - activeDid: ${settings.activeDid}`, false); |
|
|
|
|
|
|
|
|
|
|
|
if (settings.searchBoxes) { |
|
|
|
|
|
logConsoleAndDb( |
|
|
|
|
|
`[DEBUG] - searchBoxes type: ${typeof settings.searchBoxes}`, |
|
|
|
|
|
false, |
|
|
|
|
|
); |
|
|
|
|
|
logConsoleAndDb( |
|
|
|
|
|
`[DEBUG] - searchBoxes value: ${String(settings.searchBoxes)}`, |
|
|
|
|
|
false, |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
// Try to parse it
|
|
|
|
|
|
try { |
|
|
|
|
|
const parsed = JSON.parse(String(settings.searchBoxes)); |
|
|
|
|
|
logConsoleAndDb( |
|
|
|
|
|
`[DEBUG] - searchBoxes parsed successfully: ${JSON.stringify(parsed)}`, |
|
|
|
|
|
false, |
|
|
|
|
|
); |
|
|
|
|
|
} catch (parseError) { |
|
|
|
|
|
logConsoleAndDb( |
|
|
|
|
|
`[DEBUG] - searchBoxes parse error: ${parseError}`, |
|
|
|
|
|
true, |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
logConsoleAndDb( |
|
|
|
|
|
`[DEBUG] - Full record: ${JSON.stringify(settings, null, 2)}`, |
|
|
|
|
|
false, |
|
|
|
|
|
); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// If specific DID provided, also check accounts table
|
|
|
|
|
|
if (did) { |
|
|
|
|
|
const account = await platform.dbQuery( |
|
|
|
|
|
"SELECT * FROM accounts WHERE did = ?", |
|
|
|
|
|
[did], |
|
|
|
|
|
); |
|
|
|
|
|
logConsoleAndDb( |
|
|
|
|
|
`[DEBUG] Account for ${did}: ${JSON.stringify(account, null, 2)}`, |
|
|
|
|
|
false, |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
logConsoleAndDb(`[DEBUG] Error inspecting settings data: ${error}`, true); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Platform-agnostic JSON parsing utility |
|
|
|
|
|
* Handles different SQLite implementations: |
|
|
|
|
|
* - Web SQLite (wa-sqlite/absurd-sql): Auto-parses JSON strings to objects |
|
|
|
|
|
* - Capacitor SQLite: Returns raw strings that need manual parsing |
|
|
|
|
|
* |
|
|
|
|
|
* @param value The value to parse (could be string or already parsed object) |
|
|
|
|
|
* @param defaultValue Default value if parsing fails |
|
|
|
|
|
* @returns Parsed object or default value |
|
|
|
|
|
* @author Matthew Raymer |
|
|
|
|
|
*/ |
|
|
|
|
|
export function parseJsonField<T>(value: unknown, defaultValue: T): T { |
|
|
|
|
|
try { |
|
|
|
|
|
// If already an object (web SQLite auto-parsed), return as-is
|
|
|
|
|
|
if (typeof value === "object" && value !== null) { |
|
|
|
|
|
return value as T; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// If it's a string (Capacitor SQLite or fallback), parse it
|
|
|
|
|
|
if (typeof value === "string") { |
|
|
|
|
|
return JSON.parse(value) as T; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// If it's null/undefined, return default
|
|
|
|
|
|
if (value === null || value === undefined) { |
|
|
|
|
|
return defaultValue; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return defaultValue; |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
logConsoleAndDb( |
|
|
|
|
|
`[databaseUtil] Failed to parse JSON field: ${error}`, |
|
|
|
|
|
true, |
|
|
|
|
|
); |
|
|
|
|
|
return defaultValue; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|