8 changed files with 468 additions and 28 deletions
@ -0,0 +1,196 @@ |
|||
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; |
|||
import { MASTER_SETTINGS_KEY, Settings } from "./tables/settings"; |
|||
import { logger } from "@/utils/logger"; |
|||
import { DEFAULT_ENDORSER_API_SERVER } from "@/constants/app"; |
|||
|
|||
export async function updateDefaultSettings( |
|||
settingsChanges: Settings, |
|||
): Promise<boolean> { |
|||
delete settingsChanges.accountDid; // just in case
|
|||
// ensure there is no "id" that would override the key
|
|||
delete settingsChanges.id; |
|||
try { |
|||
const platformService = PlatformServiceFactory.getInstance(); |
|||
const { sql, params } = generateUpdateStatement(settingsChanges, "settings", "id = ?", [MASTER_SETTINGS_KEY]); |
|||
const result = await platformService.dbExec(sql, params); |
|||
return result.changes === 1; |
|||
} catch (error) { |
|||
logger.error("Error updating default settings:", error); |
|||
if (error instanceof Error) { |
|||
throw error; // Re-throw if it's already an Error with a message
|
|||
} else { |
|||
throw new Error( |
|||
`Failed to update settings. We recommend you try again or restart the app.`, |
|||
); |
|||
} |
|||
} |
|||
} |
|||
|
|||
const DEFAULT_SETTINGS: Settings = { |
|||
id: MASTER_SETTINGS_KEY, |
|||
activeDid: undefined, |
|||
apiServer: DEFAULT_ENDORSER_API_SERVER, |
|||
}; |
|||
|
|||
// retrieves default settings
|
|||
export async function retrieveSettingsForDefaultAccount(): Promise<Settings> { |
|||
const platform = PlatformServiceFactory.getInstance(); |
|||
const result = await platform.dbQuery("SELECT * FROM settings WHERE id = ?", MASTER_SETTINGS_KEY) |
|||
if (!result) { |
|||
return DEFAULT_SETTINGS; |
|||
} else { |
|||
return mapColumnsToValues(result.columns, result.values)[0] as Settings; |
|||
} |
|||
} |
|||
|
|||
export async function retrieveSettingsForActiveAccount(): Promise<Settings> { |
|||
const defaultSettings = await retrieveSettingsForDefaultAccount(); |
|||
if (!defaultSettings.activeDid) { |
|||
return defaultSettings; |
|||
} else { |
|||
const platform = PlatformServiceFactory.getInstance(); |
|||
const result = await platform.dbQuery( |
|||
"SELECT * FROM settings WHERE accountDid = ?", |
|||
[defaultSettings.activeDid] |
|||
); |
|||
const overrideSettings = result ? mapColumnsToValues(result.columns, result.values)[0] as Settings : {}; |
|||
return { ...defaultSettings, ...overrideSettings }; |
|||
} |
|||
} |
|||
|
|||
export async function updateAccountSettings( |
|||
accountDid: string, |
|||
settingsChanges: Settings, |
|||
): Promise<boolean> { |
|||
settingsChanges.accountDid = accountDid; |
|||
delete settingsChanges.id; // key off account, not ID
|
|||
|
|||
const platform = PlatformServiceFactory.getInstance(); |
|||
|
|||
// First try to update existing record
|
|||
const { sql: updateSql, params: updateParams } = generateUpdateStatement( |
|||
settingsChanges, |
|||
"settings", |
|||
"accountDid = ?", |
|||
[accountDid] |
|||
); |
|||
|
|||
const updateResult = await platform.dbExec(updateSql, updateParams); |
|||
|
|||
// If no record was updated, insert a new one
|
|||
if (updateResult.changes === 1) { |
|||
return true; |
|||
} else { |
|||
const columns = Object.keys(settingsChanges); |
|||
const values = Object.values(settingsChanges); |
|||
const placeholders = values.map(() => '?').join(', '); |
|||
|
|||
const insertSql = `INSERT INTO settings (${columns.join(', ')}) VALUES (${placeholders})`; |
|||
const result = await platform.dbExec(insertSql, values); |
|||
|
|||
return result.changes === 1; |
|||
} |
|||
} |
|||
|
|||
export async function logToDb(message: string): Promise<void> { |
|||
const platform = PlatformServiceFactory.getInstance(); |
|||
const todayKey = new Date().toDateString(); |
|||
|
|||
// Check if we have any logs for today
|
|||
const result = await platform.dbQuery( |
|||
"SELECT message FROM logs WHERE date = ?", |
|||
[todayKey] |
|||
); |
|||
|
|||
if (!result || result.values.length === 0) { |
|||
// If no logs for today, clear all previous logs
|
|||
await platform.dbExec("DELETE FROM logs"); |
|||
|
|||
// Insert new log
|
|||
const fullMessage = `${new Date().toISOString()} ${message}`; |
|||
await platform.dbExec( |
|||
"INSERT INTO logs (date, message) VALUES (?, ?)", |
|||
[todayKey, fullMessage] |
|||
); |
|||
} else { |
|||
// Append to existing log
|
|||
const prevMessages = result.values[0][0] as string; |
|||
const fullMessage = `${prevMessages}\n${new Date().toISOString()} ${message}`; |
|||
|
|||
await platform.dbExec( |
|||
"UPDATE logs SET message = ? WHERE date = ?", |
|||
[fullMessage, todayKey] |
|||
); |
|||
} |
|||
} |
|||
|
|||
// similar method is in the sw_scripts/additional-scripts.js file
|
|||
export async function logConsoleAndDb( |
|||
message: string, |
|||
isError = false, |
|||
): Promise<void> { |
|||
if (isError) { |
|||
logger.error(`${new Date().toISOString()} ${message}`); |
|||
} else { |
|||
logger.log(`${new Date().toISOString()} ${message}`); |
|||
} |
|||
await logToDb(message); |
|||
} |
|||
|
|||
/** |
|||
* Generates an SQL UPDATE statement and parameters from a model object. |
|||
* @param model The model object containing fields to update |
|||
* @param tableName The name of the table to update |
|||
* @param whereClause The WHERE clause for the update (e.g. "id = ?") |
|||
* @param whereParams Parameters for the WHERE clause |
|||
* @returns Object containing the SQL statement and parameters array |
|||
*/ |
|||
function generateUpdateStatement( |
|||
model: Record<string, any>, |
|||
tableName: string, |
|||
whereClause: string, |
|||
whereParams: any[] = [] |
|||
): { sql: string; params: any[] } { |
|||
// Filter out undefined/null values and create SET clause
|
|||
const setClauses: string[] = []; |
|||
const params: any[] = []; |
|||
|
|||
Object.entries(model).forEach(([key, value]) => { |
|||
if (value !== undefined) { |
|||
setClauses.push(`${key} = ?`); |
|||
params.push(value); |
|||
} |
|||
}); |
|||
|
|||
if (setClauses.length === 0) { |
|||
throw new Error('No valid fields to update'); |
|||
} |
|||
|
|||
const sql = `UPDATE ${tableName} SET ${setClauses.join(', ')} WHERE ${whereClause}`; |
|||
|
|||
return { |
|||
sql, |
|||
params: [...params, ...whereParams] |
|||
}; |
|||
} |
|||
|
|||
/** |
|||
* Maps an array of column names to an array of value arrays, creating objects where each column name |
|||
* is mapped to its corresponding value. |
|||
* @param columns Array of column names to use as object keys |
|||
* @param values Array of value arrays, where each inner array corresponds to one row of data |
|||
* @returns Array of objects where each object maps column names to their corresponding values |
|||
*/ |
|||
export function mapColumnsToValues( |
|||
columns: string[], |
|||
values: any[][] |
|||
): Record<string, any>[] { |
|||
return values.map(row => { |
|||
const obj: Record<string, any> = {}; |
|||
columns.forEach((column, index) => { |
|||
obj[column] = row[index]; |
|||
}); |
|||
return obj; |
|||
}); |
|||
} |
|||
|
Loading…
Reference in new issue