forked from jsnbuchanan/crowd-funder-for-time-pwa
refactor(platforms): create BaseDatabaseService to eliminate code duplication
- Create abstract BaseDatabaseService class with common database operations - Extract 7 duplicate methods from WebPlatformService and CapacitorPlatformService - Ensure consistent database logic across all platform implementations - Fix constructor inheritance issues with proper super() calls - Improve maintainability by centralizing database operations Methods consolidated: - generateInsertStatement - updateDefaultSettings - updateActiveDid - getActiveIdentity - insertNewDidIntoSettings - updateDidSpecificSettings - retrieveSettingsForActiveAccount Architecture: - BaseDatabaseService (abstract base class) - WebPlatformService extends BaseDatabaseService - CapacitorPlatformService extends BaseDatabaseService - ElectronPlatformService extends CapacitorPlatformService Benefits: - Eliminates ~200 lines of duplicate code - Guarantees consistency across platforms - Single point of maintenance for database operations - Prevents platform-specific bugs in database logic Author: Matthew Raymer Timestamp: Wed Oct 22 07:26:38 AM UTC 2025
This commit is contained in:
297
src/services/platforms/BaseDatabaseService.ts
Normal file
297
src/services/platforms/BaseDatabaseService.ts
Normal file
@@ -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>;
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
PlatformCapabilities,
|
||||
} from "../PlatformService";
|
||||
import { logger } from "../../utils/logger";
|
||||
import { BaseDatabaseService } from "./BaseDatabaseService";
|
||||
|
||||
interface QueuedOperation {
|
||||
type: "run" | "query" | "rawQuery";
|
||||
@@ -39,7 +40,10 @@ interface QueuedOperation {
|
||||
* - Platform-specific features
|
||||
* - SQLite database operations
|
||||
*/
|
||||
export class CapacitorPlatformService implements PlatformService {
|
||||
export class CapacitorPlatformService
|
||||
extends BaseDatabaseService
|
||||
implements PlatformService
|
||||
{
|
||||
/** Current camera direction */
|
||||
private currentDirection: CameraDirection = CameraDirection.Rear;
|
||||
|
||||
@@ -52,6 +56,7 @@ export class CapacitorPlatformService implements PlatformService {
|
||||
private isProcessingQueue: boolean = false;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.sqlite = new SQLiteConnection(CapacitorSQLite);
|
||||
}
|
||||
|
||||
@@ -1328,110 +1333,8 @@ export class CapacitorPlatformService implements PlatformService {
|
||||
// --- PWA/Web-only methods (no-op for Capacitor) ---
|
||||
public registerServiceWorker(): void {}
|
||||
|
||||
// Database utility methods
|
||||
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 };
|
||||
}
|
||||
|
||||
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(
|
||||
"[CapacitorPlatformService] 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);
|
||||
}
|
||||
|
||||
async updateActiveDid(did: string): Promise<void> {
|
||||
await this.dbExec(
|
||||
"UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1",
|
||||
[did],
|
||||
);
|
||||
}
|
||||
|
||||
async getActiveIdentity(): Promise<{ activeDid: string }> {
|
||||
const result = await this.dbQuery(
|
||||
"SELECT activeDid FROM active_identity WHERE id = 1",
|
||||
);
|
||||
return {
|
||||
activeDid: (result?.values?.[0]?.[0] as string) || "",
|
||||
};
|
||||
}
|
||||
|
||||
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],
|
||||
);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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],
|
||||
);
|
||||
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, index) => {
|
||||
if (column !== "id") {
|
||||
// Exclude the id column
|
||||
settings[column] = row[index];
|
||||
}
|
||||
});
|
||||
|
||||
return settings;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// Database utility methods - inherited from BaseDatabaseService
|
||||
// generateInsertStatement, updateDefaultSettings, updateActiveDid,
|
||||
// getActiveIdentity, insertNewDidIntoSettings, updateDidSpecificSettings,
|
||||
// retrieveSettingsForActiveAccount are all inherited from BaseDatabaseService
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
} from "../PlatformService";
|
||||
import { logger } from "../../utils/logger";
|
||||
import { QueryExecResult } from "@/interfaces/database";
|
||||
import { BaseDatabaseService } from "./BaseDatabaseService";
|
||||
// Dynamic import of initBackend to prevent worker context errors
|
||||
import type {
|
||||
WorkerRequest,
|
||||
@@ -29,7 +30,10 @@ import type {
|
||||
* Note: File system operations are not available in the web platform
|
||||
* due to browser security restrictions. These methods throw appropriate errors.
|
||||
*/
|
||||
export class WebPlatformService implements PlatformService {
|
||||
export class WebPlatformService
|
||||
extends BaseDatabaseService
|
||||
implements PlatformService
|
||||
{
|
||||
private static instanceCount = 0; // Debug counter
|
||||
private worker: Worker | null = null;
|
||||
private workerReady = false;
|
||||
@@ -46,6 +50,7 @@ export class WebPlatformService implements PlatformService {
|
||||
private readonly messageTimeout = 30000; // 30 seconds
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
WebPlatformService.instanceCount++;
|
||||
|
||||
// Use debug level logging for development mode to reduce console noise
|
||||
@@ -670,116 +675,8 @@ export class WebPlatformService implements PlatformService {
|
||||
// SharedArrayBuffer initialization is handled by initBackend call in initializeWorker
|
||||
}
|
||||
|
||||
// Database utility methods
|
||||
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 };
|
||||
}
|
||||
|
||||
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(
|
||||
"[WebPlatformService] 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);
|
||||
}
|
||||
|
||||
async updateActiveDid(did: string): Promise<void> {
|
||||
await this.dbExec(
|
||||
"INSERT OR REPLACE INTO active_identity (id, activeDid, lastUpdated) VALUES (1, ?, ?)",
|
||||
[did, new Date().toISOString()],
|
||||
);
|
||||
}
|
||||
|
||||
async getActiveIdentity(): Promise<{ activeDid: string }> {
|
||||
const result = await this.dbQuery(
|
||||
"SELECT activeDid FROM active_identity WHERE id = 1",
|
||||
);
|
||||
return {
|
||||
activeDid: (result?.values?.[0]?.[0] as string) || "",
|
||||
};
|
||||
}
|
||||
|
||||
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],
|
||||
);
|
||||
}
|
||||
|
||||
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];
|
||||
// Log update operation for debugging
|
||||
logger.debug(
|
||||
"[WebPlatformService] updateDidSpecificSettings",
|
||||
sql,
|
||||
JSON.stringify(params, null, 2),
|
||||
);
|
||||
await this.dbExec(sql, params);
|
||||
}
|
||||
|
||||
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],
|
||||
);
|
||||
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, index) => {
|
||||
if (column !== "id") {
|
||||
// Exclude the id column
|
||||
settings[column] = row[index];
|
||||
}
|
||||
});
|
||||
|
||||
return settings;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// Database utility methods - inherited from BaseDatabaseService
|
||||
// generateInsertStatement, updateDefaultSettings, updateActiveDid,
|
||||
// getActiveIdentity, insertNewDidIntoSettings, updateDidSpecificSettings,
|
||||
// retrieveSettingsForActiveAccount are all inherited from BaseDatabaseService
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user