diff --git a/doc/secure-storage-implementation.md b/doc/secure-storage-implementation.md index c41f61a6..b8c14c6d 100644 --- a/doc/secure-storage-implementation.md +++ b/doc/secure-storage-implementation.md @@ -131,14 +131,165 @@ async function getAccount(did: string): Promise { ); // Fallback to Dexie if needed - if (USE_DEXIE_DB && !account) { + if (USE_DEXIE_DB) { account = await db.accounts.get(did); } return account; } +``` + +#### A. Modifying Code + +When converting from Dexie.js to SQL-based implementation, follow these patterns: + +1. **Database Access Pattern** + ```typescript + // Before (Dexie) + const result = await db.table.where("field").equals(value).first(); + + // After (SQL) + const platform = PlatformServiceFactory.getInstance(); + let result = await platform.dbQuery( + "SELECT * FROM table WHERE field = ?", + [value] + ); + result = databaseUtil.mapQueryResultToValues(result); + + // Fallback to Dexie if needed + if (USE_DEXIE_DB) { + result = await db.table.where("field").equals(value).first(); + } + ``` + +2. **Update Operations** + ```typescript + // Before (Dexie) + await db.table.where("id").equals(id).modify(changes); + + // After (SQL) + // For settings updates, use the utility methods: + await databaseUtil.updateDefaultSettings(changes); + // OR + await databaseUtil.updateAccountSettings(did, changes); + + // For other tables, use direct SQL: + const platform = PlatformServiceFactory.getInstance(); + await platform.dbExec( + "UPDATE table SET field1 = ?, field2 = ? WHERE id = ?", + [changes.field1, changes.field2, id] + ); + + // Fallback to Dexie if needed + if (USE_DEXIE_DB) { + await db.table.where("id").equals(id).modify(changes); + } + ``` + +3. **Insert Operations** + ```typescript + // Before (Dexie) + await db.table.add(item); + + // After (SQL) + const platform = PlatformServiceFactory.getInstance(); + const columns = Object.keys(item); + const values = Object.values(item); + const placeholders = values.map(() => '?').join(', '); + const sql = `INSERT INTO table (${columns.join(', ')}) VALUES (${placeholders})`; + await platform.dbExec(sql, values); + + // Fallback to Dexie if needed + if (USE_DEXIE_DB) { + await db.table.add(item); + } + ``` + +4. **Delete Operations** + ```typescript + // Before (Dexie) + await db.table.where("id").equals(id).delete(); + + // After (SQL) + const platform = PlatformServiceFactory.getInstance(); + await platform.dbExec("DELETE FROM table WHERE id = ?", [id]); + + // Fallback to Dexie if needed + if (USE_DEXIE_DB) { + await db.table.where("id").equals(id).delete(); + } + ``` + +5. **Result Processing** + ```typescript + // Before (Dexie) + const items = await db.table.toArray(); + + // After (SQL) + const platform = PlatformServiceFactory.getInstance(); + let items = await platform.dbQuery("SELECT * FROM table"); + items = databaseUtil.mapQueryResultToValues(items); + + // Fallback to Dexie if needed + if (USE_DEXIE_DB) { + items = await db.table.toArray(); + } ``` +6. **Using Utility Methods** + +When working with settings or other common operations, use the utility methods in `db/index.ts`: + +```typescript +// Settings operations +await databaseUtil.updateDefaultSettings(settings); +await databaseUtil.updateAccountSettings(did, settings); +const settings = await databaseUtil.retrieveSettingsForDefaultAccount(); +const settings = await databaseUtil.retrieveSettingsForActiveAccount(); + +// Logging operations +await databaseUtil.logToDb(message); +await databaseUtil.logConsoleAndDb(message, showInConsole); +``` + +Key Considerations: +- Always use `databaseUtil.mapQueryResultToValues()` to process SQL query results +- Use utility methods from `db/index.ts` when available instead of direct SQL +- Keep Dexie fallbacks wrapped in `if (USE_DEXIE_DB)` checks +- For queries that return results, use `let` variables to allow Dexie fallback to override +- For updates/inserts/deletes, execute both SQL and Dexie operations when `USE_DEXIE_DB` is true + +Example Migration: +```typescript +// Before (Dexie) +export async function updateSettings(settings: Settings): Promise { + await db.settings.put(settings); +} + +// After (SQL) +export async function updateSettings(settings: Settings): Promise { + const platform = PlatformServiceFactory.getInstance(); + const { sql, params } = generateUpdateStatement( + settings, + "settings", + "id = ?", + [settings.id] + ); + await platform.dbExec(sql, params); +} +``` + +Remember to: +- Create database access code to use the platform service, putting it in front of the Dexie version +- Instead of removing Dexie-specific code, keep it. + + - For creates & updates & deletes, the duplicate code is fine. + + - For queries where we use the results, make the setting from SQL into a 'let' variable, then wrap the Dexie code in a check for USE_DEXIE_DB from app.ts and if +it's true then use that result instead of the SQL code's result. + +- Consider data migration needs, and warn if there are any potential migration problems + ## Success Criteria 1. **Functionality** diff --git a/src/App.vue b/src/App.vue index 5bd5900b..91bce243 100644 --- a/src/App.vue +++ b/src/App.vue @@ -330,8 +330,11 @@