5.9 KiB

Electron App Migration Strategy

Overview

This document outlines the migration strategy for the TimeSafari Electron app, focusing on the transition from web-based storage to native SQLite implementation while maintaining cross-platform compatibility.

Current Architecture

1. Platform Services

  • ElectronPlatformService: Implements platform-specific features for desktop
  • Uses @capacitor-community/sqlite for database operations
  • Maintains compatibility with web/mobile platforms through shared interfaces

2. Database Implementation

  • SQLite with native Node.js backend
  • WAL journal mode for better concurrency
  • Connection pooling for performance
  • Migration system for schema updates
  • Secure file permissions (0o755)

3. Build Process

# Development
npm run dev:electron

# Production Build
npm run build:web
npm run build:electron
npm run electron:build-linux  # or electron:build-mac

Migration Goals

  1. Data Integrity

    • Preserve existing data during migration
    • Maintain data relationships
    • Ensure ACID compliance
    • Implement proper backup/restore
  2. Performance

    • Optimize SQLite configuration
    • Implement connection pooling
    • Use WAL journal mode
    • Configure optimal PRAGMA settings
  3. Security

    • Secure file permissions
    • Proper IPC communication
    • Context isolation
    • Safe preload scripts
  4. User Experience

    • Zero data loss
    • Automatic migration
    • Progress indicators
    • Error recovery

Implementation Details

1. Database Initialization

// electron/src/rt/sqlite-init.ts
export async function initializeSQLite() {
  // Set up database path with proper permissions
  const dbPath = path.join(app.getPath('userData'), 'timesafari.db');
  
  // Initialize SQLite plugin
  const sqlite = new CapacitorSQLite();
  
  // Configure database
  await sqlite.createConnection({
    database: 'timesafari',
    path: dbPath,
    encrypted: false,
    mode: 'no-encryption'
  });
  
  // Set optimal PRAGMA settings
  await sqlite.execute({
    database: 'timesafari',
    statements: [
      'PRAGMA journal_mode = WAL;',
      'PRAGMA synchronous = NORMAL;',
      'PRAGMA foreign_keys = ON;'
    ]
  });
}

2. Migration System

// electron/src/rt/sqlite-migrations.ts
interface Migration {
  version: number;
  name: string;
  description: string;
  sql: string;
  rollback?: string;
}

async function runMigrations(plugin: any, database: string) {
  // Track migration state
  const state = await getMigrationState(plugin, database);
  
  // Execute migrations in transaction
  for (const migration of pendingMigrations) {
    await executeMigration(plugin, database, migration);
  }
}

3. Platform Service Implementation

// src/services/platforms/ElectronPlatformService.ts
export class ElectronPlatformService implements PlatformService {
  private sqlite: any;
  
  async dbQuery(sql: string, params: any[]): Promise<QueryExecResult> {
    return await this.sqlite.execute({
      database: 'timesafari',
      statements: [{ statement: sql, values: params }]
    });
  }
}

4. Preload Script

// electron/preload.ts
contextBridge.exposeInMainWorld('electron', {
  sqlite: {
    isAvailable: () => ipcRenderer.invoke('sqlite:isAvailable'),
    execute: (method: string, ...args: unknown[]) => 
      ipcRenderer.invoke('sqlite:execute', method, ...args)
  },
  getPath: (pathType: string) => ipcRenderer.invoke('get-path', pathType),
  env: {
    platform: 'electron'
  }
});

Build Configuration

1. Vite Configuration

// vite.config.app.electron.mts
export default defineConfig({
  build: {
    outDir: 'dist',
    emptyOutDir: true
  },
  define: {
    'process.env.VITE_PLATFORM': JSON.stringify('electron'),
    'process.env.VITE_PWA_ENABLED': JSON.stringify(false)
  }
});

2. Package Scripts

{
  "scripts": {
    "dev:electron": "vite build --watch --config vite.config.app.electron.mts",
    "build:electron": "vite build --config vite.config.app.electron.mts",
    "electron:build-linux": "electron-builder --linux",
    "electron:build-mac": "electron-builder --mac"
  }
}

Testing Strategy

  1. Unit Tests

    • Database operations
    • Migration system
    • Platform service methods
    • IPC communication
  2. Integration Tests

    • Full migration process
    • Data integrity verification
    • Cross-platform compatibility
    • Error recovery
  3. End-to-End Tests

    • User workflows
    • Data persistence
    • UI interactions
    • Platform-specific features

Error Handling

  1. Database Errors

    • Connection failures
    • Migration errors
    • Query execution errors
    • Transaction failures
  2. Platform Errors

    • File system errors
    • IPC communication errors
    • Permission issues
    • Resource constraints
  3. Recovery Mechanisms

    • Automatic retry logic
    • Transaction rollback
    • State verification
    • User notifications

Security Considerations

  1. File System

    • Secure file permissions
    • Path validation
    • Access control
    • Data encryption
  2. IPC Communication

    • Context isolation
    • Channel validation
    • Data sanitization
    • Error handling
  3. Preload Scripts

    • Minimal API exposure
    • Type safety
    • Input validation
    • Error boundaries

Future Improvements

  1. Performance

    • Query optimization
    • Index tuning
    • Connection management
    • Cache implementation
  2. Features

    • Offline support
    • Sync capabilities
    • Backup/restore
    • Data export/import
  3. Security

    • Database encryption
    • Secure storage
    • Access control
    • Audit logging

Maintenance

  1. Regular Tasks

    • Database optimization
    • Log rotation
    • Error monitoring
    • Performance tracking
  2. Updates

    • Dependency updates
    • Security patches
    • Feature additions
    • Bug fixes
  3. Documentation

    • API documentation
    • Migration guides
    • Troubleshooting
    • Best practices