You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

197 lines
6.3 KiB

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.`,
);
}
}
}
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;
}
}
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 : {};
const overrideSettingsFiltered = Object.fromEntries(Object.entries(overrideSettings).filter(([_, v]) => v !== null));
return { ...defaultSettings, ...overrideSettingsFiltered };
}
}
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;
});
}