Compare commits
23 Commits
9628d5c8c6
...
d7db7731cf
| Author | SHA1 | Date |
|---|---|---|
|
|
d7db7731cf | 4 days ago |
|
|
4d9435f257 | 1 week ago |
|
|
a353ed3c3e | 1 week ago |
|
|
e6cc058935 | 2 weeks ago |
|
|
37cff0083f | 2 weeks ago |
|
|
2049c9b6ec | 2 weeks ago |
|
|
f186e129db | 2 weeks ago |
|
|
455dfadb92 | 2 weeks ago |
|
|
637fc10e64 | 2 weeks ago |
|
|
37d4dcc1a8 | 2 weeks ago |
|
|
c369c76c1a | 2 weeks ago |
|
|
86caf793aa | 2 weeks ago |
|
|
499fbd2cb3 | 2 weeks ago |
|
|
a4a9293bc2 | 2 weeks ago |
|
|
9ac9f1d4a3 | 2 weeks ago |
|
|
fface30123 | 4 weeks ago |
|
|
97b382451a | 1 month ago |
|
|
7fd2c4e0c7 | 1 month ago |
|
|
20322789a2 | 1 month ago |
|
|
666bed0efd | 1 month ago |
|
|
7432525f4c | 1 month ago |
|
|
530cddfab0 | 1 month ago |
|
|
5340c00ae2 | 1 month ago |
17 changed files with 792 additions and 374 deletions
@ -1,37 +1,6 @@ |
|||
export type { |
|||
// From common.ts
|
|||
CreateAndSubmitClaimResult, |
|||
GenericCredWrapper, |
|||
GenericVerifiableCredential, |
|||
KeyMeta, |
|||
// Exclude types that are also exported from other files
|
|||
// GiveVerifiableCredential,
|
|||
// OfferVerifiableCredential,
|
|||
// RegisterVerifiableCredential,
|
|||
// PlanSummaryRecord,
|
|||
// UserInfo,
|
|||
} from "./common"; |
|||
|
|||
export type { |
|||
// From claims.ts
|
|||
GiveActionClaim, |
|||
OfferClaim, |
|||
RegisterActionClaim, |
|||
} from "./claims"; |
|||
|
|||
export type { |
|||
// From records.ts
|
|||
PlanSummaryRecord, |
|||
} from "./records"; |
|||
|
|||
export type { |
|||
// From user.ts
|
|||
UserInfo, |
|||
MemberData, |
|||
} from "./user"; |
|||
|
|||
export * from "./limits"; |
|||
export * from "./deepLinks"; |
|||
export * from "./common"; |
|||
export * from "./claims"; |
|||
export * from "./claims-result"; |
|||
export * from "./common"; |
|||
export * from "./deepLinks"; |
|||
export * from "./limits"; |
|||
export * from "./records"; |
|||
|
|||
@ -0,0 +1,297 @@ |
|||
/** |
|||
* @fileoverview Base Database Service for Platform Services |
|||
* @author Matthew Raymer |
|||
* |
|||
* This abstract base class provides common database operations that are |
|||
* identical across all platform implementations. It eliminates code |
|||
* duplication and ensures consistency in database operations. |
|||
* |
|||
* Key Features: |
|||
* - Common database utility methods |
|||
* - Consistent settings management |
|||
* - Active identity management |
|||
* - Abstract methods for platform-specific database operations |
|||
* |
|||
* Architecture: |
|||
* - Abstract base class with common implementations |
|||
* - Platform services extend this class |
|||
* - Platform-specific database operations remain abstract |
|||
* |
|||
* @since 1.1.1-beta |
|||
*/ |
|||
|
|||
import { logger } from "../../utils/logger"; |
|||
import { QueryExecResult } from "@/interfaces/database"; |
|||
|
|||
/** |
|||
* Abstract base class for platform-specific database services. |
|||
* |
|||
* This class provides common database operations that are identical |
|||
* across all platform implementations (Web, Capacitor, Electron). |
|||
* Platform-specific services extend this class and implement the |
|||
* abstract database operation methods. |
|||
* |
|||
* Common Operations: |
|||
* - Settings management (update, retrieve, insert) |
|||
* - Active identity management |
|||
* - Database utility methods |
|||
* |
|||
* @abstract |
|||
* @example |
|||
* ```typescript
|
|||
* export class WebPlatformService extends BaseDatabaseService { |
|||
* async dbQuery(sql: string, params?: unknown[]): Promise<QueryExecResult> { |
|||
* // Web-specific implementation
|
|||
* } |
|||
* } |
|||
* ``` |
|||
*/ |
|||
export abstract class BaseDatabaseService { |
|||
/** |
|||
* Generate an INSERT statement for a model object. |
|||
* |
|||
* Creates a parameterized INSERT statement with placeholders for |
|||
* all properties in the model object. This ensures safe SQL |
|||
* execution and prevents SQL injection. |
|||
* |
|||
* @param model - Object containing the data to insert |
|||
* @param tableName - Name of the target table |
|||
* @returns Object containing the SQL statement and parameters |
|||
* |
|||
* @example |
|||
* ```typescript
|
|||
* const { sql, params } = this.generateInsertStatement( |
|||
* { name: 'John', age: 30 }, |
|||
* 'users' |
|||
* ); |
|||
* // sql: "INSERT INTO users (name, age) VALUES (?, ?)"
|
|||
* // params: ['John', 30]
|
|||
* ``` |
|||
*/ |
|||
generateInsertStatement( |
|||
model: Record<string, unknown>, |
|||
tableName: string, |
|||
): { sql: string; params: unknown[] } { |
|||
const keys = Object.keys(model); |
|||
const placeholders = keys.map(() => "?").join(", "); |
|||
const sql = `INSERT INTO ${tableName} (${keys.join(", ")}) VALUES (${placeholders})`; |
|||
const params = keys.map((key) => model[key]); |
|||
return { sql, params }; |
|||
} |
|||
|
|||
/** |
|||
* Update default settings for the currently active account. |
|||
* |
|||
* Retrieves the active DID from the active_identity table and updates |
|||
* the corresponding settings record. This ensures settings are always |
|||
* updated for the correct account. |
|||
* |
|||
* @param settings - Object containing the settings to update |
|||
* @returns Promise that resolves when settings are updated |
|||
* |
|||
* @throws {Error} If no active DID is found or database operation fails |
|||
* |
|||
* @example |
|||
* ```typescript
|
|||
* await this.updateDefaultSettings({ |
|||
* theme: 'dark', |
|||
* notifications: true |
|||
* }); |
|||
* ``` |
|||
*/ |
|||
async updateDefaultSettings( |
|||
settings: Record<string, unknown>, |
|||
): Promise<void> { |
|||
// Get current active DID and update that identity's settings
|
|||
const activeIdentity = await this.getActiveIdentity(); |
|||
const activeDid = activeIdentity.activeDid; |
|||
|
|||
if (!activeDid) { |
|||
logger.warn( |
|||
"[BaseDatabaseService] No active DID found, cannot update default settings", |
|||
); |
|||
return; |
|||
} |
|||
|
|||
const keys = Object.keys(settings); |
|||
const setClause = keys.map((key) => `${key} = ?`).join(", "); |
|||
const sql = `UPDATE settings SET ${setClause} WHERE accountDid = ?`; |
|||
const params = [...keys.map((key) => settings[key]), activeDid]; |
|||
await this.dbExec(sql, params); |
|||
} |
|||
|
|||
/** |
|||
* Update the active DID in the active_identity table. |
|||
* |
|||
* Sets the active DID and updates the lastUpdated timestamp. |
|||
* This is used when switching between different accounts/identities. |
|||
* |
|||
* @param did - The DID to set as active |
|||
* @returns Promise that resolves when the update is complete |
|||
* |
|||
* @example |
|||
* ```typescript
|
|||
* await this.updateActiveDid('did:example:123'); |
|||
* ``` |
|||
*/ |
|||
async updateActiveDid(did: string): Promise<void> { |
|||
await this.dbExec( |
|||
"UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1", |
|||
[did], |
|||
); |
|||
} |
|||
|
|||
/** |
|||
* Get the currently active DID from the active_identity table. |
|||
* |
|||
* Retrieves the active DID that represents the currently selected |
|||
* account/identity. This is used throughout the application to |
|||
* ensure operations are performed on the correct account. |
|||
* |
|||
* @returns Promise resolving to object containing the active DID |
|||
* |
|||
* @example |
|||
* ```typescript
|
|||
* const { activeDid } = await this.getActiveIdentity(); |
|||
* console.log('Current active DID:', activeDid); |
|||
* ``` |
|||
*/ |
|||
async getActiveIdentity(): Promise<{ activeDid: string }> { |
|||
const result = (await this.dbQuery( |
|||
"SELECT activeDid FROM active_identity WHERE id = 1", |
|||
)) as QueryExecResult; |
|||
return { |
|||
activeDid: (result?.values?.[0]?.[0] as string) || "", |
|||
}; |
|||
} |
|||
|
|||
/** |
|||
* Insert a new DID into the settings table with default values. |
|||
* |
|||
* Creates a new settings record for a DID with default configuration |
|||
* values. Uses INSERT OR REPLACE to handle cases where settings |
|||
* already exist for the DID. |
|||
* |
|||
* @param did - The DID to create settings for |
|||
* @returns Promise that resolves when settings are created |
|||
* |
|||
* @example |
|||
* ```typescript
|
|||
* await this.insertNewDidIntoSettings('did:example:123'); |
|||
* ``` |
|||
*/ |
|||
async insertNewDidIntoSettings(did: string): Promise<void> { |
|||
// Import constants dynamically to avoid circular dependencies
|
|||
const { DEFAULT_ENDORSER_API_SERVER, DEFAULT_PARTNER_API_SERVER } = |
|||
await import("@/constants/app"); |
|||
|
|||
// Use INSERT OR REPLACE to handle case where settings already exist for this DID
|
|||
// This prevents duplicate accountDid entries and ensures data integrity
|
|||
await this.dbExec( |
|||
"INSERT OR REPLACE INTO settings (accountDid, finishedOnboarding, apiServer, partnerApiServer) VALUES (?, ?, ?, ?)", |
|||
[did, false, DEFAULT_ENDORSER_API_SERVER, DEFAULT_PARTNER_API_SERVER], |
|||
); |
|||
} |
|||
|
|||
/** |
|||
* Update settings for a specific DID. |
|||
* |
|||
* Updates settings for a particular DID rather than the active one. |
|||
* This is useful for bulk operations or when managing multiple accounts. |
|||
* |
|||
* @param did - The DID to update settings for |
|||
* @param settings - Object containing the settings to update |
|||
* @returns Promise that resolves when settings are updated |
|||
* |
|||
* @example |
|||
* ```typescript
|
|||
* await this.updateDidSpecificSettings('did:example:123', { |
|||
* theme: 'light', |
|||
* notifications: false |
|||
* }); |
|||
* ``` |
|||
*/ |
|||
async updateDidSpecificSettings( |
|||
did: string, |
|||
settings: Record<string, unknown>, |
|||
): Promise<void> { |
|||
const keys = Object.keys(settings); |
|||
const setClause = keys.map((key) => `${key} = ?`).join(", "); |
|||
const sql = `UPDATE settings SET ${setClause} WHERE accountDid = ?`; |
|||
const params = [...keys.map((key) => settings[key]), did]; |
|||
await this.dbExec(sql, params); |
|||
} |
|||
|
|||
/** |
|||
* Retrieve settings for the currently active account. |
|||
* |
|||
* Gets the active DID and retrieves all settings for that account. |
|||
* Excludes the 'id' column from the returned settings object. |
|||
* |
|||
* @returns Promise resolving to settings object or null if no active DID |
|||
* |
|||
* @example |
|||
* ```typescript
|
|||
* const settings = await this.retrieveSettingsForActiveAccount(); |
|||
* if (settings) { |
|||
* console.log('Theme:', settings.theme); |
|||
* console.log('Notifications:', settings.notifications); |
|||
* } |
|||
* ``` |
|||
*/ |
|||
async retrieveSettingsForActiveAccount(): Promise<Record< |
|||
string, |
|||
unknown |
|||
> | null> { |
|||
// Get current active DID from active_identity table
|
|||
const activeIdentity = await this.getActiveIdentity(); |
|||
const activeDid = activeIdentity.activeDid; |
|||
|
|||
if (!activeDid) { |
|||
return null; |
|||
} |
|||
|
|||
const result = (await this.dbQuery( |
|||
"SELECT * FROM settings WHERE accountDid = ?", |
|||
[activeDid], |
|||
)) as QueryExecResult; |
|||
if (result?.values?.[0]) { |
|||
// Convert the row to an object
|
|||
const row = result.values[0]; |
|||
const columns = result.columns || []; |
|||
const settings: Record<string, unknown> = {}; |
|||
|
|||
columns.forEach((column: string, index: number) => { |
|||
if (column !== "id") { |
|||
// Exclude the id column
|
|||
settings[column] = row[index]; |
|||
} |
|||
}); |
|||
|
|||
return settings; |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
// Abstract methods that must be implemented by platform-specific services
|
|||
|
|||
/** |
|||
* Execute a database query (SELECT operations). |
|||
* |
|||
* @abstract |
|||
* @param sql - SQL query string |
|||
* @param params - Optional parameters for prepared statements |
|||
* @returns Promise resolving to query results |
|||
*/ |
|||
abstract dbQuery(sql: string, params?: unknown[]): Promise<unknown>; |
|||
|
|||
/** |
|||
* Execute a database statement (INSERT, UPDATE, DELETE operations). |
|||
* |
|||
* @abstract |
|||
* @param sql - SQL statement string |
|||
* @param params - Optional parameters for prepared statements |
|||
* @returns Promise resolving to execution results |
|||
*/ |
|||
abstract dbExec(sql: string, params?: unknown[]): Promise<unknown>; |
|||
} |
|||
Loading…
Reference in new issue