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.
		
		
		
		
		
			
		
			
				
					
					
						
							2163 lines
						
					
					
						
							69 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							2163 lines
						
					
					
						
							69 KiB
						
					
					
				
								/**
							 | 
						|
								 * Enhanced PlatformService Mixin with ultra-concise database operations and caching
							 | 
						|
								 *
							 | 
						|
								 * Provides cached platform service access and utility methods for Vue components.
							 | 
						|
								 * Eliminates repetitive PlatformServiceFactory.getInstance() calls across components.
							 | 
						|
								 *
							 | 
						|
								 * Features:
							 | 
						|
								 * - Cached platform service instance (created once per component)
							 | 
						|
								 * - Enhanced database utility methods with comprehensive error handling
							 | 
						|
								 * - Ultra-concise database interaction methods ($db, $exec, $one, etc.)
							 | 
						|
								 * - Automatic query result mapping and JSON field parsing
							 | 
						|
								 * - Specialized shortcuts for common queries (contacts, settings)
							 | 
						|
								 * - Transaction support with automatic rollback on errors
							 | 
						|
								 * - Mixin pattern for easy integration with existing class components
							 | 
						|
								 * - Enhanced utility methods for common patterns
							 | 
						|
								 * - Robust error handling and logging
							 | 
						|
								 * - Ultra-concise database interaction methods
							 | 
						|
								 * - Smart caching layer with TTL for performance optimization
							 | 
						|
								 * - Settings shortcuts for ultra-frequent update patterns
							 | 
						|
								 * - High-level entity operations (insertContact, updateContact, etc.)
							 | 
						|
								 * - Result mapping helpers to eliminate verbose row processing
							 | 
						|
								 *
							 | 
						|
								 * Benefits:
							 | 
						|
								 * - Eliminates repeated PlatformServiceFactory.getInstance() calls
							 | 
						|
								 * - Provides consistent error handling across components
							 | 
						|
								 * - Reduces boilerplate database code by up to 80%
							 | 
						|
								 * - Maintains type safety with TypeScript
							 | 
						|
								 * - Includes common database utility patterns
							 | 
						|
								 * - Enhanced error handling and logging
							 | 
						|
								 * - Ultra-concise method names for frequent operations
							 | 
						|
								 * - Automatic caching for settings and contacts (massive performance gain)
							 | 
						|
								 * - Settings update shortcuts reduce 90% of update boilerplate
							 | 
						|
								 * - Entity operations eliminate verbose SQL INSERT/UPDATE patterns
							 | 
						|
								 * - Result mapping helpers reduce row processing boilerplate by 75%
							 | 
						|
								 *
							 | 
						|
								 * @author Matthew Raymer
							 | 
						|
								 * @version 4.1.0
							 | 
						|
								 * @since 2025-07-02
							 | 
						|
								 * @updated 2025-06-25 - Added high-level entity operations for code reduction
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
							 | 
						|
								import type {
							 | 
						|
								  PlatformService,
							 | 
						|
								  PlatformCapabilities,
							 | 
						|
								} from "@/services/PlatformService";
							 | 
						|
								import {
							 | 
						|
								  type Settings,
							 | 
						|
								  type SettingsWithJsonStrings,
							 | 
						|
								} from "@/db/tables/settings";
							 | 
						|
								import { logger } from "@/utils/logger";
							 | 
						|
								import { Contact, ContactMaybeWithJsonStrings } from "@/db/tables/contacts";
							 | 
						|
								import { Account } from "@/db/tables/accounts";
							 | 
						|
								import { Temp } from "@/db/tables/temp";
							 | 
						|
								import {
							 | 
						|
								  QueryExecResult,
							 | 
						|
								  DatabaseExecResult,
							 | 
						|
								  SqlValue,
							 | 
						|
								} from "@/interfaces/database";
							 | 
						|
								import {
							 | 
						|
								  generateInsertStatement,
							 | 
						|
								  generateUpdateStatement,
							 | 
						|
								} from "@/utils/sqlHelpers";
							 | 
						|
								
							 | 
						|
								// =================================================
							 | 
						|
								// TYPESCRIPT INTERFACES
							 | 
						|
								// =================================================
							 | 
						|
								
							 | 
						|
								// /**
							 | 
						|
								//  * Cache entry interface for storing data with TTL
							 | 
						|
								//  */
							 | 
						|
								// interface CacheEntry<T> {
							 | 
						|
								//   data: T;
							 | 
						|
								//   timestamp: number;
							 | 
						|
								//   ttl: number; // milliseconds
							 | 
						|
								// }
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Vue component interface that uses the PlatformServiceMixin
							 | 
						|
								 * This provides proper typing for the cache system
							 | 
						|
								 */
							 | 
						|
								interface VueComponentWithMixin {
							 | 
						|
								  _platformService: PlatformService | null;
							 | 
						|
								  $options: { name?: string };
							 | 
						|
								  activeDid?: string;
							 | 
						|
								  platformService(): PlatformService;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// /**
							 | 
						|
								//  * Global cache store for mixin instances
							 | 
						|
								//  * Uses WeakMap to avoid memory leaks when components are destroyed
							 | 
						|
								//  */
							 | 
						|
								// const componentCaches = new WeakMap<
							 | 
						|
								//   VueComponentWithMixin,
							 | 
						|
								//   Map<string, CacheEntry<unknown>>
							 | 
						|
								// >();
							 | 
						|
								//
							 | 
						|
								// /**
							 | 
						|
								//  * Cache configuration constants
							 | 
						|
								//  */
							 | 
						|
								// const CACHE_DEFAULTS = {
							 | 
						|
								//   default: 15000, // 15 seconds default TTL
							 | 
						|
								// } as const;
							 | 
						|
								
							 | 
						|
								const _memoryLogs: string[] = [];
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Enhanced mixin that provides cached platform service access and utility methods
							 | 
						|
								 * with smart caching layer for ultimate performance optimization
							 | 
						|
								 */
							 | 
						|
								export const PlatformServiceMixin = {
							 | 
						|
								  data() {
							 | 
						|
								    return {
							 | 
						|
								      // Cache the platform service instance at component level
							 | 
						|
								      _platformService: null as PlatformService | null,
							 | 
						|
								      // Track the current activeDid for change detection
							 | 
						|
								      _currentActiveDid: null as string | null,
							 | 
						|
								    };
							 | 
						|
								  },
							 | 
						|
								
							 | 
						|
								  computed: {
							 | 
						|
								    /**
							 | 
						|
								     * Cached platform service instance
							 | 
						|
								     * Created once per component lifecycle
							 | 
						|
								     */
							 | 
						|
								    platformService(): PlatformService {
							 | 
						|
								      if (!(this as unknown as VueComponentWithMixin)._platformService) {
							 | 
						|
								        (this as unknown as VueComponentWithMixin)._platformService =
							 | 
						|
								          PlatformServiceFactory.getInstance();
							 | 
						|
								      }
							 | 
						|
								      return (this as unknown as VueComponentWithMixin)._platformService!;
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Current active DID from settings
							 | 
						|
								     * Used for change detection and component updates
							 | 
						|
								     */
							 | 
						|
								    currentActiveDid(): string | null {
							 | 
						|
								      // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								      return (this as any)._currentActiveDid;
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Access to in-memory logs array
							 | 
						|
								     * Provides direct access to memoryLogs without requiring databaseUtil import
							 | 
						|
								     */
							 | 
						|
								    $memoryLogs(): string[] {
							 | 
						|
								      return _memoryLogs;
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Platform detection utilities
							 | 
						|
								     */
							 | 
						|
								    isCapacitor(): boolean {
							 | 
						|
								      // @ts-expect-error Accessing computed property value from Vue instance
							 | 
						|
								      return this["platformService"].isCapacitor();
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    isWeb(): boolean {
							 | 
						|
								      // @ts-expect-error Accessing computed property value from Vue instance
							 | 
						|
								      return this["platformService"].isWeb();
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    isElectron(): boolean {
							 | 
						|
								      // @ts-expect-error Accessing computed property value from Vue instance
							 | 
						|
								      return this["platformService"].isElectron();
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Platform capabilities
							 | 
						|
								     */
							 | 
						|
								    capabilities() {
							 | 
						|
								      // @ts-expect-error Accessing computed property value from Vue instance
							 | 
						|
								      return this["platformService"].getCapabilities();
							 | 
						|
								    },
							 | 
						|
								  },
							 | 
						|
								
							 | 
						|
								  watch: {
							 | 
						|
								    /**
							 | 
						|
								     * Watch for changes in the current activeDid
							 | 
						|
								     * Triggers component updates when user switches identities
							 | 
						|
								     */
							 | 
						|
								    currentActiveDid: {
							 | 
						|
								      handler(newDid: string | null, oldDid: string | null) {
							 | 
						|
								        if (newDid !== oldDid) {
							 | 
						|
								          logger.debug(
							 | 
						|
								            `[PlatformServiceMixin] ActiveDid changed from ${oldDid} to ${newDid}`,
							 | 
						|
								          );
							 | 
						|
								          // // Clear caches that might be affected by the change
							 | 
						|
								          // (this as any).$clearAllCaches();
							 | 
						|
								        }
							 | 
						|
								      },
							 | 
						|
								      immediate: true,
							 | 
						|
								    },
							 | 
						|
								  },
							 | 
						|
								
							 | 
						|
								  methods: {
							 | 
						|
								    // =================================================
							 | 
						|
								    // SELF-CONTAINED UTILITY METHODS (no databaseUtil dependency)
							 | 
						|
								    // =================================================
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Update the current activeDid and trigger change detection
							 | 
						|
								     * This method should be called when the user switches identities
							 | 
						|
								     */
							 | 
						|
								    async $updateActiveDid(newDid: string | null): Promise<void> {
							 | 
						|
								      // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								      const oldDid = (this as any)._currentActiveDid;
							 | 
						|
								      // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								      (this as any)._currentActiveDid = newDid;
							 | 
						|
								
							 | 
						|
								      if (newDid !== oldDid) {
							 | 
						|
								        logger.debug(
							 | 
						|
								          `[PlatformServiceMixin] ActiveDid updated from ${oldDid} to ${newDid}`,
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        // Write only to active_identity table (single source of truth)
							 | 
						|
								        try {
							 | 
						|
								          await this.$dbExec(
							 | 
						|
								            "UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1",
							 | 
						|
								            [newDid || ""],
							 | 
						|
								          );
							 | 
						|
								          logger.debug(
							 | 
						|
								            `[PlatformServiceMixin] ActiveDid updated in active_identity table: ${newDid}`,
							 | 
						|
								          );
							 | 
						|
								        } catch (error) {
							 | 
						|
								          logger.error(
							 | 
						|
								            `[PlatformServiceMixin] Error updating activeDid in active_identity table ${newDid}:`,
							 | 
						|
								            error,
							 | 
						|
								          );
							 | 
						|
								          // Continue with in-memory update even if database write fails
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // // Clear caches that might be affected by the change
							 | 
						|
								        // this.$clearAllCaches();
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get available account DIDs for user selection
							 | 
						|
								     * Returns array of DIDs that can be set as active identity
							 | 
						|
								     */
							 | 
						|
								    async $getAvailableAccountDids(): Promise<string[]> {
							 | 
						|
								      try {
							 | 
						|
								        const result = await this.$dbQuery(
							 | 
						|
								          "SELECT did FROM accounts ORDER BY did",
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        if (!result?.values?.length) {
							 | 
						|
								          return [];
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        return result.values.map((row: SqlValue[]) => row[0] as string);
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(
							 | 
						|
								          "[PlatformServiceMixin] Error getting available account DIDs:",
							 | 
						|
								          error,
							 | 
						|
								        );
							 | 
						|
								        return [];
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Map database columns to values with proper type conversion
							 | 
						|
								     * Handles boolean conversion from SQLite integers (0/1) to boolean values
							 | 
						|
								     */
							 | 
						|
								    _mapColumnsToValues(
							 | 
						|
								      columns: string[],
							 | 
						|
								      values: unknown[][],
							 | 
						|
								    ): Array<Record<string, unknown>> {
							 | 
						|
								      return values.map((row) => {
							 | 
						|
								        const obj: Record<string, unknown> = {};
							 | 
						|
								        columns.forEach((column, index) => {
							 | 
						|
								          let value = row[index];
							 | 
						|
								
							 | 
						|
								          // Convert SQLite integer booleans to JavaScript booleans
							 | 
						|
								          if (
							 | 
						|
								            // settings
							 | 
						|
								            column === "isRegistered" ||
							 | 
						|
								            column === "finishedOnboarding" ||
							 | 
						|
								            column === "filterFeedByVisible" ||
							 | 
						|
								            column === "filterFeedByNearby" ||
							 | 
						|
								            column === "hasBackedUpSeed" ||
							 | 
						|
								            column === "hideRegisterPromptOnNewContact" ||
							 | 
						|
								            column === "showContactGivesInline" ||
							 | 
						|
								            column === "showGeneralAdvanced" ||
							 | 
						|
								            column === "showShortcutBvc" ||
							 | 
						|
								            column === "warnIfProdServer" ||
							 | 
						|
								            column === "warnIfTestServer" ||
							 | 
						|
								            // contacts
							 | 
						|
								            column === "iViewContent" ||
							 | 
						|
								            column === "registered" ||
							 | 
						|
								            column === "seesMe"
							 | 
						|
								          ) {
							 | 
						|
								            if (value === 1) {
							 | 
						|
								              value = true;
							 | 
						|
								            } else if (value === 0) {
							 | 
						|
								              value = false;
							 | 
						|
								            }
							 | 
						|
								            // Keep null values as null
							 | 
						|
								          }
							 | 
						|
								
							 | 
						|
								          // Convert SQLite JSON strings to objects/arrays
							 | 
						|
								          if (
							 | 
						|
								            column === "contactMethods" ||
							 | 
						|
								            column === "searchBoxes" ||
							 | 
						|
								            column === "starredPlanHandleIds"
							 | 
						|
								          ) {
							 | 
						|
								            value = this._parseJsonField(value, []);
							 | 
						|
								          }
							 | 
						|
								
							 | 
						|
								          obj[column] = value;
							 | 
						|
								        });
							 | 
						|
								        return obj;
							 | 
						|
								      });
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Safely parses JSON strings with fallback to default value.
							 | 
						|
								     * Handles different SQLite implementations:
							 | 
						|
								     * - Web SQLite (wa-sqlite/absurd-sql): Auto-parses JSON strings to objects
							 | 
						|
								     * - Capacitor SQLite: Returns raw strings that need manual parsing
							 | 
						|
								     *
							 | 
						|
								     * See also src/db/databaseUtil.ts parseJsonField
							 | 
						|
								     * and maybe consolidate
							 | 
						|
								     */
							 | 
						|
								    _parseJsonField<T>(value: unknown, defaultValue: T): T {
							 | 
						|
								      if (typeof value === "string") {
							 | 
						|
								        try {
							 | 
						|
								          return JSON.parse(value);
							 | 
						|
								        } catch {
							 | 
						|
								          return defaultValue;
							 | 
						|
								        }
							 | 
						|
								      }
							 | 
						|
								      return (value as T) || defaultValue;
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Convert Settings object to SettingsWithJsonStrings for database storage
							 | 
						|
								     * Handles conversion of complex objects like searchBoxes to JSON strings
							 | 
						|
								     * @param settings Settings object to convert
							 | 
						|
								     * @returns SettingsWithJsonStrings object ready for database storage
							 | 
						|
								     */
							 | 
						|
								    _convertSettingsForStorage(
							 | 
						|
								      settings: Partial<Settings>,
							 | 
						|
								    ): Partial<SettingsWithJsonStrings> {
							 | 
						|
								      const converted = { ...settings } as Partial<SettingsWithJsonStrings>;
							 | 
						|
								
							 | 
						|
								      // Convert searchBoxes array to JSON string if present
							 | 
						|
								      if (settings.searchBoxes !== undefined) {
							 | 
						|
								        // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								        (converted as any).searchBoxes = Array.isArray(settings.searchBoxes)
							 | 
						|
								          ? JSON.stringify(settings.searchBoxes)
							 | 
						|
								          : String(settings.searchBoxes);
							 | 
						|
								      }
							 | 
						|
								      if (settings.starredPlanHandleIds !== undefined) {
							 | 
						|
								        // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								        (converted as any).starredPlanHandleIds = Array.isArray(
							 | 
						|
								          settings.starredPlanHandleIds,
							 | 
						|
								        )
							 | 
						|
								          ? JSON.stringify(settings.starredPlanHandleIds)
							 | 
						|
								          : String(settings.starredPlanHandleIds);
							 | 
						|
								      }
							 | 
						|
								
							 | 
						|
								      return converted;
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    // // =================================================
							 | 
						|
								    // // CACHING UTILITY METHODS
							 | 
						|
								    // // =================================================
							 | 
						|
								
							 | 
						|
								    // /**
							 | 
						|
								    //  * Get or initialize cache for this component instance
							 | 
						|
								    //  */
							 | 
						|
								    // _getCache(): Map<string, CacheEntry<unknown>> {
							 | 
						|
								    //   let cache = componentCaches.get(this as unknown as VueComponentWithMixin);
							 | 
						|
								    //   if (!cache) {
							 | 
						|
								    //     cache = new Map();
							 | 
						|
								    //     componentCaches.set(this as unknown as VueComponentWithMixin, cache);
							 | 
						|
								    //   }
							 | 
						|
								    //   return cache;
							 | 
						|
								    // },
							 | 
						|
								
							 | 
						|
								    // /**
							 | 
						|
								    //  * Check if cache entry is valid (not expired)
							 | 
						|
								    //  */
							 | 
						|
								    // _isCacheValid(entry: CacheEntry<unknown>): boolean {
							 | 
						|
								    //   return Date.now() - entry.timestamp < entry.ttl;
							 | 
						|
								    // },
							 | 
						|
								
							 | 
						|
								    // /**
							 | 
						|
								    //  * Get data from cache if valid, otherwise return null
							 | 
						|
								    //  */
							 | 
						|
								    // _getCached<T>(key: string): T | null {
							 | 
						|
								    //   const cache = this._getCache();
							 | 
						|
								    //   const entry = cache.get(key);
							 | 
						|
								    //   if (entry && this._isCacheValid(entry)) {
							 | 
						|
								    //     return entry.data as T;
							 | 
						|
								    //   }
							 | 
						|
								    //   cache.delete(key); // Clean up expired entries
							 | 
						|
								    //   return null;
							 | 
						|
								    // },
							 | 
						|
								
							 | 
						|
								    // /**
							 | 
						|
								    //  * Store data in cache with TTL
							 | 
						|
								    //  */
							 | 
						|
								    // _setCached<T>(key: string, data: T, ttl?: number): T {
							 | 
						|
								    //   const cache = this._getCache();
							 | 
						|
								    //   const actualTtl = ttl || CACHE_DEFAULTS.default;
							 | 
						|
								    //   cache.set(key, {
							 | 
						|
								    //     data,
							 | 
						|
								    //     timestamp: Date.now(),
							 | 
						|
								    //     ttl: actualTtl,
							 | 
						|
								    //   });
							 | 
						|
								    //   return data;
							 | 
						|
								    // },
							 | 
						|
								
							 | 
						|
								    // /**
							 | 
						|
								    //  * Invalidate specific cache entry
							 | 
						|
								    //  */
							 | 
						|
								    // _invalidateCache(key: string): void {
							 | 
						|
								    //   const cache = this._getCache();
							 | 
						|
								    //   cache.delete(key);
							 | 
						|
								    // },
							 | 
						|
								
							 | 
						|
								    // /**
							 | 
						|
								    //  * Clear all cache entries for this component
							 | 
						|
								    //  */
							 | 
						|
								    // _clearCache(): void {
							 | 
						|
								    //   const cache = this._getCache();
							 | 
						|
								    //   cache.clear();
							 | 
						|
								    // },
							 | 
						|
								
							 | 
						|
								    // =================================================
							 | 
						|
								    // ENHANCED DATABASE METHODS (with error handling)
							 | 
						|
								    // =================================================
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Enhanced database query method with error handling
							 | 
						|
								     */
							 | 
						|
								    async $dbQuery(sql: string, params?: unknown[]) {
							 | 
						|
								      try {
							 | 
						|
								        // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								        return await (this as any).platformService.dbQuery(sql, params);
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(
							 | 
						|
								          // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								          `[${(this as any).$options.name}] Database query failed:`,
							 | 
						|
								          {
							 | 
						|
								            sql,
							 | 
						|
								            params,
							 | 
						|
								            error,
							 | 
						|
								          },
							 | 
						|
								        );
							 | 
						|
								        throw error;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Enhanced database execution method with error handling
							 | 
						|
								     */
							 | 
						|
								    async $dbExec(sql: string, params?: unknown[]) {
							 | 
						|
								      try {
							 | 
						|
								        // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								        return await (this as any).platformService.dbExec(sql, params);
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(
							 | 
						|
								          // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								          `[${(this as any).$options.name}] Database exec failed:`,
							 | 
						|
								          {
							 | 
						|
								            sql,
							 | 
						|
								            params,
							 | 
						|
								            error,
							 | 
						|
								          },
							 | 
						|
								        );
							 | 
						|
								        throw error;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Enhanced database single row query method with error handling
							 | 
						|
								     */
							 | 
						|
								    async $dbGetOneRow(
							 | 
						|
								      sql: string,
							 | 
						|
								      params?: unknown[],
							 | 
						|
								    ): Promise<SqlValue[] | undefined> {
							 | 
						|
								      try {
							 | 
						|
								        // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								        return await (this as any).platformService.dbGetOneRow(sql, params);
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(
							 | 
						|
								          // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								          `[${(this as any).$options.name}] Database single row query failed:`,
							 | 
						|
								          {
							 | 
						|
								            sql,
							 | 
						|
								            params,
							 | 
						|
								            error,
							 | 
						|
								          },
							 | 
						|
								        );
							 | 
						|
								        throw error;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Database raw query method with error handling
							 | 
						|
								     */
							 | 
						|
								    async $dbRawQuery(sql: string, params?: unknown[]) {
							 | 
						|
								      try {
							 | 
						|
								        // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								        return await (this as any).platformService.dbRawQuery(sql, params);
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(
							 | 
						|
								          // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								          `[${(this as any).$options.name}] Database raw query failed:`,
							 | 
						|
								          {
							 | 
						|
								            sql,
							 | 
						|
								            params,
							 | 
						|
								            error,
							 | 
						|
								          },
							 | 
						|
								        );
							 | 
						|
								        throw error;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Utility method for retrieving master settings
							 | 
						|
								     * Common pattern used across many components
							 | 
						|
								     */
							 | 
						|
								    async _getMasterSettings(
							 | 
						|
								      fallback: Settings | null = null,
							 | 
						|
								    ): Promise<Settings | null> {
							 | 
						|
								      try {
							 | 
						|
								        // Get current active identity
							 | 
						|
								        const activeIdentity = await this.$getActiveIdentity();
							 | 
						|
								        const activeDid = activeIdentity.activeDid;
							 | 
						|
								
							 | 
						|
								        if (!activeDid) {
							 | 
						|
								          return fallback;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // Get identity-specific settings
							 | 
						|
								        const result = await this.$dbQuery(
							 | 
						|
								          "SELECT * FROM settings WHERE accountDid = ?",
							 | 
						|
								          [activeDid],
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        if (!result?.values?.length) {
							 | 
						|
								          return fallback;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        const mappedResults = this._mapColumnsToValues(
							 | 
						|
								          result.columns,
							 | 
						|
								          result.values,
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        if (!mappedResults.length) {
							 | 
						|
								          return fallback;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        const settings = mappedResults[0] as Settings;
							 | 
						|
								
							 | 
						|
								        // Handle JSON field parsing
							 | 
						|
								        if (settings.searchBoxes) {
							 | 
						|
								          settings.searchBoxes = this._parseJsonField(settings.searchBoxes, []);
							 | 
						|
								        }
							 | 
						|
								        if (settings.starredPlanHandleIds) {
							 | 
						|
								          settings.starredPlanHandleIds = this._parseJsonField(
							 | 
						|
								            settings.starredPlanHandleIds,
							 | 
						|
								            [],
							 | 
						|
								          );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        return settings;
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(`[Settings Trace] ❌ Failed to get master settings:`, {
							 | 
						|
								          error,
							 | 
						|
								        });
							 | 
						|
								        return fallback;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Utility method for merging default and account-specific settings
							 | 
						|
								     * Handles the common pattern of layered settings
							 | 
						|
								     */
							 | 
						|
								    async $getMergedSettings(
							 | 
						|
								      accountDid?: string,
							 | 
						|
								      defaultFallback: Settings = {},
							 | 
						|
								    ): Promise<Settings> {
							 | 
						|
								      try {
							 | 
						|
								        // Get default settings
							 | 
						|
								        const defaultSettings = await this._getMasterSettings(defaultFallback);
							 | 
						|
								
							 | 
						|
								        // If no account DID, return defaults
							 | 
						|
								        if (!accountDid) {
							 | 
						|
								          return defaultSettings || defaultFallback;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // Get account-specific overrides
							 | 
						|
								        const accountResult = await this.$dbQuery(
							 | 
						|
								          "SELECT * FROM settings WHERE accountDid = ?",
							 | 
						|
								          [accountDid],
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        if (!accountResult?.values?.length) {
							 | 
						|
								          return defaultSettings || defaultFallback;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // Map and filter non-null overrides
							 | 
						|
								        const mappedResults = this._mapColumnsToValues(
							 | 
						|
								          accountResult.columns,
							 | 
						|
								          accountResult.values,
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        if (!mappedResults.length) {
							 | 
						|
								          return defaultSettings || defaultFallback;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        const overrideSettings = mappedResults[0] as Settings;
							 | 
						|
								
							 | 
						|
								        const filteredOverrides = Object.fromEntries(
							 | 
						|
								          Object.entries(overrideSettings).filter(([_, v]) => v !== null),
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        // Merge settings with overrides taking precedence
							 | 
						|
								        const mergedSettings = {
							 | 
						|
								          ...defaultSettings,
							 | 
						|
								          ...filteredOverrides,
							 | 
						|
								        } as Settings;
							 | 
						|
								
							 | 
						|
								        // Handle JSON field parsing
							 | 
						|
								        if (mergedSettings.searchBoxes) {
							 | 
						|
								          mergedSettings.searchBoxes = this._parseJsonField(
							 | 
						|
								            mergedSettings.searchBoxes,
							 | 
						|
								            [],
							 | 
						|
								          );
							 | 
						|
								        }
							 | 
						|
								        if (mergedSettings.starredPlanHandleIds) {
							 | 
						|
								          mergedSettings.starredPlanHandleIds = this._parseJsonField(
							 | 
						|
								            mergedSettings.starredPlanHandleIds,
							 | 
						|
								            [],
							 | 
						|
								          );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        return mergedSettings;
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(`[Settings Trace] ❌ Failed to get merged settings:`, {
							 | 
						|
								          accountDid,
							 | 
						|
								          error,
							 | 
						|
								        });
							 | 
						|
								        return defaultFallback;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get active identity from the new active_identity table
							 | 
						|
								     * This replaces the activeDid field in settings for better architecture
							 | 
						|
								     */
							 | 
						|
								    async $getActiveIdentity(): Promise<{ activeDid: string }> {
							 | 
						|
								      try {
							 | 
						|
								        const result = await this.$dbQuery(
							 | 
						|
								          "SELECT activeDid FROM active_identity WHERE id = 1",
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        if (!result?.values?.length) {
							 | 
						|
								          logger.warn(
							 | 
						|
								            "[PlatformServiceMixin] Active identity table is empty - this may indicate a migration issue",
							 | 
						|
								          );
							 | 
						|
								          return { activeDid: "" };
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        const activeDid = result.values[0][0] as string | null;
							 | 
						|
								
							 | 
						|
								        // Handle null activeDid (initial state after migration) - auto-select first account
							 | 
						|
								        if (activeDid === null) {
							 | 
						|
								          const firstAccount = await this.$dbQuery(
							 | 
						|
								            "SELECT did FROM accounts ORDER BY dateCreated, did LIMIT 1",
							 | 
						|
								          );
							 | 
						|
								
							 | 
						|
								          if (firstAccount?.values?.length) {
							 | 
						|
								            const firstAccountDid = firstAccount.values[0][0] as string;
							 | 
						|
								            await this.$dbExec(
							 | 
						|
								              "UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1",
							 | 
						|
								              [firstAccountDid],
							 | 
						|
								            );
							 | 
						|
								            return { activeDid: firstAccountDid };
							 | 
						|
								          }
							 | 
						|
								
							 | 
						|
								          logger.warn(
							 | 
						|
								            "[PlatformServiceMixin] No accounts available for auto-selection",
							 | 
						|
								          );
							 | 
						|
								          return { activeDid: "" };
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // Validate activeDid exists in accounts
							 | 
						|
								        const accountExists = await this.$dbQuery(
							 | 
						|
								          "SELECT did FROM accounts WHERE did = ?",
							 | 
						|
								          [activeDid],
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        if (accountExists?.values?.length) {
							 | 
						|
								          return { activeDid };
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // Clear corrupted activeDid and return empty
							 | 
						|
								        logger.warn(
							 | 
						|
								          "[PlatformServiceMixin] Active identity not found in accounts, clearing",
							 | 
						|
								        );
							 | 
						|
								        await this.$dbExec(
							 | 
						|
								          "UPDATE active_identity SET activeDid = NULL, lastUpdated = datetime('now') WHERE id = 1",
							 | 
						|
								        );
							 | 
						|
								        return { activeDid: "" };
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(
							 | 
						|
								          "[PlatformServiceMixin] Error getting active identity:",
							 | 
						|
								          error,
							 | 
						|
								        );
							 | 
						|
								        return { activeDid: "" };
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Transaction wrapper with automatic rollback on error
							 | 
						|
								     */
							 | 
						|
								    async $withTransaction<T>(callback: () => Promise<T>): Promise<T> {
							 | 
						|
								      try {
							 | 
						|
								        await this.$dbExec("BEGIN TRANSACTION");
							 | 
						|
								        const result = await callback();
							 | 
						|
								        await this.$dbExec("COMMIT");
							 | 
						|
								        return result;
							 | 
						|
								      } catch (error) {
							 | 
						|
								        await this.$dbExec("ROLLBACK");
							 | 
						|
								        throw error;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    // =================================================
							 | 
						|
								    // SMART DELETION PATTERN DAL METHODS
							 | 
						|
								    // =================================================
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get account DID by ID
							 | 
						|
								     * Required for smart deletion pattern
							 | 
						|
								     */
							 | 
						|
								    async $getAccountDidById(id: number): Promise<string> {
							 | 
						|
								      const result = await this.$dbQuery(
							 | 
						|
								        "SELECT did FROM accounts WHERE id = ?",
							 | 
						|
								        [id],
							 | 
						|
								      );
							 | 
						|
								      return result?.values?.[0]?.[0] as string;
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get active DID (returns null if none selected)
							 | 
						|
								     * Required for smart deletion pattern
							 | 
						|
								     */
							 | 
						|
								    async $getActiveDid(): Promise<string | null> {
							 | 
						|
								      const result = await this.$dbQuery(
							 | 
						|
								        "SELECT activeDid FROM active_identity WHERE id = 1",
							 | 
						|
								      );
							 | 
						|
								      return (result?.values?.[0]?.[0] as string) || null;
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Set active DID (can be null for no selection)
							 | 
						|
								     * Required for smart deletion pattern
							 | 
						|
								     */
							 | 
						|
								    async $setActiveDid(did: string | null): Promise<void> {
							 | 
						|
								      await this.$dbExec(
							 | 
						|
								        "UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1",
							 | 
						|
								        [did],
							 | 
						|
								      );
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Count total accounts
							 | 
						|
								     * Required for smart deletion pattern
							 | 
						|
								     */
							 | 
						|
								    async $countAccounts(): Promise<number> {
							 | 
						|
								      const result = await this.$dbQuery("SELECT COUNT(*) FROM accounts");
							 | 
						|
								      return (result?.values?.[0]?.[0] as number) || 0;
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Deterministic "next" picker for account selection
							 | 
						|
								     * Required for smart deletion pattern
							 | 
						|
								     */
							 | 
						|
								    $pickNextAccountDid(all: string[], current?: string): string {
							 | 
						|
								      const sorted = [...all].sort();
							 | 
						|
								      if (!current) return sorted[0];
							 | 
						|
								      const i = sorted.indexOf(current);
							 | 
						|
								      return sorted[(i + 1) % sorted.length];
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Ensure an active account is selected (repair hook)
							 | 
						|
								     * Required for smart deletion pattern bootstrapping
							 | 
						|
								     */
							 | 
						|
								    async $ensureActiveSelected(): Promise<void> {
							 | 
						|
								      const active = await this.$getActiveDid();
							 | 
						|
								      const all = await this.$getAllAccountDids();
							 | 
						|
								      if (active === null && all.length > 0) {
							 | 
						|
								        await this.$setActiveDid(this.$pickNextAccountDid(all));
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    // =================================================
							 | 
						|
								    // ULTRA-CONCISE DATABASE METHODS (shortest names)
							 | 
						|
								    // =================================================
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Ultra-short database query - just $db()
							 | 
						|
								     * @param sql SQL query string
							 | 
						|
								     * @param params Query parameters
							 | 
						|
								     */
							 | 
						|
								    async $db(
							 | 
						|
								      sql: string,
							 | 
						|
								      params: unknown[] = [],
							 | 
						|
								    ): Promise<QueryExecResult | undefined> {
							 | 
						|
								      // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								      return await (this as any).platformService.dbQuery(sql, params);
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Ultra-short database exec - just $exec()
							 | 
						|
								     * @param sql SQL statement string
							 | 
						|
								     * @param params Statement parameters
							 | 
						|
								     */
							 | 
						|
								    async $exec(
							 | 
						|
								      sql: string,
							 | 
						|
								      params: unknown[] = [],
							 | 
						|
								    ): Promise<DatabaseExecResult> {
							 | 
						|
								      // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								      return await (this as any).platformService.dbExec(sql, params);
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Ultra-short single row query - just $one()
							 | 
						|
								     * @param sql SQL query string
							 | 
						|
								     * @param params Query parameters
							 | 
						|
								     */
							 | 
						|
								    async $one(
							 | 
						|
								      sql: string,
							 | 
						|
								      params: unknown[] = [],
							 | 
						|
								    ): Promise<SqlValue[] | undefined> {
							 | 
						|
								      // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								      return await (this as any).platformService.dbGetOneRow(sql, params);
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    // =================================================
							 | 
						|
								    // QUERY + MAPPING COMBO METHODS (ultimate conciseness)
							 | 
						|
								    // =================================================
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Query with automatic result mapping - $query()
							 | 
						|
								     * Combines database query + mapping in one call
							 | 
						|
								     * @param sql SQL query string
							 | 
						|
								     * @param params Query parameters
							 | 
						|
								     * @returns Mapped array of results
							 | 
						|
								     */
							 | 
						|
								    async $query<T = Record<string, unknown>>(
							 | 
						|
								      sql: string,
							 | 
						|
								      params: unknown[] = [],
							 | 
						|
								    ): Promise<T[]> {
							 | 
						|
								      // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								      const result = await (this as any).platformService.dbQuery(sql, params);
							 | 
						|
								      if (!result?.columns || !result?.values) {
							 | 
						|
								        return [];
							 | 
						|
								      }
							 | 
						|
								      const mappedResults = this._mapColumnsToValues(
							 | 
						|
								        result.columns,
							 | 
						|
								        result.values,
							 | 
						|
								      );
							 | 
						|
								      return mappedResults as T[];
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get first result with automatic mapping - $first()
							 | 
						|
								     * @param sql SQL query string
							 | 
						|
								     * @param params Query parameters
							 | 
						|
								     * @returns First mapped result or null
							 | 
						|
								     */
							 | 
						|
								    async $first<T = Record<string, unknown>>(
							 | 
						|
								      sql: string,
							 | 
						|
								      params: unknown[] = [],
							 | 
						|
								    ): Promise<T | null> {
							 | 
						|
								      const results = await this.$query(sql, params);
							 | 
						|
								      return results.length > 0 ? (results[0] as T) : null;
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    // =================================================
							 | 
						|
								    // CACHED SPECIALIZED SHORTCUTS (massive performance boost)
							 | 
						|
								    // =================================================
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Normalize contact data by parsing JSON strings into proper objects
							 | 
						|
								     * Handles the contactMethods field which can be either a JSON string or an array
							 | 
						|
								     * @param rawContacts Raw contact data from database
							 | 
						|
								     * @returns Normalized Contact[] array
							 | 
						|
								     */
							 | 
						|
								    $normalizeContacts(rawContacts: ContactMaybeWithJsonStrings[]): Contact[] {
							 | 
						|
								      return rawContacts.map((contact) => {
							 | 
						|
								        // Create a new contact object with proper typing
							 | 
						|
								        const normalizedContact: Contact = {
							 | 
						|
								          did: contact.did,
							 | 
						|
								          iViewContent: contact.iViewContent,
							 | 
						|
								          name: contact.name,
							 | 
						|
								          nextPubKeyHashB64: contact.nextPubKeyHashB64,
							 | 
						|
								          notes: contact.notes,
							 | 
						|
								          profileImageUrl: contact.profileImageUrl,
							 | 
						|
								          publicKeyBase64: contact.publicKeyBase64,
							 | 
						|
								          seesMe: contact.seesMe,
							 | 
						|
								          registered: contact.registered,
							 | 
						|
								        };
							 | 
						|
								
							 | 
						|
								        // Handle contactMethods field which can be a JSON string or an array
							 | 
						|
								        if (contact.contactMethods !== undefined) {
							 | 
						|
								          if (typeof contact.contactMethods === "string") {
							 | 
						|
								            // Parse JSON string into array
							 | 
						|
								            normalizedContact.contactMethods = this._parseJsonField(
							 | 
						|
								              contact.contactMethods,
							 | 
						|
								              [],
							 | 
						|
								            );
							 | 
						|
								          } else if (Array.isArray(contact.contactMethods)) {
							 | 
						|
								            // Validate that each item in the array is a proper ContactMethod object
							 | 
						|
								            normalizedContact.contactMethods = contact.contactMethods.filter(
							 | 
						|
								              (method) => {
							 | 
						|
								                const isValid =
							 | 
						|
								                  method &&
							 | 
						|
								                  typeof method === "object" &&
							 | 
						|
								                  typeof method.label === "string" &&
							 | 
						|
								                  typeof method.type === "string" &&
							 | 
						|
								                  typeof method.value === "string";
							 | 
						|
								
							 | 
						|
								                if (!isValid && method !== undefined) {
							 | 
						|
								                  // eslint-disable-next-line no-console
							 | 
						|
								                  console.warn(
							 | 
						|
								                    "[ContactNormalization] Invalid contact method:",
							 | 
						|
								                    method,
							 | 
						|
								                  );
							 | 
						|
								                }
							 | 
						|
								
							 | 
						|
								                return isValid;
							 | 
						|
								              },
							 | 
						|
								            );
							 | 
						|
								          } else {
							 | 
						|
								            // Invalid data, use empty array
							 | 
						|
								            normalizedContact.contactMethods = [];
							 | 
						|
								          }
							 | 
						|
								        } else {
							 | 
						|
								          // No contactMethods, use empty array
							 | 
						|
								          normalizedContact.contactMethods = [];
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        return normalizedContact;
							 | 
						|
								      });
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Load all contacts (always fresh) - $contacts()
							 | 
						|
								     * Always fetches fresh data from database for consistency
							 | 
						|
								     * Handles JSON string/object duality for contactMethods field
							 | 
						|
								     * @returns Promise<Contact[]> Array of normalized contact objects
							 | 
						|
								     */
							 | 
						|
								    async $contacts(): Promise<Contact[]> {
							 | 
						|
								      const rawContacts = (await this.$query(
							 | 
						|
								        "SELECT * FROM contacts ORDER BY name",
							 | 
						|
								      )) as ContactMaybeWithJsonStrings[];
							 | 
						|
								
							 | 
						|
								      return this.$normalizeContacts(rawContacts);
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Load all contacts sorted by when they were added (by ID)
							 | 
						|
								     * Always fetches fresh data from database for consistency
							 | 
						|
								     * Handles JSON string/object duality for contactMethods field
							 | 
						|
								     * @returns Promise<Contact[]> Array of normalized contact objects sorted by addition date (newest first)
							 | 
						|
								     */
							 | 
						|
								    async $contactsByDateAdded(): Promise<Contact[]> {
							 | 
						|
								      const rawContacts = (await this.$query(
							 | 
						|
								        "SELECT * FROM contacts ORDER BY id DESC",
							 | 
						|
								      )) as ContactMaybeWithJsonStrings[];
							 | 
						|
								
							 | 
						|
								      return this.$normalizeContacts(rawContacts);
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Ultra-concise shortcut for getting number of contacts
							 | 
						|
								     * @returns Promise<number> Total number of contacts
							 | 
						|
								     */
							 | 
						|
								    async $contactCount(): Promise<number> {
							 | 
						|
								      const countRow = await this.$one("SELECT COUNT(*) FROM contacts");
							 | 
						|
								      return (countRow?.[0] as number) || 0;
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Ultra-concise shortcut for getting all logs from database
							 | 
						|
								     * @returns Promise<Array<Record<string, unknown>>> Array of log records
							 | 
						|
								     */
							 | 
						|
								    async $logs(): Promise<Array<Record<string, unknown>>> {
							 | 
						|
								      return await this.$query("SELECT * FROM logs ORDER BY date DESC");
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Load settings with optional defaults WITHOUT caching - $settings()
							 | 
						|
								     * Settings are loaded fresh every time for immediate consistency
							 | 
						|
								     * @param defaults Optional default values
							 | 
						|
								     * @returns Fresh settings object from database
							 | 
						|
								     */
							 | 
						|
								    async $settings(defaults: Settings = {}): Promise<Settings> {
							 | 
						|
								      const settings = await this._getMasterSettings(defaults);
							 | 
						|
								
							 | 
						|
								      if (!settings) {
							 | 
						|
								        return defaults;
							 | 
						|
								      }
							 | 
						|
								
							 | 
						|
								      // FIXED: Set default apiServer for all platforms, not just Electron
							 | 
						|
								      // Only set default if no user preference exists
							 | 
						|
								      if (!settings.apiServer) {
							 | 
						|
								        // Import constants dynamically to get platform-specific values
							 | 
						|
								        const { DEFAULT_ENDORSER_API_SERVER } = await import(
							 | 
						|
								          "../constants/app"
							 | 
						|
								        );
							 | 
						|
								        // Set default for all platforms when apiServer is empty
							 | 
						|
								        settings.apiServer = DEFAULT_ENDORSER_API_SERVER;
							 | 
						|
								      }
							 | 
						|
								
							 | 
						|
								      return settings; // Return fresh data without caching
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Load account-specific settings WITHOUT caching - $accountSettings()
							 | 
						|
								     * Settings are loaded fresh every time for immediate consistency
							 | 
						|
								     * @param did DID identifier (optional, uses current active DID)
							 | 
						|
								     * @param defaults Optional default values
							 | 
						|
								     * @returns Fresh merged settings object from database
							 | 
						|
								     */
							 | 
						|
								    async $accountSettings(
							 | 
						|
								      did?: string,
							 | 
						|
								      defaults: Settings = {},
							 | 
						|
								    ): Promise<Settings> {
							 | 
						|
								      try {
							 | 
						|
								        // Get default settings first
							 | 
						|
								        const defaultSettings = await this._getMasterSettings(defaults);
							 | 
						|
								
							 | 
						|
								        if (!defaultSettings) {
							 | 
						|
								          return defaults;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // Get DID from active_identity table (single source of truth)
							 | 
						|
								        const activeIdentity = await this.$getActiveIdentity();
							 | 
						|
								        const targetDid = did || activeIdentity.activeDid;
							 | 
						|
								
							 | 
						|
								        // If no target DID, return default settings
							 | 
						|
								        if (!targetDid) {
							 | 
						|
								          return defaultSettings;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // Get merged settings using existing method
							 | 
						|
								        const mergedSettings = await this.$getMergedSettings(
							 | 
						|
								          targetDid,
							 | 
						|
								          defaultSettings,
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        // Set activeDid from active_identity table (single source of truth)
							 | 
						|
								        mergedSettings.activeDid = activeIdentity.activeDid;
							 | 
						|
								        logger.debug(
							 | 
						|
								          "[PlatformServiceMixin] Using activeDid from active_identity table:",
							 | 
						|
								          { activeDid: activeIdentity.activeDid },
							 | 
						|
								        );
							 | 
						|
								        logger.debug(
							 | 
						|
								          "[PlatformServiceMixin] $accountSettings() returning activeDid:",
							 | 
						|
								          { activeDid: mergedSettings.activeDid },
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        // FIXED: Set default apiServer for all platforms, not just Electron
							 | 
						|
								        // Only set default if no user preference exists
							 | 
						|
								        if (!mergedSettings.apiServer) {
							 | 
						|
								          // Import constants dynamically to get platform-specific values
							 | 
						|
								          const { DEFAULT_ENDORSER_API_SERVER } = await import(
							 | 
						|
								            "../constants/app"
							 | 
						|
								          );
							 | 
						|
								          // Set default for all platforms when apiServer is empty
							 | 
						|
								          mergedSettings.apiServer = DEFAULT_ENDORSER_API_SERVER;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // Merge with any provided defaults (these take highest precedence)
							 | 
						|
								        // Filter out undefined and empty string values to prevent overriding real settings
							 | 
						|
								        const filteredDefaults = Object.fromEntries(
							 | 
						|
								          Object.entries(defaults).filter(
							 | 
						|
								            ([_, value]) => value !== undefined && value !== "",
							 | 
						|
								          ),
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        const finalSettings = { ...mergedSettings, ...filteredDefaults };
							 | 
						|
								        return finalSettings;
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error("[Settings Trace] ❌ Error in $accountSettings:", error);
							 | 
						|
								
							 | 
						|
								        // Fallback to defaults on error
							 | 
						|
								        return defaults;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    // =================================================
							 | 
						|
								    // SETTINGS UPDATE SHORTCUTS (eliminate 90% boilerplate)
							 | 
						|
								    // =================================================
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Save default settings - $saveSettings()
							 | 
						|
								     * Ultra-concise shortcut for updateDefaultSettings
							 | 
						|
								     *
							 | 
						|
								     * ✅ KEEP: This method will be the primary settings save method after consolidation
							 | 
						|
								     *
							 | 
						|
								     * @param changes Settings changes to save
							 | 
						|
								     * @returns Promise<boolean> Success status
							 | 
						|
								     */
							 | 
						|
								    async $saveSettings(changes: Partial<Settings>): Promise<boolean> {
							 | 
						|
								      try {
							 | 
						|
								        // Remove fields that shouldn't be updated
							 | 
						|
								        const {
							 | 
						|
								          accountDid,
							 | 
						|
								          id,
							 | 
						|
								          activeDid: activeDidField,
							 | 
						|
								          ...safeChanges
							 | 
						|
								        } = changes;
							 | 
						|
								        // eslint-disable-next-line @typescript-eslint/no-unused-vars
							 | 
						|
								        void accountDid;
							 | 
						|
								        // eslint-disable-next-line @typescript-eslint/no-unused-vars
							 | 
						|
								        void id;
							 | 
						|
								        // eslint-disable-next-line @typescript-eslint/no-unused-vars
							 | 
						|
								        void activeDidField;
							 | 
						|
								
							 | 
						|
								        logger.debug(
							 | 
						|
								          "[PlatformServiceMixin] $saveSettings - Original changes:",
							 | 
						|
								          changes,
							 | 
						|
								        );
							 | 
						|
								        logger.debug(
							 | 
						|
								          "[PlatformServiceMixin] $saveSettings - Safe changes:",
							 | 
						|
								          safeChanges,
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        if (Object.keys(safeChanges).length === 0) return true;
							 | 
						|
								
							 | 
						|
								        // Convert settings for database storage (handles searchBoxes conversion)
							 | 
						|
								        const convertedChanges = this._convertSettingsForStorage(safeChanges);
							 | 
						|
								        logger.debug(
							 | 
						|
								          "[PlatformServiceMixin] $saveSettings - Converted changes:",
							 | 
						|
								          convertedChanges,
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        const setParts: string[] = [];
							 | 
						|
								        const params: unknown[] = [];
							 | 
						|
								
							 | 
						|
								        Object.entries(convertedChanges).forEach(([key, value]) => {
							 | 
						|
								          if (value !== undefined) {
							 | 
						|
								            setParts.push(`${key} = ?`);
							 | 
						|
								            params.push(value);
							 | 
						|
								          }
							 | 
						|
								        });
							 | 
						|
								
							 | 
						|
								        logger.debug(
							 | 
						|
								          "[PlatformServiceMixin] $saveSettings - Set parts:",
							 | 
						|
								          setParts,
							 | 
						|
								        );
							 | 
						|
								        logger.debug("[PlatformServiceMixin] $saveSettings - Params:", params);
							 | 
						|
								
							 | 
						|
								        if (setParts.length === 0) return true;
							 | 
						|
								
							 | 
						|
								        // Get current active DID and update that identity's settings
							 | 
						|
								        const activeIdentity = await this.$getActiveIdentity();
							 | 
						|
								        const currentActiveDid = activeIdentity.activeDid;
							 | 
						|
								
							 | 
						|
								        if (currentActiveDid) {
							 | 
						|
								          params.push(currentActiveDid);
							 | 
						|
								          await this.$dbExec(
							 | 
						|
								            `UPDATE settings SET ${setParts.join(", ")} WHERE accountDid = ?`,
							 | 
						|
								            params,
							 | 
						|
								          );
							 | 
						|
								        } else {
							 | 
						|
								          logger.warn(
							 | 
						|
								            "[PlatformServiceMixin] No active DID found, cannot save settings",
							 | 
						|
								          );
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // Update activeDid tracking if it changed
							 | 
						|
								        if (activeDidField !== undefined) {
							 | 
						|
								          await this.$updateActiveDid(activeDidField);
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        return true;
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error("[PlatformServiceMixin] Error saving settings:", error);
							 | 
						|
								        return false;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Save user-specific settings - $saveUserSettings()
							 | 
						|
								     * Ultra-concise shortcut for updateDidSpecificSettings
							 | 
						|
								     * @param did DID identifier
							 | 
						|
								     * @param changes Settings changes to save
							 | 
						|
								     * @returns Promise<boolean> Success status
							 | 
						|
								     */
							 | 
						|
								    async $saveUserSettings(
							 | 
						|
								      did: string,
							 | 
						|
								      changes: Partial<Settings>,
							 | 
						|
								    ): Promise<boolean> {
							 | 
						|
								      try {
							 | 
						|
								        // Remove fields that shouldn't be updated
							 | 
						|
								        const { id, ...safeChanges } = changes;
							 | 
						|
								        // eslint-disable-next-line @typescript-eslint/no-unused-vars
							 | 
						|
								        void id;
							 | 
						|
								        safeChanges.accountDid = did;
							 | 
						|
								
							 | 
						|
								        if (Object.keys(safeChanges).length === 0) return true;
							 | 
						|
								
							 | 
						|
								        // Convert settings for database storage (handles searchBoxes conversion)
							 | 
						|
								        const convertedChanges = this._convertSettingsForStorage(safeChanges);
							 | 
						|
								
							 | 
						|
								        const setParts: string[] = [];
							 | 
						|
								        const params: unknown[] = [];
							 | 
						|
								
							 | 
						|
								        Object.entries(convertedChanges).forEach(([key, value]) => {
							 | 
						|
								          if (value !== undefined) {
							 | 
						|
								            setParts.push(`${key} = ?`);
							 | 
						|
								            params.push(value);
							 | 
						|
								          }
							 | 
						|
								        });
							 | 
						|
								
							 | 
						|
								        if (setParts.length === 0) return true;
							 | 
						|
								
							 | 
						|
								        params.push(did);
							 | 
						|
								        const sql = `UPDATE settings SET ${setParts.join(", ")} WHERE accountDid = ?`;
							 | 
						|
								
							 | 
						|
								        await this.$dbExec(sql, params);
							 | 
						|
								        return true;
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(
							 | 
						|
								          "[PlatformServiceMixin] Error saving user settings:",
							 | 
						|
								          error,
							 | 
						|
								        );
							 | 
						|
								        return false;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Save settings for current active user - $saveMySettings()
							 | 
						|
								     * Ultra-concise shortcut using activeDid from component
							 | 
						|
								     * @param changes Settings changes to save
							 | 
						|
								     * @returns Promise<boolean> Success status
							 | 
						|
								     */
							 | 
						|
								    /**
							 | 
						|
								     * Since this is unused, and since it relies on this.activeDid which isn't guaranteed to exist,
							 | 
						|
								     * let's take this out for the sake of safety.
							 | 
						|
								     * Totally remove after start of 2026 (since it would be obvious by then that it's not used).
							 | 
						|
								     *
							 | 
						|
								    async $saveMySettings(changes: Partial<Settings>): Promise<boolean> {
							 | 
						|
								      // eslint-disable-next-line @typescript-eslint/no-explicit-any
							 | 
						|
								      const currentDid = (this as any).activeDid;
							 | 
						|
								
							 | 
						|
								      if (!currentDid) {
							 | 
						|
								        return await this.$saveSettings(changes);
							 | 
						|
								      }
							 | 
						|
								      return await this.$saveUserSettings(currentDid, changes);
							 | 
						|
								    },
							 | 
						|
								    **/
							 | 
						|
								
							 | 
						|
								    // =================================================
							 | 
						|
								    // CACHE MANAGEMENT METHODS
							 | 
						|
								    // =================================================
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Refresh settings from database - $refreshSettings()
							 | 
						|
								     * Since settings are no longer cached, this simply returns fresh settings
							 | 
						|
								     */
							 | 
						|
								    async $refreshSettings(): Promise<Settings> {
							 | 
						|
								      return await this.$settings();
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get fresh contacts from database - $refreshContacts()
							 | 
						|
								     * Always returns fresh data (no caching)
							 | 
						|
								     */
							 | 
						|
								    async $refreshContacts(): Promise<Contact[]> {
							 | 
						|
								      return await this.$contacts();
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    // /**
							 | 
						|
								    //  * Clear all caches for this component - $clearAllCaches()
							 | 
						|
								    //  * Useful for manual cache management
							 | 
						|
								    //  */
							 | 
						|
								    // $clearAllCaches(): void {
							 | 
						|
								    //   this._clearCache();
							 | 
						|
								    // },
							 | 
						|
								
							 | 
						|
								    // =================================================
							 | 
						|
								    // HIGH-LEVEL ENTITY OPERATIONS (eliminate verbose SQL patterns)
							 | 
						|
								    // =================================================
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Map SQL query results to typed objects - $mapResults()
							 | 
						|
								     * Eliminates verbose row mapping patterns
							 | 
						|
								     * @param results SQL query results
							 | 
						|
								     * @param mapper Function to map each row to an object
							 | 
						|
								     * @returns Array of mapped objects
							 | 
						|
								     */
							 | 
						|
								    $mapResults<T>(
							 | 
						|
								      results: QueryExecResult | undefined,
							 | 
						|
								      mapper: (row: unknown[]) => T,
							 | 
						|
								    ): T[] {
							 | 
						|
								      if (!results?.values) return [];
							 | 
						|
								      return results.values.map(mapper);
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Maps a SQLite query result to an array of objects
							 | 
						|
								     * @param record The query result from SQLite
							 | 
						|
								     * @returns Array of objects where each object maps column names to their corresponding values
							 | 
						|
								     */
							 | 
						|
								    $mapQueryResultToValues(
							 | 
						|
								      record: QueryExecResult | undefined,
							 | 
						|
								    ): Array<Record<string, unknown>> {
							 | 
						|
								      if (!record) {
							 | 
						|
								        return [];
							 | 
						|
								      }
							 | 
						|
								      return this.$mapColumnsToValues(record.columns, record.values) as Array<
							 | 
						|
								        Record<string, unknown>
							 | 
						|
								      >;
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Public method for mapping database columns to values
							 | 
						|
								     * Provides the same functionality as _mapColumnsToValues but as a public method
							 | 
						|
								     */
							 | 
						|
								    $mapColumnsToValues(
							 | 
						|
								      columns: string[],
							 | 
						|
								      values: unknown[][],
							 | 
						|
								    ): Array<Record<string, unknown>> {
							 | 
						|
								      return this._mapColumnsToValues(columns, values);
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Insert or replace contact - $insertContact()
							 | 
						|
								     * Eliminates verbose INSERT OR REPLACE patterns
							 | 
						|
								     * @param contact Contact object to insert
							 | 
						|
								     * @returns Promise<boolean> Success status
							 | 
						|
								     */
							 | 
						|
								    async $insertContact(contact: Partial<Contact>): Promise<boolean> {
							 | 
						|
								      try {
							 | 
						|
								        // Convert undefined values to null for SQL.js compatibility
							 | 
						|
								        const safeContact = {
							 | 
						|
								          did: contact.did !== undefined ? contact.did : null,
							 | 
						|
								          name: contact.name !== undefined ? contact.name : null,
							 | 
						|
								          publicKeyBase64:
							 | 
						|
								            contact.publicKeyBase64 !== undefined
							 | 
						|
								              ? contact.publicKeyBase64
							 | 
						|
								              : null,
							 | 
						|
								          seesMe: contact.seesMe !== undefined ? contact.seesMe : null,
							 | 
						|
								          registered:
							 | 
						|
								            contact.registered !== undefined ? contact.registered : null,
							 | 
						|
								          nextPubKeyHashB64:
							 | 
						|
								            contact.nextPubKeyHashB64 !== undefined
							 | 
						|
								              ? contact.nextPubKeyHashB64
							 | 
						|
								              : null,
							 | 
						|
								          profileImageUrl:
							 | 
						|
								            contact.profileImageUrl !== undefined
							 | 
						|
								              ? contact.profileImageUrl
							 | 
						|
								              : null,
							 | 
						|
								          contactMethods:
							 | 
						|
								            contact.contactMethods !== undefined
							 | 
						|
								              ? Array.isArray(contact.contactMethods)
							 | 
						|
								                ? JSON.stringify(contact.contactMethods)
							 | 
						|
								                : contact.contactMethods
							 | 
						|
								              : null,
							 | 
						|
								        };
							 | 
						|
								
							 | 
						|
								        await this.$dbExec(
							 | 
						|
								          `INSERT OR REPLACE INTO contacts 
							 | 
						|
								           (did, name, publicKeyBase64, seesMe, registered, nextPubKeyHashB64, profileImageUrl, contactMethods) 
							 | 
						|
								           VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
							 | 
						|
								          [
							 | 
						|
								            safeContact.did,
							 | 
						|
								            safeContact.name,
							 | 
						|
								            safeContact.publicKeyBase64,
							 | 
						|
								            safeContact.seesMe,
							 | 
						|
								            safeContact.registered,
							 | 
						|
								            safeContact.nextPubKeyHashB64,
							 | 
						|
								            safeContact.profileImageUrl,
							 | 
						|
								            safeContact.contactMethods,
							 | 
						|
								          ],
							 | 
						|
								        );
							 | 
						|
								        return true;
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error("[PlatformServiceMixin] Error inserting contact:", error);
							 | 
						|
								        return false;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Update contact - $updateContact()
							 | 
						|
								     * Eliminates verbose UPDATE patterns
							 | 
						|
								     * @param did Contact DID to update
							 | 
						|
								     * @param changes Partial contact changes
							 | 
						|
								     * @returns Promise<boolean> Success status
							 | 
						|
								     */
							 | 
						|
								    async $updateContact(
							 | 
						|
								      did: string,
							 | 
						|
								      changes: Partial<Contact>,
							 | 
						|
								    ): Promise<boolean> {
							 | 
						|
								      try {
							 | 
						|
								        const setParts: string[] = [];
							 | 
						|
								        const params: unknown[] = [];
							 | 
						|
								
							 | 
						|
								        Object.entries(changes).forEach(([key, value]) => {
							 | 
						|
								          if (value !== undefined) {
							 | 
						|
								            setParts.push(`${key} = ?`);
							 | 
						|
								
							 | 
						|
								            // Handle contactMethods field - convert array to JSON string
							 | 
						|
								            if (key === "contactMethods" && Array.isArray(value)) {
							 | 
						|
								              params.push(JSON.stringify(value));
							 | 
						|
								            } else {
							 | 
						|
								              params.push(value);
							 | 
						|
								            }
							 | 
						|
								          }
							 | 
						|
								        });
							 | 
						|
								
							 | 
						|
								        if (setParts.length === 0) return true;
							 | 
						|
								
							 | 
						|
								        params.push(did);
							 | 
						|
								        await this.$dbExec(
							 | 
						|
								          `UPDATE contacts SET ${setParts.join(", ")} WHERE did = ?`,
							 | 
						|
								          params,
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        return true;
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error("[PlatformServiceMixin] Error updating contact:", error);
							 | 
						|
								        return false;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get all contacts as typed objects - $getAllContacts()
							 | 
						|
								     * Eliminates verbose query + mapping patterns
							 | 
						|
								     * Handles JSON string/object duality for contactMethods field
							 | 
						|
								     * @returns Promise<Contact[]> Array of normalized contact objects
							 | 
						|
								     */
							 | 
						|
								    async $getAllContacts(): Promise<Contact[]> {
							 | 
						|
								      const rawContacts = (await this.$query(
							 | 
						|
								        "SELECT * FROM contacts ORDER BY name",
							 | 
						|
								      )) as ContactMaybeWithJsonStrings[];
							 | 
						|
								
							 | 
						|
								      return this.$normalizeContacts(rawContacts);
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get single contact by DID - $getContact()
							 | 
						|
								     * Eliminates verbose single contact query patterns
							 | 
						|
								     * Handles JSON string/object duality for contactMethods field
							 | 
						|
								     * @param did Contact DID to retrieve
							 | 
						|
								     * @returns Promise<Contact | null> Normalized contact object or null if not found
							 | 
						|
								     */
							 | 
						|
								    async $getContact(did: string): Promise<Contact | null> {
							 | 
						|
								      const rawContacts = (await this.$query(
							 | 
						|
								        "SELECT * FROM contacts WHERE did = ?",
							 | 
						|
								        [did],
							 | 
						|
								      )) as ContactMaybeWithJsonStrings[];
							 | 
						|
								
							 | 
						|
								      if (rawContacts.length === 0) {
							 | 
						|
								        return null;
							 | 
						|
								      }
							 | 
						|
								
							 | 
						|
								      const normalizedContacts = this.$normalizeContacts(rawContacts);
							 | 
						|
								      return normalizedContacts[0];
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Delete contact by DID - $deleteContact()
							 | 
						|
								     * Eliminates verbose contact deletion patterns
							 | 
						|
								     * @param did Contact DID to delete
							 | 
						|
								     * @returns Promise<boolean> Success status
							 | 
						|
								     */
							 | 
						|
								    async $deleteContact(did: string): Promise<boolean> {
							 | 
						|
								      try {
							 | 
						|
								        await this.$dbExec("DELETE FROM contacts WHERE did = ?", [did]);
							 | 
						|
								        return true;
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error("[PlatformServiceMixin] Error deleting contact:", error);
							 | 
						|
								        return false;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get all accounts - $getAllAccounts()
							 | 
						|
								     * Retrieves all account metadata from the accounts table
							 | 
						|
								     * @returns Promise<Account[]> Array of account objects
							 | 
						|
								     */
							 | 
						|
								    async $getAllAccounts(): Promise<Account[]> {
							 | 
						|
								      try {
							 | 
						|
								        return await this.$query<Account>("SELECT * FROM accounts");
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(
							 | 
						|
								          "[PlatformServiceMixin] Error getting all accounts:",
							 | 
						|
								          error,
							 | 
						|
								        );
							 | 
						|
								        return [];
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get all account DIDs - $getAllAccountDids()
							 | 
						|
								     * Retrieves all account DIDs from the accounts table
							 | 
						|
								     * @returns Promise<string[]> Array of account DIDs
							 | 
						|
								     */
							 | 
						|
								    async $getAllAccountDids(): Promise<string[]> {
							 | 
						|
								      try {
							 | 
						|
								        const result = await this.$dbQuery(
							 | 
						|
								          "SELECT did FROM accounts ORDER BY did",
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        if (!result?.values?.length) {
							 | 
						|
								          return [];
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        return result.values.map((row: SqlValue[]) => row[0] as string);
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(
							 | 
						|
								          "[PlatformServiceMixin] Error getting all account DIDs:",
							 | 
						|
								          error,
							 | 
						|
								        );
							 | 
						|
								        return [];
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    // =================================================
							 | 
						|
								    // TEMP TABLE METHODS (for temporary storage)
							 | 
						|
								    // =================================================
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get temporary data by ID - $getTemp()
							 | 
						|
								     * Retrieves temporary data from the temp table
							 | 
						|
								     * @param id Temporary storage ID
							 | 
						|
								     * @returns Promise<Temp | null> Temporary data or null if not found
							 | 
						|
								     */
							 | 
						|
								    async $getTemp(id: string): Promise<Temp | null> {
							 | 
						|
								      try {
							 | 
						|
								        return await this.$first<Temp>("SELECT * FROM temp WHERE id = ?", [id]);
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error("[PlatformServiceMixin] Error getting temp data:", error);
							 | 
						|
								        return null;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Delete temporary data by ID - $deleteTemp()
							 | 
						|
								     * Removes temporary data from the temp table
							 | 
						|
								     * @param id Temporary storage ID
							 | 
						|
								     * @returns Promise<boolean> Success status
							 | 
						|
								     */
							 | 
						|
								    async $deleteTemp(id: string): Promise<boolean> {
							 | 
						|
								      try {
							 | 
						|
								        await this.$dbExec("DELETE FROM temp WHERE id = ?", [id]);
							 | 
						|
								        return true;
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error("[PlatformServiceMixin] Error deleting temp data:", error);
							 | 
						|
								        return false;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Generic entity insertion - $insertEntity()
							 | 
						|
								     * Eliminates verbose INSERT patterns for any entity
							 | 
						|
								     * @param tableName Database table name
							 | 
						|
								     * @param entity Entity object to insert
							 | 
						|
								     * @param fields Array of field names to insert
							 | 
						|
								     * @returns Promise<boolean> Success status
							 | 
						|
								     */
							 | 
						|
								    async $insertEntity(
							 | 
						|
								      tableName: string,
							 | 
						|
								      entity: Record<string, unknown>,
							 | 
						|
								      fields: string[],
							 | 
						|
								    ): Promise<boolean> {
							 | 
						|
								      try {
							 | 
						|
								        const placeholders = fields.map(() => "?").join(", ");
							 | 
						|
								        // Convert undefined values to null for SQL.js compatibility
							 | 
						|
								        const values = fields.map((field) =>
							 | 
						|
								          entity[field] !== undefined ? entity[field] : null,
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        await this.$dbExec(
							 | 
						|
								          `INSERT OR REPLACE INTO ${tableName} (${fields.join(", ")}) VALUES (${placeholders})`,
							 | 
						|
								          values,
							 | 
						|
								        );
							 | 
						|
								        return true;
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(
							 | 
						|
								          `[PlatformServiceMixin] Error inserting entity into ${tableName}:`,
							 | 
						|
								          error,
							 | 
						|
								        );
							 | 
						|
								        return false;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Update settings with direct SQL - $updateSettings()
							 | 
						|
								     * Eliminates verbose settings update patterns
							 | 
						|
								     * @param changes Settings changes to apply
							 | 
						|
								     * @param did Optional DID for user-specific settings
							 | 
						|
								     * @returns Promise<boolean> Success status
							 | 
						|
								     */
							 | 
						|
								    /**
							 | 
						|
								     * Update settings - $updateSettings()
							 | 
						|
								     * Ultra-concise shortcut for updating settings (default or user-specific)
							 | 
						|
								     *
							 | 
						|
								     * ⚠️ DEPRECATED: This method will be removed in favor of $saveSettings()
							 | 
						|
								     * Use $saveSettings(changes, did?) instead for better consistency
							 | 
						|
								     *
							 | 
						|
								     * @param changes Settings changes to save
							 | 
						|
								     * @param did Optional DID for user-specific settings
							 | 
						|
								     * @returns Promise<boolean> Success status
							 | 
						|
								     */
							 | 
						|
								    async $updateSettings(
							 | 
						|
								      changes: Partial<Settings>,
							 | 
						|
								      did?: string,
							 | 
						|
								    ): Promise<boolean> {
							 | 
						|
								      try {
							 | 
						|
								        // Use self-contained methods which handle the correct schema
							 | 
						|
								        if (did) {
							 | 
						|
								          return await this.$saveUserSettings(did, changes);
							 | 
						|
								        } else {
							 | 
						|
								          return await this.$saveSettings(changes);
							 | 
						|
								        }
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error("[PlatformServiceMixin] Error updating settings:", error);
							 | 
						|
								        return false;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get settings row as array - $getSettingsRow()
							 | 
						|
								     * Eliminates verbose settings retrieval patterns
							 | 
						|
								     * @param fields Array of field names to retrieve
							 | 
						|
								     * @param did Optional DID for user-specific settings
							 | 
						|
								     * @returns Promise<unknown[]> Settings row as array
							 | 
						|
								     */
							 | 
						|
								    async $getSettingsRow(
							 | 
						|
								      fields: string[],
							 | 
						|
								      did?: string,
							 | 
						|
								    ): Promise<unknown[] | undefined> {
							 | 
						|
								      // Use current active DID if no specific DID provided
							 | 
						|
								      const targetDid = did || (await this.$getActiveIdentity()).activeDid;
							 | 
						|
								
							 | 
						|
								      if (!targetDid) {
							 | 
						|
								        return undefined;
							 | 
						|
								      }
							 | 
						|
								
							 | 
						|
								      return await this.$one(
							 | 
						|
								        `SELECT ${fields.join(", ")} FROM settings WHERE accountDid = ?`,
							 | 
						|
								        [targetDid],
							 | 
						|
								      );
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Update entity with direct SQL - $updateEntity()
							 | 
						|
								     * Eliminates verbose UPDATE patterns for any table
							 | 
						|
								     * @param tableName Name of the table to update
							 | 
						|
								     * @param entity Object containing fields to update
							 | 
						|
								     * @param whereClause WHERE clause for the update (e.g. "id = ?")
							 | 
						|
								     * @param whereParams Parameters for the WHERE clause
							 | 
						|
								     * @returns Promise<boolean> Success status
							 | 
						|
								     */
							 | 
						|
								    async $updateEntity(
							 | 
						|
								      tableName: string,
							 | 
						|
								      entity: Record<string, unknown>,
							 | 
						|
								      whereClause: string,
							 | 
						|
								      whereParams: unknown[],
							 | 
						|
								    ): Promise<boolean> {
							 | 
						|
								      try {
							 | 
						|
								        const setParts: string[] = [];
							 | 
						|
								        const params: unknown[] = [];
							 | 
						|
								
							 | 
						|
								        Object.entries(entity).forEach(([key, value]) => {
							 | 
						|
								          if (value !== undefined) {
							 | 
						|
								            setParts.push(`${key} = ?`);
							 | 
						|
								            // Convert values to SQLite-compatible types
							 | 
						|
								            let convertedValue = value ?? null;
							 | 
						|
								            if (convertedValue !== null) {
							 | 
						|
								              if (typeof convertedValue === "object") {
							 | 
						|
								                // Convert objects and arrays to JSON strings
							 | 
						|
								                convertedValue = JSON.stringify(convertedValue);
							 | 
						|
								              } else if (typeof convertedValue === "boolean") {
							 | 
						|
								                // Convert boolean to integer (0 or 1)
							 | 
						|
								                convertedValue = convertedValue ? 1 : 0;
							 | 
						|
								              }
							 | 
						|
								            }
							 | 
						|
								            params.push(convertedValue);
							 | 
						|
								          }
							 | 
						|
								        });
							 | 
						|
								
							 | 
						|
								        if (setParts.length === 0) return true;
							 | 
						|
								
							 | 
						|
								        const sql = `UPDATE ${tableName} SET ${setParts.join(", ")} WHERE ${whereClause}`;
							 | 
						|
								        await this.$dbExec(sql, [...params, ...whereParams]);
							 | 
						|
								        return true;
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(
							 | 
						|
								          `[PlatformServiceMixin] Error updating entity in ${tableName}:`,
							 | 
						|
								          error,
							 | 
						|
								        );
							 | 
						|
								        return false;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Insert user-specific settings - $insertUserSettings()
							 | 
						|
								     * Creates new settings record for a specific DID
							 | 
						|
								     * @param did DID identifier for the user
							 | 
						|
								     * @param settings Settings to insert (accountDid will be set automatically)
							 | 
						|
								     * @returns Promise<boolean> Success status
							 | 
						|
								     */
							 | 
						|
								    async $insertUserSettings(
							 | 
						|
								      did: string,
							 | 
						|
								      settings: Partial<Settings>,
							 | 
						|
								    ): Promise<boolean> {
							 | 
						|
								      try {
							 | 
						|
								        // Ensure accountDid is set and remove id to avoid conflicts
							 | 
						|
								        const { id, ...safeSettings } = settings;
							 | 
						|
								        // eslint-disable-next-line @typescript-eslint/no-unused-vars
							 | 
						|
								        void id;
							 | 
						|
								        const insertSettings = { ...safeSettings, accountDid: did };
							 | 
						|
								
							 | 
						|
								        // Convert to SQL-compatible values
							 | 
						|
								        const fields = Object.keys(insertSettings);
							 | 
						|
								        const values = fields.map((field) => {
							 | 
						|
								          const value = insertSettings[field as keyof typeof insertSettings];
							 | 
						|
								          if (value === undefined) return null;
							 | 
						|
								          if (typeof value === "object" && value !== null) {
							 | 
						|
								            return JSON.stringify(value);
							 | 
						|
								          }
							 | 
						|
								          if (typeof value === "boolean") {
							 | 
						|
								            return value ? 1 : 0;
							 | 
						|
								          }
							 | 
						|
								          return value;
							 | 
						|
								        });
							 | 
						|
								
							 | 
						|
								        const placeholders = fields.map(() => "?").join(", ");
							 | 
						|
								        await this.$dbExec(
							 | 
						|
								          `INSERT OR REPLACE INTO settings (${fields.join(", ")}) VALUES (${placeholders})`,
							 | 
						|
								          values,
							 | 
						|
								        );
							 | 
						|
								        return true;
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(
							 | 
						|
								          "[PlatformServiceMixin] Error inserting user settings:",
							 | 
						|
								          error,
							 | 
						|
								        );
							 | 
						|
								        return false;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    // =================================================
							 | 
						|
								    // LOGGING METHODS (convenience methods for components)
							 | 
						|
								    // =================================================
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Log message to database - $log()
							 | 
						|
								     * @param message Message to log
							 | 
						|
								     * @param level Log level (info, warn, error)
							 | 
						|
								     * @returns Promise<void>
							 | 
						|
								     */
							 | 
						|
								    async $log(message: string, level?: string): Promise<void> {
							 | 
						|
								      return logger.toDb(message, level);
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Log error message to database - $logError()
							 | 
						|
								     * @param message Error message to log
							 | 
						|
								     * @returns Promise<void>
							 | 
						|
								     */
							 | 
						|
								    async $logError(message: string): Promise<void> {
							 | 
						|
								      return logger.toDb(message, "error");
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Log message to console and database - $logAndConsole()
							 | 
						|
								     * @param message Message to log
							 | 
						|
								     * @param isError Whether this is an error message
							 | 
						|
								     * @returns Promise<void>
							 | 
						|
								     */
							 | 
						|
								    async $logAndConsole(message: string, isError = false): Promise<void> {
							 | 
						|
								      return logger.toConsoleAndDb(message, isError);
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    $appendToMemoryLogs(message: string): void {
							 | 
						|
								      _memoryLogs.push(`${new Date().toISOString()}: ${message}`);
							 | 
						|
								      if (_memoryLogs.length > 1000) {
							 | 
						|
								        _memoryLogs.splice(0, _memoryLogs.length - 1000);
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Public wrapper for generateInsertStatement
							 | 
						|
								     */
							 | 
						|
								    $generateInsertStatement(
							 | 
						|
								      model: Record<string, unknown>,
							 | 
						|
								      tableName: string,
							 | 
						|
								    ): { sql: string; params: unknown[] } {
							 | 
						|
								      return generateInsertStatement(model, tableName);
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Public wrapper for generateUpdateStatement
							 | 
						|
								     */
							 | 
						|
								    $generateUpdateStatement(
							 | 
						|
								      model: Record<string, unknown>,
							 | 
						|
								      tableName: string,
							 | 
						|
								      whereClause: string,
							 | 
						|
								      whereParams: unknown[] = [],
							 | 
						|
								    ): { sql: string; params: unknown[] } {
							 | 
						|
								      return generateUpdateStatement(
							 | 
						|
								        model,
							 | 
						|
								        tableName,
							 | 
						|
								        whereClause,
							 | 
						|
								        whereParams,
							 | 
						|
								      );
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Debug method to verify settings for a specific DID
							 | 
						|
								     * Useful for troubleshooting settings propagation issues
							 | 
						|
								     * @param did DID to check settings for
							 | 
						|
								     * @returns Promise<Settings | null> Settings object or null if not found
							 | 
						|
								     */
							 | 
						|
								    async $debugDidSettings(did: string): Promise<Settings | null> {
							 | 
						|
								      try {
							 | 
						|
								        const result = await this.$dbQuery(
							 | 
						|
								          "SELECT * FROM settings WHERE accountDid = ?",
							 | 
						|
								          [did],
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        if (!result?.values?.length) {
							 | 
						|
								          logger.warn(
							 | 
						|
								            `[PlatformServiceMixin] No settings found for DID: ${did}`,
							 | 
						|
								          );
							 | 
						|
								          return null;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        const mappedResults = this._mapColumnsToValues(
							 | 
						|
								          result.columns,
							 | 
						|
								          result.values,
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        if (!mappedResults.length) {
							 | 
						|
								          logger.warn(
							 | 
						|
								            `[PlatformServiceMixin] Failed to map settings for DID: ${did}`,
							 | 
						|
								          );
							 | 
						|
								          return null;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        const settings = mappedResults[0] as Settings;
							 | 
						|
								
							 | 
						|
								        logger.debug(`[PlatformServiceMixin] Settings for DID ${did}:`, {
							 | 
						|
								          firstName: settings.firstName,
							 | 
						|
								          isRegistered: settings.isRegistered,
							 | 
						|
								          activeDid: settings.activeDid,
							 | 
						|
								          apiServer: settings.apiServer,
							 | 
						|
								        });
							 | 
						|
								
							 | 
						|
								        return settings;
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(
							 | 
						|
								          `[PlatformServiceMixin] Error debugging settings for DID ${did}:`,
							 | 
						|
								          error,
							 | 
						|
								        );
							 | 
						|
								        return null;
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Debug method to verify merged settings for a specific DID
							 | 
						|
								     * Shows both default and DID-specific settings
							 | 
						|
								     * @param did DID to check merged settings for
							 | 
						|
								     * @returns Promise<void> Logs debug information
							 | 
						|
								     */
							 | 
						|
								    async $debugMergedSettings(did: string): Promise<void> {
							 | 
						|
								      try {
							 | 
						|
								        // Get default settings
							 | 
						|
								        const defaultSettings = await this._getMasterSettings({});
							 | 
						|
								        logger.debug(
							 | 
						|
								          `[PlatformServiceMixin] Default settings:`,
							 | 
						|
								          defaultSettings,
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        // Get DID-specific settings
							 | 
						|
								        const didSettings = await this.$debugDidSettings(did);
							 | 
						|
								
							 | 
						|
								        // Get merged settings
							 | 
						|
								        const mergedSettings = await this.$getMergedSettings(
							 | 
						|
								          did,
							 | 
						|
								          defaultSettings || {},
							 | 
						|
								        );
							 | 
						|
								
							 | 
						|
								        logger.debug(`[PlatformServiceMixin] Merged settings for ${did}:`, {
							 | 
						|
								          defaultSettings,
							 | 
						|
								          didSettings,
							 | 
						|
								          mergedSettings,
							 | 
						|
								          isRegistered: mergedSettings.isRegistered,
							 | 
						|
								        });
							 | 
						|
								      } catch (error) {
							 | 
						|
								        logger.error(
							 | 
						|
								          `[PlatformServiceMixin] Error debugging merged settings for DID ${did}:`,
							 | 
						|
								          error,
							 | 
						|
								        );
							 | 
						|
								      }
							 | 
						|
								    },
							 | 
						|
								  },
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								// =================================================
							 | 
						|
								// TYPESCRIPT INTERFACES
							 | 
						|
								// =================================================
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Enhanced interface with caching utility methods
							 | 
						|
								 */
							 | 
						|
								export interface IPlatformServiceMixin {
							 | 
						|
								  platformService: PlatformService;
							 | 
						|
								  $dbQuery(
							 | 
						|
								    sql: string,
							 | 
						|
								    params?: unknown[],
							 | 
						|
								  ): Promise<QueryExecResult | undefined>;
							 | 
						|
								  $dbExec(sql: string, params?: unknown[]): Promise<DatabaseExecResult>;
							 | 
						|
								  $dbGetOneRow(
							 | 
						|
								    sql: string,
							 | 
						|
								    params?: unknown[],
							 | 
						|
								  ): Promise<SqlValue[] | undefined>;
							 | 
						|
								  $dbRawQuery(sql: string, params?: unknown[]): Promise<unknown | undefined>;
							 | 
						|
								  $getMergedSettings(
							 | 
						|
								    defaultKey: string,
							 | 
						|
								    accountDid?: string,
							 | 
						|
								    defaultFallback?: Settings,
							 | 
						|
								  ): Promise<Settings>;
							 | 
						|
								  $getActiveIdentity(): Promise<{ activeDid: string }>;
							 | 
						|
								  $withTransaction<T>(callback: () => Promise<T>): Promise<T>;
							 | 
						|
								  $getAvailableAccountDids(): Promise<string[]>;
							 | 
						|
								  isCapacitor: boolean;
							 | 
						|
								  isWeb: boolean;
							 | 
						|
								  isElectron: boolean;
							 | 
						|
								  capabilities: PlatformCapabilities;
							 | 
						|
								
							 | 
						|
								  // High-level entity operations
							 | 
						|
								  $mapResults<T>(
							 | 
						|
								    results: QueryExecResult | undefined,
							 | 
						|
								    mapper: (row: unknown[]) => T,
							 | 
						|
								  ): T[];
							 | 
						|
								  $insertContact(contact: Partial<Contact>): Promise<boolean>;
							 | 
						|
								  $updateContact(did: string, changes: Partial<Contact>): Promise<boolean>;
							 | 
						|
								  $getAllContacts(): Promise<Contact[]>;
							 | 
						|
								  $getContact(did: string): Promise<Contact | null>;
							 | 
						|
								  $deleteContact(did: string): Promise<boolean>;
							 | 
						|
								  $contactCount(): Promise<number>;
							 | 
						|
								  $getAllAccounts(): Promise<Account[]>;
							 | 
						|
								  $getAllAccountDids(): Promise<string[]>;
							 | 
						|
								  $insertEntity(
							 | 
						|
								    tableName: string,
							 | 
						|
								    entity: Record<string, unknown>,
							 | 
						|
								    fields: string[],
							 | 
						|
								  ): Promise<boolean>;
							 | 
						|
								  $updateSettings(changes: Partial<Settings>, did?: string): Promise<boolean>;
							 | 
						|
								  $getSettingsRow(
							 | 
						|
								    fields: string[],
							 | 
						|
								    did?: string,
							 | 
						|
								  ): Promise<unknown[] | undefined>;
							 | 
						|
								  $updateEntity(
							 | 
						|
								    tableName: string,
							 | 
						|
								    entity: Record<string, unknown>,
							 | 
						|
								    whereClause: string,
							 | 
						|
								    whereParams: unknown[],
							 | 
						|
								  ): Promise<boolean>;
							 | 
						|
								  $insertUserSettings(
							 | 
						|
								    did: string,
							 | 
						|
								    settings: Partial<Settings>,
							 | 
						|
								  ): Promise<boolean>;
							 | 
						|
								  $getTemp(id: string): Promise<Temp | null>;
							 | 
						|
								  $deleteTemp(id: string): Promise<boolean>;
							 | 
						|
								
							 | 
						|
								  // Logging methods
							 | 
						|
								  $log(message: string, level?: string): Promise<void>;
							 | 
						|
								  $logError(message: string): Promise<void>;
							 | 
						|
								  $logAndConsole(message: string, isError?: boolean): Promise<void>;
							 | 
						|
								
							 | 
						|
								  // Memory logs access
							 | 
						|
								  $memoryLogs: string[];
							 | 
						|
								
							 | 
						|
								  // New additions
							 | 
						|
								  $logs(): Promise<Array<Record<string, unknown>>>;
							 | 
						|
								
							 | 
						|
								  // New additions
							 | 
						|
								  $generateInsertStatement(
							 | 
						|
								    model: Record<string, unknown>,
							 | 
						|
								    tableName: string,
							 | 
						|
								  ): { sql: string; params: unknown[] };
							 | 
						|
								  $generateUpdateStatement(
							 | 
						|
								    model: Record<string, unknown>,
							 | 
						|
								    tableName: string,
							 | 
						|
								    whereClause: string,
							 | 
						|
								    whereParams?: unknown[],
							 | 
						|
								  ): { sql: string; params: unknown[] };
							 | 
						|
								  $mapQueryResultToValues(
							 | 
						|
								    record: QueryExecResult | undefined,
							 | 
						|
								  ): Array<Record<string, unknown>>;
							 | 
						|
								  $mapColumnsToValues(
							 | 
						|
								    columns: string[],
							 | 
						|
								    values: unknown[][],
							 | 
						|
								  ): Array<Record<string, unknown>>;
							 | 
						|
								
							 | 
						|
								  // Debug methods
							 | 
						|
								  $debugDidSettings(did: string): Promise<Settings | null>;
							 | 
						|
								  $debugMergedSettings(did: string): Promise<void>;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// TypeScript declaration merging to eliminate (this as any) type assertions
							 | 
						|
								declare module "@vue/runtime-core" {
							 | 
						|
								  interface ComponentCustomProperties {
							 | 
						|
								    // Core platform service access
							 | 
						|
								    platformService: PlatformService;
							 | 
						|
								    isCapacitor: boolean;
							 | 
						|
								    isWeb: boolean;
							 | 
						|
								    isElectron: boolean;
							 | 
						|
								    capabilities: PlatformCapabilities;
							 | 
						|
								
							 | 
						|
								    // ActiveDid tracking
							 | 
						|
								    currentActiveDid: string | null;
							 | 
						|
								    $updateActiveDid(newDid: string | null): Promise<void>;
							 | 
						|
								
							 | 
						|
								    // Ultra-concise database methods (shortest possible names)
							 | 
						|
								    $db(sql: string, params?: unknown[]): Promise<QueryExecResult | undefined>;
							 | 
						|
								    $exec(sql: string, params?: unknown[]): Promise<DatabaseExecResult>;
							 | 
						|
								    $one(sql: string, params?: unknown[]): Promise<SqlValue[] | undefined>;
							 | 
						|
								
							 | 
						|
								    // Query + mapping combo methods
							 | 
						|
								    $query<T = Record<string, unknown>>(
							 | 
						|
								      sql: string,
							 | 
						|
								      params?: unknown[],
							 | 
						|
								    ): Promise<T[]>;
							 | 
						|
								    $first<T = Record<string, unknown>>(
							 | 
						|
								      sql: string,
							 | 
						|
								      params?: unknown[],
							 | 
						|
								    ): Promise<T | null>;
							 | 
						|
								
							 | 
						|
								    // Enhanced utility methods
							 | 
						|
								    $dbQuery(
							 | 
						|
								      sql: string,
							 | 
						|
								      params?: unknown[],
							 | 
						|
								    ): Promise<QueryExecResult | undefined>;
							 | 
						|
								    $dbExec(sql: string, params?: unknown[]): Promise<DatabaseExecResult>;
							 | 
						|
								    $dbGetOneRow(
							 | 
						|
								      sql: string,
							 | 
						|
								      params?: unknown[],
							 | 
						|
								    ): Promise<unknown[] | undefined>;
							 | 
						|
								    $dbRawQuery(sql: string, params?: unknown[]): Promise<unknown | undefined>;
							 | 
						|
								    $getMergedSettings(
							 | 
						|
								      key: string,
							 | 
						|
								      did?: string,
							 | 
						|
								      defaults?: Settings,
							 | 
						|
								    ): Promise<Settings>;
							 | 
						|
								    $getActiveIdentity(): Promise<{ activeDid: string }>;
							 | 
						|
								    $withTransaction<T>(fn: () => Promise<T>): Promise<T>;
							 | 
						|
								    $getAvailableAccountDids(): Promise<string[]>;
							 | 
						|
								
							 | 
						|
								    // Specialized shortcuts - contacts cached, settings fresh
							 | 
						|
								    $contacts(): Promise<Contact[]>;
							 | 
						|
								    $contactsByDateAdded(): Promise<Contact[]>;
							 | 
						|
								    $contactCount(): Promise<number>;
							 | 
						|
								    $settings(defaults?: Settings): Promise<Settings>;
							 | 
						|
								    $accountSettings(did?: string, defaults?: Settings): Promise<Settings>;
							 | 
						|
								    $normalizeContacts(rawContacts: ContactMaybeWithJsonStrings[]): Contact[];
							 | 
						|
								
							 | 
						|
								    // Settings update shortcuts (eliminate 90% boilerplate)
							 | 
						|
								    $saveSettings(changes: Partial<Settings>): Promise<boolean>;
							 | 
						|
								    $saveUserSettings(
							 | 
						|
								      did: string,
							 | 
						|
								      changes: Partial<Settings>,
							 | 
						|
								    ): Promise<boolean>;
							 | 
						|
								    // @deprecated; see implementation note above
							 | 
						|
								    // $saveMySettings(changes: Partial<Settings>): Promise<boolean>;
							 | 
						|
								
							 | 
						|
								    // Cache management methods
							 | 
						|
								    $refreshSettings(): Promise<Settings>;
							 | 
						|
								    $refreshContacts(): Promise<Contact[]>;
							 | 
						|
								    // $clearAllCaches(): void;
							 | 
						|
								
							 | 
						|
								    // High-level entity operations (eliminate verbose SQL patterns)
							 | 
						|
								    $mapResults<T>(
							 | 
						|
								      results: QueryExecResult | undefined,
							 | 
						|
								      mapper: (row: unknown[]) => T,
							 | 
						|
								    ): T[];
							 | 
						|
								    $insertContact(contact: Partial<Contact>): Promise<boolean>;
							 | 
						|
								    $updateContact(did: string, changes: Partial<Contact>): Promise<boolean>;
							 | 
						|
								    $getAllContacts(): Promise<Contact[]>;
							 | 
						|
								    $getContact(did: string): Promise<Contact | null>;
							 | 
						|
								    $deleteContact(did: string): Promise<boolean>;
							 | 
						|
								    $getAllAccounts(): Promise<Account[]>;
							 | 
						|
								    $getAllAccountDids(): Promise<string[]>;
							 | 
						|
								    $insertEntity(
							 | 
						|
								      tableName: string,
							 | 
						|
								      entity: Record<string, unknown>,
							 | 
						|
								      fields: string[],
							 | 
						|
								    ): Promise<boolean>;
							 | 
						|
								    $updateSettings(changes: Partial<Settings>, did?: string): Promise<boolean>;
							 | 
						|
								    $getSettingsRow(
							 | 
						|
								      fields: string[],
							 | 
						|
								      did?: string,
							 | 
						|
								    ): Promise<unknown[] | undefined>;
							 | 
						|
								    $updateEntity(
							 | 
						|
								      tableName: string,
							 | 
						|
								      entity: Record<string, unknown>,
							 | 
						|
								      whereClause: string,
							 | 
						|
								      whereParams: unknown[],
							 | 
						|
								    ): Promise<boolean>;
							 | 
						|
								    $insertUserSettings(
							 | 
						|
								      did: string,
							 | 
						|
								      settings: Partial<Settings>,
							 | 
						|
								    ): Promise<boolean>;
							 | 
						|
								    $getTemp(id: string): Promise<Temp | null>;
							 | 
						|
								    $deleteTemp(id: string): Promise<boolean>;
							 | 
						|
								
							 | 
						|
								    // Logging methods
							 | 
						|
								    $log(message: string, level?: string): Promise<void>;
							 | 
						|
								    $logError(message: string): Promise<void>;
							 | 
						|
								    $logAndConsole(message: string, isError?: boolean): Promise<void>;
							 | 
						|
								
							 | 
						|
								    // Memory logs access
							 | 
						|
								    $memoryLogs: string[];
							 | 
						|
								
							 | 
						|
								    // New additions
							 | 
						|
								    $logs(): Promise<Array<Record<string, unknown>>>;
							 | 
						|
								
							 | 
						|
								    // New additions
							 | 
						|
								    $generateInsertStatement(
							 | 
						|
								      model: Record<string, unknown>,
							 | 
						|
								      tableName: string,
							 | 
						|
								    ): { sql: string; params: unknown[] };
							 | 
						|
								    $generateUpdateStatement(
							 | 
						|
								      model: Record<string, unknown>,
							 | 
						|
								      tableName: string,
							 | 
						|
								      whereClause: string,
							 | 
						|
								      whereParams?: unknown[],
							 | 
						|
								    ): { sql: string; params: unknown[] };
							 | 
						|
								    $mapQueryResultToValues(
							 | 
						|
								      record: QueryExecResult | undefined,
							 | 
						|
								    ): Array<Record<string, unknown>>;
							 | 
						|
								    $mapColumnsToValues(
							 | 
						|
								      columns: string[],
							 | 
						|
								      values: unknown[][],
							 | 
						|
								    ): Array<Record<string, unknown>>;
							 | 
						|
								
							 | 
						|
								    // Debug methods
							 | 
						|
								    $debugDidSettings(did: string): Promise<Settings | null>;
							 | 
						|
								    $debugMergedSettings(did: string): Promise<void>;
							 | 
						|
								  }
							 | 
						|
								}
							 | 
						|
								
							 |