docs: migrate web storage implementation from wa-sql to absurd-sql
- Update web platform storage solution to use absurd-sql with IndexedDB backend - Replace wa-sqlite dependencies with absurd-sql and @jlongster/sql.js - Update WebSQLiteService implementation with SQLiteFS and IndexedDBBackend - Add performance optimizations (WAL mode, mmap, temp store) - Add type-safe query method and improved error handling - Update platform capabilities matrix with new features - Add absurd-sql compatibility checks in migration service This change improves transaction support, performance, and reliability of the web platform's SQLite implementation.
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
This document outlines the implementation of secure storage for the TimeSafari app using Capacitor solutions. The implementation focuses on:
|
This document outlines the implementation of secure storage for the TimeSafari app using Capacitor solutions. The implementation focuses on:
|
||||||
|
|
||||||
1. **Platform-Specific Storage Solutions**:
|
1. **Platform-Specific Storage Solutions**:
|
||||||
- Web: wa-sqlite with IndexedDB backend
|
- Web: absurd-sql with IndexedDB backend
|
||||||
- iOS: SQLCipher with Keychain integration
|
- iOS: SQLCipher with Keychain integration
|
||||||
- Android: SQLCipher with Keystore integration
|
- Android: SQLCipher with Keystore integration
|
||||||
- Electron: SQLite with secure storage
|
- Electron: SQLite with secure storage
|
||||||
@@ -23,8 +23,8 @@ This document outlines the implementation of secure storage for the TimeSafari a
|
|||||||
```bash
|
```bash
|
||||||
# Core dependencies
|
# Core dependencies
|
||||||
npm install @capacitor-community/sqlite@6.0.0
|
npm install @capacitor-community/sqlite@6.0.0
|
||||||
npm install @wa-sqlite/sql.js@0.8.12
|
npm install absurd-sql@latest
|
||||||
npm install @wa-sqlite/sql.js-httpvfs@0.8.12
|
npm install @jlongster/sql.js@latest
|
||||||
|
|
||||||
# Platform-specific dependencies
|
# Platform-specific dependencies
|
||||||
npm install @capacitor/preferences@6.0.2
|
npm install @capacitor/preferences@6.0.2
|
||||||
@@ -218,13 +218,18 @@ try {
|
|||||||
|
|
||||||
### 4. Platform-Specific Implementations
|
### 4. Platform-Specific Implementations
|
||||||
|
|
||||||
#### Web Platform (wa-sqlite)
|
#### Web Platform (absurd-sql)
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// src/services/platforms/web/WebSQLiteService.ts
|
// src/services/platforms/web/WebSQLiteService.ts
|
||||||
|
import { initSqlJs } from '@jlongster/sql.js';
|
||||||
|
import { SQLiteFS } from 'absurd-sql';
|
||||||
|
import IndexedDBBackend from 'absurd-sql/dist/indexeddb-backend';
|
||||||
|
import { StorageError, StorageErrorCodes } from '../errors/StorageError';
|
||||||
|
|
||||||
export class WebSQLiteService implements PlatformService {
|
export class WebSQLiteService implements PlatformService {
|
||||||
private db: SQLite.Database | null = null;
|
private db: SQLite.Database | null = null;
|
||||||
private vfs: IDBBatchAtomicVFS | null = null;
|
private vfs: SQLiteFS | null = null;
|
||||||
private initialized = false;
|
private initialized = false;
|
||||||
|
|
||||||
async initialize(): Promise<void> {
|
async initialize(): Promise<void> {
|
||||||
@@ -258,8 +263,8 @@ export class WebSQLiteService implements PlatformService {
|
|||||||
|
|
||||||
private async initializeSQLite(): Promise<SQLite.SqlJsStatic> {
|
private async initializeSQLite(): Promise<SQLite.SqlJsStatic> {
|
||||||
try {
|
try {
|
||||||
return await SQLite.init({
|
return await initSqlJs({
|
||||||
locateFile: file => `https://cdn.jsdelivr.net/npm/@wa-sqlite/sql.js@0.8.12/dist/${file}`
|
locateFile: file => `https://cdn.jsdelivr.net/npm/@jlongster/sql.js@latest/dist/${file}`
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new StorageError(
|
throw new StorageError(
|
||||||
@@ -272,8 +277,14 @@ export class WebSQLiteService implements PlatformService {
|
|||||||
|
|
||||||
private async setupVFS(sqlite3: SQLite.SqlJsStatic): Promise<void> {
|
private async setupVFS(sqlite3: SQLite.SqlJsStatic): Promise<void> {
|
||||||
try {
|
try {
|
||||||
this.vfs = new IDBBatchAtomicVFS('timesafari');
|
// Initialize IndexedDB backend
|
||||||
await this.vfs.registerVFS(sqlite3);
|
const backend = new IndexedDBBackend();
|
||||||
|
|
||||||
|
// Create SQLiteFS instance
|
||||||
|
this.vfs = new SQLiteFS(backend, sqlite3);
|
||||||
|
|
||||||
|
// Register the VFS
|
||||||
|
sqlite3.register_for_idb(this.vfs);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new StorageError(
|
throw new StorageError(
|
||||||
'Failed to set up IndexedDB VFS',
|
'Failed to set up IndexedDB VFS',
|
||||||
@@ -292,6 +303,7 @@ export class WebSQLiteService implements PlatformService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Open database with absurd-sql
|
||||||
this.db = await this.vfs.openDatabase('timesafari.db');
|
this.db = await this.vfs.openDatabase('timesafari.db');
|
||||||
await this.setupPragmas();
|
await this.setupPragmas();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -312,6 +324,8 @@ export class WebSQLiteService implements PlatformService {
|
|||||||
PRAGMA synchronous = NORMAL;
|
PRAGMA synchronous = NORMAL;
|
||||||
PRAGMA foreign_keys = ON;
|
PRAGMA foreign_keys = ON;
|
||||||
PRAGMA busy_timeout = 5000;
|
PRAGMA busy_timeout = 5000;
|
||||||
|
PRAGMA temp_store = MEMORY;
|
||||||
|
PRAGMA mmap_size = 30000000000;
|
||||||
`);
|
`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new StorageError(
|
throw new StorageError(
|
||||||
@@ -329,6 +343,34 @@ export class WebSQLiteService implements PlatformService {
|
|||||||
}
|
}
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Example query method
|
||||||
|
async query<T>(sql: string, params: any[] = []): Promise<T[]> {
|
||||||
|
if (!this.db) {
|
||||||
|
throw new StorageError(
|
||||||
|
'Database not initialized',
|
||||||
|
StorageErrorCodes.INITIALIZATION_FAILED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const stmt = this.db.prepare(sql);
|
||||||
|
const results: T[] = [];
|
||||||
|
|
||||||
|
while (stmt.step()) {
|
||||||
|
results.push(stmt.getAsObject() as T);
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt.free();
|
||||||
|
return results;
|
||||||
|
} catch (error) {
|
||||||
|
throw new StorageError(
|
||||||
|
'Query failed',
|
||||||
|
StorageErrorCodes.QUERY_FAILED,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migration strategy for web platform
|
// Migration strategy for web platform
|
||||||
@@ -369,6 +411,14 @@ export class WebMigrationService {
|
|||||||
StorageErrorCodes.INITIALIZATION_FAILED
|
StorageErrorCodes.INITIALIZATION_FAILED
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check absurd-sql compatibility
|
||||||
|
if (!window.indexedDB.databases) {
|
||||||
|
throw new StorageError(
|
||||||
|
'Browser does not support required IndexedDB features',
|
||||||
|
StorageErrorCodes.INITIALIZATION_FAILED
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createBackup(): Promise<MigrationBackup> {
|
private async createBackup(): Promise<MigrationBackup> {
|
||||||
@@ -916,7 +966,7 @@ CREATE INDEX idx_settings_updated_at ON settings(updated_at);
|
|||||||
|
|
||||||
| Feature | Web | iOS | Android | Electron |
|
| Feature | Web | iOS | Android | Electron |
|
||||||
|---------|-----|-----|---------|----------|
|
|---------|-----|-----|---------|----------|
|
||||||
| SQLite | wa-sqlite | SQLCipher | SQLCipher | SQLite |
|
| SQLite | absurd-sql | SQLCipher | SQLCipher | SQLite |
|
||||||
| Encryption | SQLCipher | SQLCipher | SQLCipher | SQLCipher |
|
| Encryption | SQLCipher | SQLCipher | SQLCipher | SQLCipher |
|
||||||
| Secure Storage | IndexedDB | Keychain | Keystore | Secure Storage |
|
| Secure Storage | IndexedDB | Keychain | Keystore | Secure Storage |
|
||||||
| Biometrics | No | Yes | Yes | No |
|
| Biometrics | No | Yes | Yes | No |
|
||||||
@@ -924,6 +974,8 @@ CREATE INDEX idx_settings_updated_at ON settings(updated_at);
|
|||||||
| Background Sync | No | Yes | Yes | Yes |
|
| Background Sync | No | Yes | Yes | Yes |
|
||||||
| Storage Quota | Yes | No | No | No |
|
| Storage Quota | Yes | No | No | No |
|
||||||
| Multi-tab Support | Yes | N/A | N/A | Yes |
|
| Multi-tab Support | Yes | N/A | N/A | Yes |
|
||||||
|
| WAL Mode | Yes | Yes | Yes | Yes |
|
||||||
|
| Atomic Transactions | Yes | Yes | Yes | Yes |
|
||||||
|
|
||||||
### D. Usage Examples
|
### D. Usage Examples
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user