Browse Source

feat: add missing settings management functions

- Add getSettingsForAccount() to retrieve complete settings for any account DID
- Add getAccountSpecificSettings() to get account-specific settings without defaults
- Add mergeSettings() for consistent settings merging across SQLite and Dexie
- Update retrieveSettingsForActiveAccount() to use new mergeSettings() function
- Improve error handling and logging for settings operations
- Maintain backward compatibility with existing settings API

This provides better settings management capabilities for account switching,
debugging, and data validation while ensuring consistent behavior across
both SQLite and Dexie storage implementations.
master-settings-upgrade
Matthew Raymer 4 days ago
parent
commit
3881144c62
  1. 151
      src/db/databaseUtil.ts
  2. 37
      src/db/index.ts

151
src/db/databaseUtil.ts

@ -117,34 +117,14 @@ export async function retrieveSettingsForActiveAccount(): Promise<Settings> {
return defaultSettings;
}
// Map and filter settings
// Map settings
const overrideSettings = mapColumnsToValues(
result.columns,
result.values,
)[0] as Settings;
const overrideSettingsFiltered = Object.fromEntries(
Object.entries(overrideSettings).filter(([_, v]) => v !== null),
);
// Merge settings
const settings = { ...defaultSettings, ...overrideSettingsFiltered };
// Handle searchBoxes parsing
if (settings.searchBoxes) {
try {
// @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;
// Use the new mergeSettings function for consistency
return mergeSettings(defaultSettings, overrideSettings);
} catch (error) {
logConsoleAndDb(
`[databaseUtil] Failed to retrieve account settings for ${defaultSettings.activeDid}: ${error}`,
@ -312,3 +292,128 @@ export function mapColumnsToValues(
return obj;
});
}
/**
* Retrieves settings for a specific account by DID
* @param accountDid - The DID of the account to retrieve settings for
* @returns Promise<Settings> Combined settings for the specified account
*/
export async function getSettingsForAccount(accountDid: string): Promise<Settings> {
try {
// Get default settings first
const defaultSettings = await retrieveSettingsForDefaultAccount();
// Get account-specific settings
const platform = PlatformServiceFactory.getInstance();
const result = await platform.dbQuery(
"SELECT * FROM settings WHERE accountDid = ?",
[accountDid],
);
if (!result?.values?.length) {
logConsoleAndDb(
`[databaseUtil] No account-specific settings found for ${accountDid}`,
);
return defaultSettings;
}
// Map and merge settings
const overrideSettings = mapColumnsToValues(
result.columns,
result.values,
)[0] as Settings;
return mergeSettings(defaultSettings, overrideSettings);
} catch (error) {
logConsoleAndDb(
`[databaseUtil] Failed to retrieve settings for account ${accountDid}: ${error}`,
true,
);
// Return default settings on error
return await retrieveSettingsForDefaultAccount();
}
}
/**
* Retrieves only account-specific settings for a given DID (without merging with defaults)
* @param accountDid - The DID of the account to retrieve settings for
* @returns Promise<Settings> Account-specific settings only
*/
export async function getAccountSpecificSettings(accountDid: string): Promise<Settings> {
try {
const platform = PlatformServiceFactory.getInstance();
const result = await platform.dbQuery(
"SELECT * FROM settings WHERE accountDid = ?",
[accountDid],
);
if (!result?.values?.length) {
logConsoleAndDb(
`[databaseUtil] No account-specific settings found for ${accountDid}`,
);
return {};
}
// Map settings
const settings = mapColumnsToValues(
result.columns,
result.values,
)[0] as Settings;
// Handle searchBoxes parsing
if (settings.searchBoxes) {
try {
// @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 ${accountDid}: ${error}`,
true,
);
// Reset to empty array on parse failure
settings.searchBoxes = [];
}
}
return settings;
} catch (error) {
logConsoleAndDb(
`[databaseUtil] Failed to retrieve account-specific settings for ${accountDid}: ${error}`,
true,
);
return {};
}
}
/**
* Merges default settings with account-specific settings using consistent logic
* @param defaultSettings - The default/master settings
* @param accountSettings - The account-specific settings to merge
* @returns Settings - Merged settings with account-specific overrides
*/
export function mergeSettings(defaultSettings: Settings, accountSettings: Settings): Settings {
// Filter out null values from account settings
const accountSettingsFiltered = Object.fromEntries(
Object.entries(accountSettings).filter(([_, v]) => v !== null),
);
// Perform shallow merge (account settings override defaults)
const mergedSettings = { ...defaultSettings, ...accountSettingsFiltered };
// Handle searchBoxes parsing if present
if (mergedSettings.searchBoxes) {
try {
// @ts-expect-error - the searchBoxes field is a string in the DB
mergedSettings.searchBoxes = JSON.parse(mergedSettings.searchBoxes);
} catch (error) {
logConsoleAndDb(
`[databaseUtil] Failed to parse searchBoxes during merge: ${error}`,
true,
);
// Reset to empty array on parse failure
mergedSettings.searchBoxes = [];
}
}
return mergedSettings;
}

37
src/db/index.ts

@ -265,6 +265,43 @@ export async function retrieveSettingsForActiveAccount(): Promise<Settings> {
}
}
/**
* Retrieves settings for a specific account by DID
* @param accountDid - The DID of the account to retrieve settings for
* @returns Promise<Settings> Combined settings for the specified account
*/
export async function getSettingsForAccount(accountDid: string): Promise<Settings> {
const defaultSettings = await retrieveSettingsForDefaultAccount();
const overrideSettings =
(await db.settings
.where("accountDid")
.equals(accountDid)
.first()) || {};
return R.mergeDeepRight(defaultSettings, overrideSettings);
}
/**
* Retrieves only account-specific settings for a given DID (without merging with defaults)
* @param accountDid - The DID of the account to retrieve settings for
* @returns Promise<Settings> Account-specific settings only
*/
export async function getAccountSpecificSettings(accountDid: string): Promise<Settings> {
return (await db.settings
.where("accountDid")
.equals(accountDid)
.first()) || {};
}
/**
* Merges default settings with account-specific settings using consistent logic
* @param defaultSettings - The default/master settings
* @param accountSettings - The account-specific settings to merge
* @returns Settings - Merged settings with account-specific overrides
*/
export function mergeSettings(defaultSettings: Settings, accountSettings: Settings): Settings {
return R.mergeDeepRight(defaultSettings, accountSettings);
}
export async function updateAccountSettings(
accountDid: string,
settingsChanges: Settings,

Loading…
Cancel
Save