From 0f364cf8dc5377402f2a695f8b51a4801050647a Mon Sep 17 00:00:00 2001 From: Haroon Date: Thu, 5 Mar 2026 08:21:17 +0530 Subject: [PATCH 1/4] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20rename=20V?= =?UTF-8?q?FS=20type=20'memdb'=20to=20'memory'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PROJECT_SUMMARY.md | 171 +++++++++++++++++++------------------ QUICKSTART.md | 95 +++++++++++---------- README.md | 2 +- src/types/index.ts | 2 +- src/worker/sqliteWorker.ts | 4 +- 5 files changed, 144 insertions(+), 130 deletions(-) diff --git a/PROJECT_SUMMARY.md b/PROJECT_SUMMARY.md index f5aade9..1ad4cfa 100644 --- a/PROJECT_SUMMARY.md +++ b/PROJECT_SUMMARY.md @@ -2,11 +2,13 @@ ## Overview -**sqlite-wasm-easy** is a zero-configuration wrapper around `@sqlite.org/sqlite-wasm` that simplifies SQLite database usage in the browser. +**sqlite-wasm-easy** is a zero-configuration wrapper around `@sqlite.org/sqlite-wasm` that +simplifies SQLite database usage in the browser. ## ✅ What We Built ### Core Features + 1. **Zero Configuration** - Works out of the box with sensible defaults 2. **Fully Configurable** - VFS type, PRAGMA settings, logging options 3. **TypeScript First** - Complete type safety and IntelliSense @@ -53,32 +55,32 @@ All aspects are configurable with sensible defaults: ```typescript interface SQLiteWASMConfig { - filename: string; - vfs?: { - type?: 'opfs-sahpool' | 'opfs' | 'memdb'; - poolConfig?: { - initialCapacity?: number; // Default: 3 - clearOnInit?: boolean; // Default: false - name?: string; // Default: 'sqlite-wasm-pool' - }; - }; - pragma?: { - journal_mode?: JournalMode; // Default: 'WAL' - synchronous?: SynchronousMode; // Default: 'NORMAL' - temp_store?: TempStoreMode; // Default: 'MEMORY' - cache_size?: number; - page_size?: number; - foreign_keys?: 'ON' | 'OFF'; - [key: string]: any; // Any custom PRAGMA - }; - worker?: { - path?: string; // Custom worker path - }; - logging?: { - filterSqlTrace?: boolean; // Default: true - print?: (msg: string) => void; - printErr?: (msg: string) => void; - }; + filename: string; + vfs?: { + type?: 'opfs-sahpool' | 'opfs' | 'memory'; + poolConfig?: { + initialCapacity?: number; // Default: 3 + clearOnInit?: boolean; // Default: false + name?: string; // Default: 'sqlite-wasm-pool' + }; + }; + pragma?: { + journal_mode?: JournalMode; // Default: 'WAL' + synchronous?: SynchronousMode; // Default: 'NORMAL' + temp_store?: TempStoreMode; // Default: 'MEMORY' + cache_size?: number; + page_size?: number; + foreign_keys?: 'ON' | 'OFF'; + [key: string]: any; // Any custom PRAGMA + }; + worker?: { + path?: string; // Custom worker path + }; + logging?: { + filterSqlTrace?: boolean; // Default: true + print?: (msg: string) => void; + printErr?: (msg: string) => void; + }; } ``` @@ -88,16 +90,16 @@ Only high-level methods (no CRUD): ```typescript class SQLiteWASM { - ready(): Promise - exec(sql: string, params?: any[]): Promise - query(sql: string, params?: any[]): Promise - run(sql: string, params?: any[]): Promise - transaction(callback: (tx: Transaction) => Promise): Promise - table(name: K): TypedTable - export(): Promise - import(filename: string, data: Uint8Array): Promise - close(): Promise - delete(): Promise + ready(): Promise; + exec(sql: string, params?: any[]): Promise; + query(sql: string, params?: any[]): Promise; + run(sql: string, params?: any[]): Promise; + transaction(callback: (tx: Transaction) => Promise): Promise; + table(name: K): TypedTable; + export(): Promise; + import(filename: string, data: Uint8Array): Promise; + close(): Promise; + delete(): Promise; } ``` @@ -105,9 +107,9 @@ class SQLiteWASM { ```typescript interface TypedTable { - query(sql: string, params?: any[]): Promise - exec(sql: string, params?: any[]): Promise - run(sql: string, params?: any[]): Promise + query(sql: string, params?: any[]): Promise; + exec(sql: string, params?: any[]): Promise; + run(sql: string, params?: any[]): Promise; } ``` @@ -131,23 +133,23 @@ const users = await db.query('SELECT * FROM users'); ```typescript const db = new SQLiteWASM({ - filename: 'myapp.db', - vfs: { - type: 'opfs-sahpool', - poolConfig: { - initialCapacity: 5, - clearOnInit: false, - name: 'custom-pool' - } - }, - pragma: { - journal_mode: 'WAL', - synchronous: 'FULL', - foreign_keys: 'ON' - }, - logging: { - filterSqlTrace: true - } + filename: 'myapp.db', + vfs: { + type: 'opfs-sahpool', + poolConfig: { + initialCapacity: 5, + clearOnInit: false, + name: 'custom-pool', + }, + }, + pragma: { + journal_mode: 'WAL', + synchronous: 'FULL', + foreign_keys: 'ON', + }, + logging: { + filterSqlTrace: true, + }, }); ``` @@ -155,8 +157,8 @@ const db = new SQLiteWASM({ ```typescript interface Schema { - users: { id: number; name: string; email: string }; - posts: { id: number; userId: number; title: string }; + users: { id: number; name: string; email: string }; + posts: { id: number; userId: number; title: string }; } const db = new SQLiteWASM({ filename: 'app.db' }); @@ -171,54 +173,57 @@ const users = await usersTable.query('SELECT * FROM users'); ```typescript await db.transaction(async (tx) => { - await tx.exec('INSERT INTO users (name) VALUES (?)', ['Charlie']); - await tx.exec('UPDATE users SET active = 1 WHERE id = ?', [1]); + await tx.exec('INSERT INTO users (name) VALUES (?)', ['Charlie']); + await tx.exec('UPDATE users SET active = 1 WHERE id = ?', [1]); }); ``` ## Key Differences from Your Current Implementation -| Aspect | Current (Supersorted) | sqlite-wasm-easy | -|--------|----------------------|------------------| -| **Scope** | App-specific | General-purpose package | -| **Configuration** | Hardcoded values | Fully configurable | -| **Table API** | Full ORM-like (insert, update, delete, etc.) | Type hints only (query, exec, run) | -| **PRAGMA** | Hardcoded (MEMORY, NORMAL) | User configurable | -| **VFS** | Hardcoded opfs-sahpool | User can choose (opfs-sahpool, opfs, memdb) | -| **Pool Config** | Fixed (initialCapacity: 3) | Configurable | -| **Console Filtering** | Always on | Optional (configurable) | +| Aspect | Current (Supersorted) | sqlite-wasm-easy | +| --------------------- | -------------------------------------------- | -------------------------------------------- | +| **Scope** | App-specific | General-purpose package | +| **Configuration** | Hardcoded values | Fully configurable | +| **Table API** | Full ORM-like (insert, update, delete, etc.) | Type hints only (query, exec, run) | +| **PRAGMA** | Hardcoded (MEMORY, NORMAL) | User configurable | +| **VFS** | Hardcoded opfs-sahpool | User can choose (opfs-sahpool, opfs, memory) | +| **Pool Config** | Fixed (initialCapacity: 3) | Configurable | +| **Console Filtering** | Always on | Optional (configurable) | ## What's Configurable (vs Hardcoded Before) -✅ **VFS Method** - User chooses: opfs-sahpool, opfs, or memdb -✅ **Pool Settings** - initialCapacity, clearOnInit, name +✅ **VFS Method** - User chooses: opfs-sahpool, opfs, or memory ✅ **Pool Settings** - +initialCapacity, clearOnInit, name ✅ **PRAGMA Settings** - journal_mode, synchronous, temp_store, cache_size, etc. ✅ **Logging** - filterSqlTrace, custom print/printErr functions -✅ **Worker Path** - Custom worker location +✅ **Worker Path** - Custom worker location ## Build & Distribution ### Build Output + - Main bundle: `dist/index.js` (14.5 KB, gzipped: 5.5 KB) - Worker bundle: `dist/worker/sqliteWorker.js` (5 KB, gzipped: 1.6 KB) - TypeScript declarations: `dist/index.d.ts` ### NPM Package Structure + ```json { - "name": "sqlite-wasm-easy", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "exports": { - ".": "./dist/index.js", - "./worker": "./dist/worker/sqliteWorker.js" - } + "name": "sqlite-wasm-easy", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": "./dist/index.js", + "./worker": "./dist/worker/sqliteWorker.js" + } } ``` ## Next Steps ### For Development + ```bash cd sqlite-wasm-easy npm install @@ -227,10 +232,12 @@ npm run typecheck # Type checking only ``` ### For Testing + 1. Open `examples/basic.html` in a browser (via dev server) 2. Open `examples/typed-schema.html` for TypeScript examples ### For Publishing + ```bash # Test locally first npm pack @@ -253,14 +260,16 @@ npm publish ✅ Chrome/Edge 102+ ✅ Firefox (with OPFS support) -⚠️ Safari (experimental OPFS support) +⚠️ Safari (experimental OPFS support) ## Dependencies **Peer Dependencies:** + - `@sqlite.org/sqlite-wasm`: ^3.49.0 **Dev Dependencies:** + - `typescript`: ^5.7.3 - `vite`: ^6.1.0 diff --git a/QUICKSTART.md b/QUICKSTART.md index 6ab9e7e..1f59902 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -35,8 +35,7 @@ await db.exec(` `); // Insert data -await db.exec('INSERT INTO users (name, email) VALUES (?, ?)', - ['Alice', 'alice@example.com']); +await db.exec('INSERT INTO users (name, email) VALUES (?, ?)', ['Alice', 'alice@example.com']); // Query data const users = await db.query('SELECT * FROM users'); @@ -49,22 +48,22 @@ console.log(users); ### Insert with ID Return ```typescript -const result = await db.run( - 'INSERT INTO users (name, email) VALUES (?, ?)', - ['Bob', 'bob@example.com'] -); +const result = await db.run('INSERT INTO users (name, email) VALUES (?, ?)', [ + 'Bob', + 'bob@example.com', +]); console.log(result.lastInsertRowId); // 2 -console.log(result.changes); // 1 +console.log(result.changes); // 1 ``` ### Transactions ```typescript await db.transaction(async (tx) => { - await tx.exec('INSERT INTO users (name) VALUES (?)', ['Charlie']); - await tx.exec('INSERT INTO posts (userId, title) VALUES (?, ?)', [3, 'Hello']); - // Both succeed or both roll back + await tx.exec('INSERT INTO users (name) VALUES (?)', ['Charlie']); + await tx.exec('INSERT INTO posts (userId, title) VALUES (?, ?)', [3, 'Hello']); + // Both succeed or both roll back }); ``` @@ -72,7 +71,7 @@ await db.transaction(async (tx) => { ```typescript interface Schema { - users: { id: number; name: string; email: string }; + users: { id: number; name: string; email: string }; } const db = new SQLiteWASM({ filename: 'app.db' }); @@ -87,19 +86,19 @@ const users = await usersTable.query('SELECT * FROM users'); ```typescript const db = new SQLiteWASM({ - filename: 'myapp.db', - vfs: { - type: 'opfs-sahpool', // or 'opfs', 'memdb' - poolConfig: { - initialCapacity: 5, - name: 'my-custom-pool' - } - }, - pragma: { - journal_mode: 'WAL', // or 'DELETE', 'MEMORY', etc. - synchronous: 'NORMAL', // or 'OFF', 'FULL', 'EXTRA' - foreign_keys: 'ON' - } + filename: 'myapp.db', + vfs: { + type: 'opfs-sahpool', // or 'opfs', 'memory' + poolConfig: { + initialCapacity: 5, + name: 'my-custom-pool', + }, + }, + pragma: { + journal_mode: 'WAL', // or 'DELETE', 'MEMORY', etc. + synchronous: 'NORMAL', // or 'OFF', 'FULL', 'EXTRA' + foreign_keys: 'ON', + }, }); ``` @@ -129,21 +128,23 @@ await db.import('/myapp.db', data); ```typescript // Core operations -await db.exec(sql, params) // Execute without results -await db.query(sql, params) // Execute with results -await db.run(sql, params) // Execute with metadata +await db.exec(sql, params); // Execute without results +await db.query(sql, params); // Execute with results +await db.run(sql, params); // Execute with metadata // Transactions -await db.transaction(async (tx) => { /* ... */ }) +await db.transaction(async (tx) => { + /* ... */ +}); // Type hints -const table = db.table('tableName') +const table = db.table('tableName'); // Database management -await db.export() // Get database as Uint8Array -await db.import(filename, data) // Import database -await db.close() // Close connection -await db.delete() // Delete database +await db.export(); // Get database as Uint8Array +await db.import(filename, data); // Import database +await db.close(); // Close connection +await db.delete(); // Delete database ``` ## Configuration Options Reference @@ -151,18 +152,18 @@ await db.delete() // Delete database ```typescript { filename: string; // Required: database filename - + vfs?: { type?: 'opfs-sahpool' // Default: 'opfs-sahpool' - | 'opfs' - | 'memdb'; + | 'opfs' + | 'memory'; poolConfig?: { initialCapacity?: number; // Default: 3 clearOnInit?: boolean; // Default: false name?: string; // Default: 'sqlite-wasm-pool' }; }; - + pragma?: { journal_mode?: 'WAL' | ...; // Default: 'WAL' synchronous?: 'NORMAL' | ...; // Default: 'NORMAL' @@ -171,7 +172,7 @@ await db.delete() // Delete database foreign_keys?: 'ON' | 'OFF'; [key: string]: any; // Any custom PRAGMA }; - + logging?: { filterSqlTrace?: boolean; // Default: true print?: (msg: string) => void; @@ -189,34 +190,38 @@ await db.delete() // Delete database ## Troubleshooting ### Database not working? + ```typescript // Make sure to await ready() await db.ready(); ``` ### Worker not found? + ```typescript // Specify custom worker path if needed const db = new SQLiteWASM({ - filename: 'app.db', - worker: { path: '/custom/worker/path.js' } + filename: 'app.db', + worker: { path: '/custom/worker/path.js' }, }); ``` ### Want to see SQL logs? + ```typescript const db = new SQLiteWASM({ - filename: 'app.db', - logging: { - filterSqlTrace: false, // Show all SQL traces - print: (msg) => console.log('[DB]', msg) - } + filename: 'app.db', + logging: { + filterSqlTrace: false, // Show all SQL traces + print: (msg) => console.log('[DB]', msg), + }, }); ``` ## Examples See the `examples/` directory: + - `basic.html` - Interactive CRUD example - `typed-schema.html` - TypeScript schema example diff --git a/README.md b/README.md index 00be694..eedb7e9 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ Key interfaces for better TypeScript integration. interface SQLiteWASMConfig { filename: string; // Required: Database file name vfs?: { - type?: 'opfs' | 'opfs-sahpool' | 'memdb'; // Default: 'opfs' + type?: 'opfs' | 'opfs-sahpool' | 'memory'; // Default: 'opfs' poolConfig?: { // Only used when type is 'opfs-sahpool' initialCapacity?: number; // Default: 3 diff --git a/src/types/index.ts b/src/types/index.ts index c74a538..6ba0bc0 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,7 +1,7 @@ /** * VFS (Virtual File System) type options */ -export type VFSType = 'opfs-sahpool' | 'opfs' | 'memdb'; +export type VFSType = 'opfs-sahpool' | 'opfs' | 'memory'; /** * PRAGMA journal_mode options diff --git a/src/worker/sqliteWorker.ts b/src/worker/sqliteWorker.ts index 5b10038..cee49a1 100644 --- a/src/worker/sqliteWorker.ts +++ b/src/worker/sqliteWorker.ts @@ -52,7 +52,7 @@ async function initDatabase(config: SQLiteWASMConfig) { } else if (vfsType === 'opfs') { // Direct OPFS VFS (if available) PoolUtil = sqlite3.opfs || null; - } else if (vfsType === 'memdb') { + } else if (vfsType === 'memory') { // In-memory database PoolUtil = null; } @@ -69,7 +69,7 @@ async function openDatabase(filename: string) { flags: 'create', vfs: 'opfs-sahpool', }); - } else if (vfsType === 'memdb') { + } else if (vfsType === 'memory') { db = new sqlite3.oo1.DB(':memory:', 'c'); } else { // Check if OpfsDb is available (requires COOP/COEP headers) From 4d98ced6c482d1e16fd8f5168fcee0f72c47b374 Mon Sep 17 00:00:00 2001 From: Haroon Date: Thu, 5 Mar 2026 08:23:13 +0530 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=94=96=20chore:=20update=20package=20?= =?UTF-8?q?version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f104a18..1a22608 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@haroonwaves/sqlite-wasm-easy", - "version": "0.2.5", + "version": "0.2.6", "description": "A simple, zero-config wrapper around @sqlite.org/sqlite-wasm", "type": "module", "main": "./dist/index.js", From 85baf1dfd4770f25fbbe77774932132be126a867 Mon Sep 17 00:00:00 2001 From: Haroon Date: Thu, 5 Mar 2026 08:28:40 +0530 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=9A=A8=20fix:=20Update=20cspell=20con?= =?UTF-8?q?figuration=20to=20ignore=20`pnpm-lock.yaml`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cspell.config.yaml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cspell.config.yaml b/cspell.config.yaml index a280472..be04033 100644 --- a/cspell.config.yaml +++ b/cspell.config.yaml @@ -1,12 +1,14 @@ -version: "0.2" +version: '0.2' language: en allowCompoundWords: true useGitignore: true gitignoreRoot: . ignorePaths: - - "**/*.{png,jpg,jpeg,gif,svg,icns}" - - "**/*.min.*" + - '**/*.{png,jpg,jpeg,gif,svg,icns}' + - '**/*.min.*' + - 'pnpm-lock.yaml' words: + - COEP - eslint - haroonwaves - Hwaci @@ -15,6 +17,7 @@ words: - myapp - opfs - sahpool + - serializability - tsbuildinfo - tsconfig - tseslint From 05cc7bc8a8d30d7c1d9ebebaa45fd1899fc64931 Mon Sep 17 00:00:00 2001 From: Haroon Date: Thu, 5 Mar 2026 08:40:16 +0530 Subject: [PATCH 4/4] =?UTF-8?q?=E2=9C=A8=20feat:=20validate=20VFS=20type?= =?UTF-8?q?=20parameter=20by=20throwing=20an=20error=20for=20unsupported?= =?UTF-8?q?=20types.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/worker/sqliteWorker.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/worker/sqliteWorker.ts b/src/worker/sqliteWorker.ts index cee49a1..8c5afab 100644 --- a/src/worker/sqliteWorker.ts +++ b/src/worker/sqliteWorker.ts @@ -55,6 +55,8 @@ async function initDatabase(config: SQLiteWASMConfig) { } else if (vfsType === 'memory') { // In-memory database PoolUtil = null; + } else { + throw new Error(`Unsupported VFS type: ${vfsType}`); } }