@korajs/store 1.0.0-beta.4 → 1.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/better-sqlite3.d.cts +1 -1
- package/dist/adapters/better-sqlite3.d.ts +1 -1
- package/dist/adapters/indexeddb.cjs +4 -1
- package/dist/adapters/indexeddb.cjs.map +1 -1
- package/dist/adapters/indexeddb.d.cts +2 -2
- package/dist/adapters/indexeddb.d.ts +2 -2
- package/dist/adapters/indexeddb.js +1 -1
- package/dist/adapters/sqlite-wasm-shared-host.cjs +292 -42
- package/dist/adapters/sqlite-wasm-shared-host.cjs.map +1 -1
- package/dist/adapters/sqlite-wasm-shared-host.d.cts +43 -25
- package/dist/adapters/sqlite-wasm-shared-host.d.ts +43 -25
- package/dist/adapters/sqlite-wasm-shared-host.js +33 -42
- package/dist/adapters/sqlite-wasm-shared-host.js.map +1 -1
- package/dist/adapters/sqlite-wasm-worker.cjs +206 -208
- package/dist/adapters/sqlite-wasm-worker.cjs.map +1 -1
- package/dist/adapters/sqlite-wasm-worker.js +8 -257
- package/dist/adapters/sqlite-wasm-worker.js.map +1 -1
- package/dist/adapters/sqlite-wasm.cjs +4 -1
- package/dist/adapters/sqlite-wasm.cjs.map +1 -1
- package/dist/adapters/sqlite-wasm.d.cts +3 -3
- package/dist/adapters/sqlite-wasm.d.ts +3 -3
- package/dist/adapters/sqlite-wasm.js +1 -1
- package/dist/{backup-IQE4QC7Q.js → backup-5S7K2Z35.js} +3 -3
- package/dist/chunk-3Y2IERBF.js +255 -0
- package/dist/chunk-3Y2IERBF.js.map +1 -0
- package/dist/{chunk-RCTG3IJG.js → chunk-CYO3YKFL.js} +2 -2
- package/dist/{chunk-6NKLDBTY.js → chunk-GSJ7EEUC.js} +2 -1
- package/dist/chunk-GSJ7EEUC.js.map +1 -0
- package/dist/{chunk-OCOGQRHW.js → chunk-HS6DBMST.js} +2 -2
- package/dist/{chunk-2ZRQGFEF.js → chunk-Q57CHIIN.js} +5 -2
- package/dist/chunk-Q57CHIIN.js.map +1 -0
- package/dist/{chunk-UXRWVXBP.js → chunk-RL43UYQZ.js} +2 -2
- package/dist/{export-audit-MT2LTMIN.js → export-audit-ODGQTQIK.js} +3 -3
- package/dist/index.cjs +120 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -4
- package/dist/index.d.ts +27 -4
- package/dist/index.js +128 -11
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +1 -0
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +3 -3
- package/dist/internal.d.ts +3 -3
- package/dist/internal.js +2 -2
- package/dist/{sqlite-wasm-channel-CNHRf-m2.d.cts → sqlite-wasm-channel-Bx57s8Cq.d.cts} +1 -1
- package/dist/{sqlite-wasm-channel-CNHRf-m2.d.ts → sqlite-wasm-channel-Bx57s8Cq.d.ts} +1 -1
- package/dist/{types-5h4Hqcwc.d.ts → types-C1kigrWz.d.ts} +1 -1
- package/dist/{types-k6AZgiH4.d.ts → types-D1MzKVmk.d.cts} +10 -0
- package/dist/{types-k6AZgiH4.d.cts → types-D1MzKVmk.d.ts} +10 -0
- package/dist/{types-DfPiPwKr.d.cts → types-DAo9oduO.d.cts} +1 -1
- package/package.json +2 -2
- package/dist/chunk-2ZRQGFEF.js.map +0 -1
- package/dist/chunk-6NKLDBTY.js.map +0 -1
- /package/dist/{backup-IQE4QC7Q.js.map → backup-5S7K2Z35.js.map} +0 -0
- /package/dist/{chunk-RCTG3IJG.js.map → chunk-CYO3YKFL.js.map} +0 -0
- /package/dist/{chunk-OCOGQRHW.js.map → chunk-HS6DBMST.js.map} +0 -0
- /package/dist/{chunk-UXRWVXBP.js.map → chunk-RL43UYQZ.js.map} +0 -0
- /package/dist/{export-audit-MT2LTMIN.js.map → export-audit-ODGQTQIK.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/sqlite-wasm-worker.ts"],"sourcesContent":["/// <reference lib=\"webworker\" />\n/**\n * Web Worker script for running SQLite WASM.\n *\n * This file is intended to run inside a Web Worker in browsers.\n * It loads @sqlite.org/sqlite-wasm, initializes SQLite with OPFS persistence\n * (falling back to in-memory if unavailable), and processes messages from\n * the main thread via the WorkerRequest/WorkerResponse protocol.\n *\n * This script cannot be tested in Node.js — it is validated in E2E browser tests.\n */\n\nimport type { WorkerRequest, WorkerResponse } from './sqlite-wasm-channel'\n\ninterface SqliteDb {\n\texec(opts: {\n\t\tsql: string\n\t\tbind?: unknown[]\n\t\treturnValue?: string\n\t\trowMode?: string\n\t\tcallback?: (row: Record<string, unknown>) => void\n\t}): void\n\tclose(): void\n\tdeserialize?: (data: Uint8Array) => void\n}\n\ndeclare const self: DedicatedWorkerGlobalScope\n\nlet db: SqliteDb | null = null\nlet sqlite3Api: unknown = null\n\nfunction sendResponse(response: WorkerResponse): void {\n\tself.postMessage(response)\n}\n\nfunction handleExecute(id: number, sql: string, params?: unknown[]): void {\n\tif (!db) {\n\t\tsendResponse({ id, type: 'error', message: 'Database is not open', code: 'DB_NOT_OPEN' })\n\t\treturn\n\t}\n\ttry {\n\t\tdb.exec({ sql, bind: params })\n\t\tsendResponse({ id, type: 'success' })\n\t} catch (error) {\n\t\tsendResponse({ id, type: 'error', message: (error as Error).message, code: 'EXEC_ERROR' })\n\t}\n}\n\nfunction handleQuery(id: number, sql: string, params?: unknown[]): void {\n\tif (!db) {\n\t\tsendResponse({ id, type: 'error', message: 'Database is not open', code: 'DB_NOT_OPEN' })\n\t\treturn\n\t}\n\ttry {\n\t\tconst rows: Record<string, unknown>[] = []\n\t\tdb.exec({\n\t\t\tsql,\n\t\t\tbind: params,\n\t\t\trowMode: 'object',\n\t\t\tcallback: (row: Record<string, unknown>) => {\n\t\t\t\trows.push({ ...row })\n\t\t\t},\n\t\t})\n\t\tsendResponse({ id, type: 'success', data: rows })\n\t} catch (error) {\n\t\tsendResponse({ id, type: 'error', message: (error as Error).message, code: 'QUERY_ERROR' })\n\t}\n}\n\nfunction opfsDatabaseFilename(dbName: string): string {\n\tconst base = dbName.replace(/[^a-zA-Z0-9._-]/g, '_')\n\treturn base.endsWith('.db') ? base : `${base}.db`\n}\n\n/** Headless browsers and some profiles hang on OPFS VFS install; fall back to memory. */\nconst OPFS_INIT_TIMEOUT_MS = 10_000\n\nasync function withTimeout<T>(promise: Promise<T>, timeoutMs: number, label: string): Promise<T> {\n\tlet timer: ReturnType<typeof setTimeout> | undefined\n\ttry {\n\t\treturn await Promise.race([\n\t\t\tpromise,\n\t\t\tnew Promise<T>((_, reject) => {\n\t\t\t\ttimer = setTimeout(\n\t\t\t\t\t() => reject(new Error(`${label} timed out after ${timeoutMs}ms`)),\n\t\t\t\t\ttimeoutMs,\n\t\t\t\t)\n\t\t\t}),\n\t\t])\n\t} finally {\n\t\tif (timer !== undefined) clearTimeout(timer)\n\t}\n}\n\nasync function handleOpen(id: number, ddlStatements: string[], dbName?: string): Promise<void> {\n\ttry {\n\t\tconst sqlite3InitModule = (await import('@sqlite.org/sqlite-wasm')).default\n\n\t\t// In production builds, Vite hashes asset filenames (e.g. sqlite3-[hash].wasm).\n\t\t// The sqlite3 module's default locateFile resolves the unhashed name, causing a 404.\n\t\t// Templates set __KORA_SQLITE_WASM_URL via `import wasmUrl from '...sqlite3.wasm?url'`\n\t\t// so we can override locateFile with the correct hashed URL.\n\t\tconst wasmUrl = (globalThis as Record<string, unknown>).__KORA_SQLITE_WASM_URL as\n\t\t\t| string\n\t\t\t| undefined\n\t\tconst initOptions = wasmUrl\n\t\t\t? {\n\t\t\t\t\tlocateFile: (file: string) => {\n\t\t\t\t\t\tif (file.endsWith('.wasm')) return wasmUrl\n\t\t\t\t\t\treturn file\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: undefined\n\n\t\t// sqlite3InitModule accepts Emscripten Module overrides but the types don't reflect this\n\t\tconst initFn = sqlite3InitModule as unknown as (\n\t\t\topts?: Record<string, unknown>,\n\t\t) => Promise<unknown>\n\t\tconst sqlite3 = (await withTimeout(\n\t\t\tinitFn(initOptions),\n\t\t\t60_000,\n\t\t\t'SQLite3 module init',\n\t\t)) as Awaited<ReturnType<typeof sqlite3InitModule>>\n\t\tsqlite3Api = sqlite3\n\n\t\t// Try OPFS persistence first\n\t\tlet useOpfs = false\n\t\tlet fallbackReason: 'lock-conflict' | 'timeout' | 'unsupported' | undefined\n\t\tif (sqlite3.installOpfsSAHPoolVfs) {\n\t\t\ttry {\n\t\t\t\tconst pool = await withTimeout(\n\t\t\t\t\tsqlite3.installOpfsSAHPoolVfs({ name: 'kora-opfs' }),\n\t\t\t\t\tOPFS_INIT_TIMEOUT_MS,\n\t\t\t\t\t'OPFS VFS install',\n\t\t\t\t)\n\t\t\t\tdb = new pool.OpfsSAHPoolDb(opfsDatabaseFilename(dbName ?? 'kora-db'))\n\t\t\t\tuseOpfs = true\n\t\t\t} catch (error) {\n\t\t\t\t// OPFS unavailable. Classify WHY so the main thread can surface a clear\n\t\t\t\t// diagnostic instead of a silent, non-persistent in-memory fallback that\n\t\t\t\t// loses the user's data on reload.\n\t\t\t\tfallbackReason = classifyOpfsFailure(error)\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[kora] OPFS unavailable (${fallbackReason}), falling back to in-memory SQLite`,\n\t\t\t\t)\n\t\t\t}\n\t\t} else {\n\t\t\tfallbackReason = 'unsupported'\n\t\t}\n\n\t\tif (!useOpfs) {\n\t\t\tdb = new sqlite3.oo1.DB({ filename: ':memory:' })\n\t\t}\n\n\t\t// Set pragmas\n\t\tdb?.exec({ sql: 'PRAGMA journal_mode = WAL' })\n\t\tdb?.exec({ sql: 'PRAGMA foreign_keys = ON' })\n\n\t\t// Execute DDL statements\n\t\tfor (const sql of ddlStatements) {\n\t\t\tif (sql.startsWith('--kora:safe-alter')) {\n\t\t\t\t// Safe ALTER TABLE — ignore \"duplicate column name\" errors for existing columns\n\t\t\t\ttry {\n\t\t\t\t\tdb?.exec({ sql: sql.replace('--kora:safe-alter\\n', '') })\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconst msg = (e as Error).message || ''\n\t\t\t\t\tif (!msg.includes('duplicate column name')) {\n\t\t\t\t\t\tthrow e\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdb?.exec({ sql })\n\t\t\t}\n\t\t}\n\n\t\t// Report the storage mode so the adapter can emit `store:opfs-unavailable`\n\t\t// when persistence silently degraded to in-memory.\n\t\tsendResponse({\n\t\t\tid,\n\t\t\ttype: 'success',\n\t\t\tdata: { persistent: useOpfs, ...(fallbackReason ? { fallbackReason } : {}) },\n\t\t})\n\t} catch (error) {\n\t\tsendResponse({\n\t\t\tid,\n\t\t\ttype: 'error',\n\t\t\tmessage: (error as Error).message,\n\t\t\tcode: 'INIT_ERROR',\n\t\t})\n\t}\n}\n\n/**\n * Classify why the OPFS SyncAccessHandle pool could not be installed, so the\n * fallback to in-memory is explainable rather than silent.\n *\n * A `lock-conflict` is the important case: another runtime on the same origin\n * (another tab or a logically separate app that reused the database name) already\n * holds the pool's access handles, so this runtime cannot persist.\n */\nfunction classifyOpfsFailure(error: unknown): 'lock-conflict' | 'timeout' | 'unsupported' {\n\tconst message = error instanceof Error ? error.message : String(error)\n\tif (/timed out|timeout/i.test(message)) {\n\t\treturn 'timeout'\n\t}\n\tif (\n\t\t/lock|already|in use|in-use|NoModificationAllowed|acquire|SyncAccessHandle|being created/i.test(\n\t\t\tmessage,\n\t\t)\n\t) {\n\t\treturn 'lock-conflict'\n\t}\n\treturn 'unsupported'\n}\n\nfunction handleClose(id: number): void {\n\tif (db) {\n\t\tdb.close()\n\t\tdb = null\n\t}\n\tsendResponse({ id, type: 'success' })\n}\n\nfunction handleImport(id: number, data: Uint8Array): void {\n\tif (!db) {\n\t\tsendResponse({ id, type: 'error', message: 'Database is not open', code: 'DB_NOT_OPEN' })\n\t\treturn\n\t}\n\n\tconst dbWithDeserialize = db as SqliteDb & { deserialize?: (bytes: Uint8Array) => void }\n\tif (typeof dbWithDeserialize.deserialize === 'function') {\n\t\ttry {\n\t\t\tdbWithDeserialize.deserialize(data)\n\t\t\tsendResponse({ id, type: 'success' })\n\t\t\treturn\n\t\t} catch (error) {\n\t\t\tsendResponse({ id, type: 'error', message: (error as Error).message, code: 'IMPORT_ERROR' })\n\t\t\treturn\n\t\t}\n\t}\n\n\tconst sqlite3 = sqlite3Api as {\n\t\too1?: { DB?: new (...args: unknown[]) => SqliteDb }\n\t\tcapi?: { sqlite3_deserialize?: unknown }\n\t} | null\n\n\tif (!sqlite3 || typeof sqlite3.capi?.sqlite3_deserialize === 'undefined') {\n\t\tsendResponse({\n\t\t\tid,\n\t\t\ttype: 'error',\n\t\t\tmessage: 'Import not supported in this SQLite WASM runtime',\n\t\t\tcode: 'IMPORT_NOT_SUPPORTED',\n\t\t})\n\t\treturn\n\t}\n\n\tsendResponse({\n\t\tid,\n\t\ttype: 'error',\n\t\tmessage:\n\t\t\t'Import requires runtime-specific deserialize wiring and is unavailable in this worker build',\n\t\tcode: 'IMPORT_NOT_SUPPORTED',\n\t})\n}\n\nfunction handleMessage(request: WorkerRequest): void {\n\ttry {\n\t\tswitch (request.type) {\n\t\t\tcase 'open':\n\t\t\t\t// open is async due to WASM loading\n\t\t\t\thandleOpen(request.id, request.ddlStatements, request.dbName)\n\t\t\t\treturn\n\t\t\tcase 'close':\n\t\t\t\thandleClose(request.id)\n\t\t\t\treturn\n\t\t\tcase 'execute':\n\t\t\t\thandleExecute(request.id, request.sql, request.params)\n\t\t\t\treturn\n\t\t\tcase 'query':\n\t\t\t\thandleQuery(request.id, request.sql, request.params)\n\t\t\t\treturn\n\t\t\tcase 'begin':\n\t\t\t\thandleExecute(request.id, 'BEGIN')\n\t\t\t\treturn\n\t\t\tcase 'commit':\n\t\t\t\thandleExecute(request.id, 'COMMIT')\n\t\t\t\treturn\n\t\t\tcase 'rollback':\n\t\t\t\thandleExecute(request.id, 'ROLLBACK')\n\t\t\t\treturn\n\t\t\tcase 'migrate':\n\t\t\t\tif (!db) {\n\t\t\t\t\tsendResponse({\n\t\t\t\t\t\tid: request.id,\n\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\tmessage: 'Database is not open',\n\t\t\t\t\t\tcode: 'DB_NOT_OPEN',\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tfor (const sql of request.statements) {\n\t\t\t\t\t\tdb.exec({ sql })\n\t\t\t\t\t}\n\t\t\t\t\tsendResponse({ id: request.id, type: 'success' })\n\t\t\t\t} catch (error) {\n\t\t\t\t\tsendResponse({\n\t\t\t\t\t\tid: request.id,\n\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\tmessage: (error as Error).message,\n\t\t\t\t\t\tcode: 'MIGRATE_ERROR',\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\tcase 'export':\n\t\t\t\t// Export is not trivially supported via the oo1 API in the browser.\n\t\t\t\t// In a real implementation, we'd use the C API's sqlite3_serialize.\n\t\t\t\tsendResponse({\n\t\t\t\t\tid: request.id,\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tmessage: 'Export not yet supported in browser worker',\n\t\t\t\t\tcode: 'EXPORT_NOT_SUPPORTED',\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\tcase 'import':\n\t\t\t\thandleImport(request.id, request.data)\n\t\t\t\treturn\n\t\t\tdefault:\n\t\t\t\tsendResponse({\n\t\t\t\t\tid: (request as WorkerRequest).id,\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tmessage: 'Unknown request type',\n\t\t\t\t\tcode: 'UNKNOWN_REQUEST',\n\t\t\t\t})\n\t\t}\n\t} catch (error) {\n\t\tsendResponse({\n\t\t\tid: request.id,\n\t\t\ttype: 'error',\n\t\t\tmessage: (error as Error).message,\n\t\t\tcode: 'WORKER_ERROR',\n\t\t})\n\t}\n}\n\n// Listen for messages from the main thread\nself.onmessage = (event: MessageEvent<WorkerRequest>) => {\n\thandleMessage(event.data)\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/sqlite-wasm-worker-core.ts","../../src/adapters/sqlite-wasm-worker.ts"],"sourcesContent":["/// <reference lib=\"webworker\" />\n/**\n * Reusable SQLite WASM core, decoupled from any specific worker global.\n *\n * The dedicated worker ({@link file://./sqlite-wasm-worker.ts}) wires one core to\n * `self.onmessage`/`self.postMessage`. The SharedWorker host\n * ({@link file://./sqlite-wasm-shared-host.ts}) runs one core PER database inside\n * a single SharedWorker scope, because a SharedWorker cannot spawn a nested\n * `Worker` (the `Worker` constructor is not defined in `SharedWorkerGlobalScope`\n * in Chromium), so it must run SQLite directly.\n *\n * The WASM module and the OPFS SyncAccessHandle pool are cached at module scope\n * and shared across every core in the same worker/SharedWorker: the pool holds\n * multiple database files keyed by filename, so installing it once and opening\n * each database within it avoids the single-writer conflict that installing the\n * pool twice in one scope would cause.\n *\n * This file cannot be unit-tested in Node (no WASM/OPFS); it is exercised through\n * the browser E2E suite and its dispatch is covered via the shared-host tests.\n */\n\nimport type { WorkerRequest, WorkerResponse } from './sqlite-wasm-channel'\n\ninterface SqliteDb {\n\texec(opts: {\n\t\tsql: string\n\t\tbind?: unknown[]\n\t\treturnValue?: string\n\t\trowMode?: string\n\t\tcallback?: (row: Record<string, unknown>) => void\n\t}): void\n\tclose(): void\n\tdeserialize?: (data: Uint8Array) => void\n}\n\ninterface OpfsPool {\n\tOpfsSAHPoolDb: new (filename: string) => SqliteDb\n}\n\ninterface Sqlite3Api {\n\too1: { DB: new (opts: { filename: string }) => SqliteDb }\n\tinstallOpfsSAHPoolVfs?: (opts: { name: string }) => Promise<OpfsPool>\n\tcapi?: { sqlite3_deserialize?: unknown }\n}\n\n/** OPFS SAH pool name. Shared across all databases on the origin (the pool holds\n * multiple db files keyed by filename), so it must NOT be namespaced per database\n * or existing persisted data would be orphaned. */\nconst OPFS_POOL_NAME = 'kora-opfs'\n\n/** Headless browsers and some profiles hang on OPFS VFS install; fall back to memory. */\nconst OPFS_INIT_TIMEOUT_MS = 10_000\n\nasync function withTimeout<T>(promise: Promise<T>, timeoutMs: number, label: string): Promise<T> {\n\tlet timer: ReturnType<typeof setTimeout> | undefined\n\ttry {\n\t\treturn await Promise.race([\n\t\t\tpromise,\n\t\t\tnew Promise<T>((_, reject) => {\n\t\t\t\ttimer = setTimeout(\n\t\t\t\t\t() => reject(new Error(`${label} timed out after ${timeoutMs}ms`)),\n\t\t\t\t\ttimeoutMs,\n\t\t\t\t)\n\t\t\t}),\n\t\t])\n\t} finally {\n\t\tif (timer !== undefined) clearTimeout(timer)\n\t}\n}\n\nfunction opfsDatabaseFilename(dbName: string): string {\n\tconst base = dbName.replace(/[^a-zA-Z0-9._-]/g, '_')\n\treturn base.endsWith('.db') ? base : `${base}.db`\n}\n\n/**\n * Classify why the OPFS SyncAccessHandle pool could not be installed, so the\n * fallback to in-memory is explainable rather than silent.\n */\nfunction classifyOpfsFailure(error: unknown): 'lock-conflict' | 'timeout' | 'unsupported' {\n\tconst message = error instanceof Error ? error.message : String(error)\n\tif (/timed out|timeout/i.test(message)) {\n\t\treturn 'timeout'\n\t}\n\tif (\n\t\t/lock|already|in use|in-use|NoModificationAllowed|acquire|SyncAccessHandle|being created/i.test(\n\t\t\tmessage,\n\t\t)\n\t) {\n\t\treturn 'lock-conflict'\n\t}\n\treturn 'unsupported'\n}\n\n// Scope-global caches shared by every core in this worker/SharedWorker.\nlet sqlite3Promise: Promise<Sqlite3Api> | null = null\nlet opfsPoolPromise: Promise<OpfsPool | null> | null = null\nlet opfsFallbackReason: 'lock-conflict' | 'timeout' | 'unsupported' | undefined\n\nasync function loadSqlite3(): Promise<Sqlite3Api> {\n\tconst sqlite3InitModule = (await import('@sqlite.org/sqlite-wasm')).default\n\t// In production builds, Vite hashes asset filenames (e.g. sqlite3-[hash].wasm).\n\t// The sqlite3 module's default locateFile resolves the unhashed name, causing a\n\t// 404. The worker/host entry sets __KORA_SQLITE_WASM_URL via a `?url` import so\n\t// we can override locateFile with the correct hashed URL.\n\tconst wasmUrl = (globalThis as Record<string, unknown>).__KORA_SQLITE_WASM_URL as\n\t\t| string\n\t\t| undefined\n\tconst initOptions = wasmUrl\n\t\t? {\n\t\t\t\tlocateFile: (file: string): string => (file.endsWith('.wasm') ? wasmUrl : file),\n\t\t\t}\n\t\t: undefined\n\tconst initFn = sqlite3InitModule as unknown as (\n\t\topts?: Record<string, unknown>,\n\t) => Promise<unknown>\n\treturn (await withTimeout(initFn(initOptions), 60_000, 'SQLite3 module init')) as Sqlite3Api\n}\n\nfunction getSqlite3(): Promise<Sqlite3Api> {\n\tif (!sqlite3Promise) {\n\t\tsqlite3Promise = loadSqlite3()\n\t}\n\treturn sqlite3Promise\n}\n\nasync function installOpfsPool(sqlite3: Sqlite3Api): Promise<OpfsPool | null> {\n\tif (!sqlite3.installOpfsSAHPoolVfs) {\n\t\topfsFallbackReason = 'unsupported'\n\t\treturn null\n\t}\n\ttry {\n\t\treturn await withTimeout(\n\t\t\tsqlite3.installOpfsSAHPoolVfs({ name: OPFS_POOL_NAME }),\n\t\t\tOPFS_INIT_TIMEOUT_MS,\n\t\t\t'OPFS VFS install',\n\t\t)\n\t} catch (error) {\n\t\topfsFallbackReason = classifyOpfsFailure(error)\n\t\treturn null\n\t}\n}\n\nfunction getOpfsPool(sqlite3: Sqlite3Api): Promise<OpfsPool | null> {\n\tif (!opfsPoolPromise) {\n\t\topfsPoolPromise = installOpfsPool(sqlite3)\n\t}\n\treturn opfsPoolPromise\n}\n\n/** Handle to a single database, dispatching the worker protocol for it. */\nexport interface SqliteWasmCore {\n\thandle(request: WorkerRequest): Promise<WorkerResponse>\n}\n\n/**\n * Creates a core bound to one database. `handle` resolves with the response for\n * each request; the caller routes it back to whichever transport delivered the\n * request (the dedicated worker's `postMessage`, or a SharedWorker client port).\n */\nexport function createSqliteWasmCore(): SqliteWasmCore {\n\tlet db: SqliteDb | null = null\n\tlet sqlite3Api: Sqlite3Api | null = null\n\tlet persistent = false\n\n\tasync function open(\n\t\tid: number,\n\t\tddlStatements: string[],\n\t\tdbName?: string,\n\t): Promise<WorkerResponse> {\n\t\ttry {\n\t\t\t// A shared core (one per database in a SharedWorker) may receive `open`\n\t\t\t// from more than one tab. Re-run the idempotent DDL on the existing handle\n\t\t\t// rather than opening the database a second time.\n\t\t\tif (db) {\n\t\t\t\tapplyDdl(db, ddlStatements)\n\t\t\t\treturn { id, type: 'success', data: buildOpenData() }\n\t\t\t}\n\n\t\t\tconst sqlite3 = await getSqlite3()\n\t\t\tsqlite3Api = sqlite3\n\t\t\tconst pool = await getOpfsPool(sqlite3)\n\n\t\t\tif (pool) {\n\t\t\t\tdb = new pool.OpfsSAHPoolDb(opfsDatabaseFilename(dbName ?? 'kora-db'))\n\t\t\t\tpersistent = true\n\t\t\t} else {\n\t\t\t\tdb = new sqlite3.oo1.DB({ filename: ':memory:' })\n\t\t\t\tpersistent = false\n\t\t\t}\n\n\t\t\tdb.exec({ sql: 'PRAGMA journal_mode = WAL' })\n\t\t\tdb.exec({ sql: 'PRAGMA foreign_keys = ON' })\n\n\t\t\tapplyDdl(db, ddlStatements)\n\t\t\treturn { id, type: 'success', data: buildOpenData() }\n\t\t} catch (error) {\n\t\t\treturn { id, type: 'error', message: (error as Error).message, code: 'INIT_ERROR' }\n\t\t}\n\t}\n\n\tfunction buildOpenData(): { persistent: boolean; fallbackReason?: string } {\n\t\treturn {\n\t\t\tpersistent,\n\t\t\t...(persistent ? {} : { fallbackReason: opfsFallbackReason ?? 'unsupported' }),\n\t\t}\n\t}\n\n\tfunction applyDdl(target: SqliteDb, ddlStatements: string[]): void {\n\t\tfor (const sql of ddlStatements) {\n\t\t\tif (sql.startsWith('--kora:safe-alter')) {\n\t\t\t\ttry {\n\t\t\t\t\ttarget.exec({ sql: sql.replace('--kora:safe-alter\\n', '') })\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst msg = (error as Error).message || ''\n\t\t\t\t\tif (!msg.includes('duplicate column name')) {\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttarget.exec({ sql })\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction execute(id: number, sql: string, params?: unknown[]): WorkerResponse {\n\t\tif (!db) {\n\t\t\treturn { id, type: 'error', message: 'Database is not open', code: 'DB_NOT_OPEN' }\n\t\t}\n\t\ttry {\n\t\t\tdb.exec({ sql, bind: params })\n\t\t\treturn { id, type: 'success' }\n\t\t} catch (error) {\n\t\t\treturn { id, type: 'error', message: (error as Error).message, code: 'EXEC_ERROR' }\n\t\t}\n\t}\n\n\tfunction query(id: number, sql: string, params?: unknown[]): WorkerResponse {\n\t\tif (!db) {\n\t\t\treturn { id, type: 'error', message: 'Database is not open', code: 'DB_NOT_OPEN' }\n\t\t}\n\t\ttry {\n\t\t\tconst rows: Record<string, unknown>[] = []\n\t\t\tdb.exec({\n\t\t\t\tsql,\n\t\t\t\tbind: params,\n\t\t\t\trowMode: 'object',\n\t\t\t\tcallback: (row: Record<string, unknown>) => {\n\t\t\t\t\trows.push({ ...row })\n\t\t\t\t},\n\t\t\t})\n\t\t\treturn { id, type: 'success', data: rows }\n\t\t} catch (error) {\n\t\t\treturn { id, type: 'error', message: (error as Error).message, code: 'QUERY_ERROR' }\n\t\t}\n\t}\n\n\tfunction close(id: number): WorkerResponse {\n\t\tif (db) {\n\t\t\tdb.close()\n\t\t\tdb = null\n\t\t}\n\t\treturn { id, type: 'success' }\n\t}\n\n\tfunction migrate(id: number, statements: string[]): WorkerResponse {\n\t\tif (!db) {\n\t\t\treturn { id, type: 'error', message: 'Database is not open', code: 'DB_NOT_OPEN' }\n\t\t}\n\t\ttry {\n\t\t\tfor (const sql of statements) {\n\t\t\t\tdb.exec({ sql })\n\t\t\t}\n\t\t\treturn { id, type: 'success' }\n\t\t} catch (error) {\n\t\t\treturn { id, type: 'error', message: (error as Error).message, code: 'MIGRATE_ERROR' }\n\t\t}\n\t}\n\n\tfunction importData(id: number, data: Uint8Array): WorkerResponse {\n\t\tif (!db) {\n\t\t\treturn { id, type: 'error', message: 'Database is not open', code: 'DB_NOT_OPEN' }\n\t\t}\n\t\tconst dbWithDeserialize = db as SqliteDb & { deserialize?: (bytes: Uint8Array) => void }\n\t\tif (typeof dbWithDeserialize.deserialize === 'function') {\n\t\t\ttry {\n\t\t\t\tdbWithDeserialize.deserialize(data)\n\t\t\t\treturn { id, type: 'success' }\n\t\t\t} catch (error) {\n\t\t\t\treturn { id, type: 'error', message: (error as Error).message, code: 'IMPORT_ERROR' }\n\t\t\t}\n\t\t}\n\t\tif (!sqlite3Api || typeof sqlite3Api.capi?.sqlite3_deserialize === 'undefined') {\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\ttype: 'error',\n\t\t\t\tmessage: 'Import not supported in this SQLite WASM runtime',\n\t\t\t\tcode: 'IMPORT_NOT_SUPPORTED',\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tid,\n\t\t\ttype: 'error',\n\t\t\tmessage:\n\t\t\t\t'Import requires runtime-specific deserialize wiring and is unavailable in this worker build',\n\t\t\tcode: 'IMPORT_NOT_SUPPORTED',\n\t\t}\n\t}\n\n\tasync function handle(request: WorkerRequest): Promise<WorkerResponse> {\n\t\ttry {\n\t\t\tswitch (request.type) {\n\t\t\t\tcase 'open':\n\t\t\t\t\treturn await open(request.id, request.ddlStatements, request.dbName)\n\t\t\t\tcase 'close':\n\t\t\t\t\treturn close(request.id)\n\t\t\t\tcase 'execute':\n\t\t\t\t\treturn execute(request.id, request.sql, request.params)\n\t\t\t\tcase 'query':\n\t\t\t\t\treturn query(request.id, request.sql, request.params)\n\t\t\t\tcase 'begin':\n\t\t\t\t\treturn execute(request.id, 'BEGIN')\n\t\t\t\tcase 'commit':\n\t\t\t\t\treturn execute(request.id, 'COMMIT')\n\t\t\t\tcase 'rollback':\n\t\t\t\t\treturn execute(request.id, 'ROLLBACK')\n\t\t\t\tcase 'migrate':\n\t\t\t\t\treturn migrate(request.id, request.statements)\n\t\t\t\tcase 'import':\n\t\t\t\t\treturn importData(request.id, request.data)\n\t\t\t\tcase 'export':\n\t\t\t\t\treturn {\n\t\t\t\t\t\tid: request.id,\n\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\tmessage: 'Export not yet supported in browser worker',\n\t\t\t\t\t\tcode: 'EXPORT_NOT_SUPPORTED',\n\t\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\treturn {\n\t\t\t\t\t\tid: (request as WorkerRequest).id,\n\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\tmessage: 'Unknown request type',\n\t\t\t\t\t\tcode: 'UNKNOWN_REQUEST',\n\t\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tid: request.id,\n\t\t\t\ttype: 'error',\n\t\t\t\tmessage: (error as Error).message,\n\t\t\t\tcode: 'WORKER_ERROR',\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { handle }\n}\n","/// <reference lib=\"webworker\" />\n/**\n * Web Worker script for running SQLite WASM in a dedicated worker.\n *\n * This file is intended to run inside a Web Worker in browsers. It wires one\n * {@link createSqliteWasmCore} to the worker's message channel. The database\n * logic lives in `sqlite-wasm-worker-core.ts` so it can be reused by the\n * SharedWorker host, which cannot spawn a nested worker.\n *\n * This script cannot be tested in Node.js; it is validated in E2E browser tests.\n */\n\nimport type { WorkerRequest } from './sqlite-wasm-channel'\nimport { createSqliteWasmCore } from './sqlite-wasm-worker-core'\n\ndeclare const self: DedicatedWorkerGlobalScope\n\nconst core = createSqliteWasmCore()\n\nself.onmessage = (event: MessageEvent<WorkerRequest>): void => {\n\tvoid core.handle(event.data).then((response) => {\n\t\tself.postMessage(response)\n\t})\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAgDA,IAAM,iBAAiB;AAGvB,IAAM,uBAAuB;AAE7B,eAAe,YAAe,SAAqB,WAAmB,OAA2B;AAChG,MAAI;AACJ,MAAI;AACH,WAAO,MAAM,QAAQ,KAAK;AAAA,MACzB;AAAA,MACA,IAAI,QAAW,CAAC,GAAG,WAAW;AAC7B,gBAAQ;AAAA,UACP,MAAM,OAAO,IAAI,MAAM,GAAG,KAAK,oBAAoB,SAAS,IAAI,CAAC;AAAA,UACjE;AAAA,QACD;AAAA,MACD,CAAC;AAAA,IACF,CAAC;AAAA,EACF,UAAE;AACD,QAAI,UAAU,OAAW,cAAa,KAAK;AAAA,EAC5C;AACD;AAEA,SAAS,qBAAqB,QAAwB;AACrD,QAAM,OAAO,OAAO,QAAQ,oBAAoB,GAAG;AACnD,SAAO,KAAK,SAAS,KAAK,IAAI,OAAO,GAAG,IAAI;AAC7C;AAMA,SAAS,oBAAoB,OAA6D;AACzF,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,MAAI,qBAAqB,KAAK,OAAO,GAAG;AACvC,WAAO;AAAA,EACR;AACA,MACC,2FAA2F;AAAA,IAC1F;AAAA,EACD,GACC;AACD,WAAO;AAAA,EACR;AACA,SAAO;AACR;AAGA,IAAI,iBAA6C;AACjD,IAAI,kBAAmD;AACvD,IAAI;AAEJ,eAAe,cAAmC;AACjD,QAAM,qBAAqB,MAAM,OAAO,yBAAyB,GAAG;AAKpE,QAAM,UAAW,WAAuC;AAGxD,QAAM,cAAc,UACjB;AAAA,IACA,YAAY,CAAC,SAA0B,KAAK,SAAS,OAAO,IAAI,UAAU;AAAA,EAC3E,IACC;AACH,QAAM,SAAS;AAGf,SAAQ,MAAM,YAAY,OAAO,WAAW,GAAG,KAAQ,qBAAqB;AAC7E;AAEA,SAAS,aAAkC;AAC1C,MAAI,CAAC,gBAAgB;AACpB,qBAAiB,YAAY;AAAA,EAC9B;AACA,SAAO;AACR;AAEA,eAAe,gBAAgB,SAA+C;AAC7E,MAAI,CAAC,QAAQ,uBAAuB;AACnC,yBAAqB;AACrB,WAAO;AAAA,EACR;AACA,MAAI;AACH,WAAO,MAAM;AAAA,MACZ,QAAQ,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAAA,MACtD;AAAA,MACA;AAAA,IACD;AAAA,EACD,SAAS,OAAO;AACf,yBAAqB,oBAAoB,KAAK;AAC9C,WAAO;AAAA,EACR;AACD;AAEA,SAAS,YAAY,SAA+C;AACnE,MAAI,CAAC,iBAAiB;AACrB,sBAAkB,gBAAgB,OAAO;AAAA,EAC1C;AACA,SAAO;AACR;AAYO,SAAS,uBAAuC;AACtD,MAAI,KAAsB;AAC1B,MAAI,aAAgC;AACpC,MAAI,aAAa;AAEjB,iBAAe,KACd,IACA,eACA,QAC0B;AAC1B,QAAI;AAIH,UAAI,IAAI;AACP,iBAAS,IAAI,aAAa;AAC1B,eAAO,EAAE,IAAI,MAAM,WAAW,MAAM,cAAc,EAAE;AAAA,MACrD;AAEA,YAAM,UAAU,MAAM,WAAW;AACjC,mBAAa;AACb,YAAM,OAAO,MAAM,YAAY,OAAO;AAEtC,UAAI,MAAM;AACT,aAAK,IAAI,KAAK,cAAc,qBAAqB,UAAU,SAAS,CAAC;AACrE,qBAAa;AAAA,MACd,OAAO;AACN,aAAK,IAAI,QAAQ,IAAI,GAAG,EAAE,UAAU,WAAW,CAAC;AAChD,qBAAa;AAAA,MACd;AAEA,SAAG,KAAK,EAAE,KAAK,4BAA4B,CAAC;AAC5C,SAAG,KAAK,EAAE,KAAK,2BAA2B,CAAC;AAE3C,eAAS,IAAI,aAAa;AAC1B,aAAO,EAAE,IAAI,MAAM,WAAW,MAAM,cAAc,EAAE;AAAA,IACrD,SAAS,OAAO;AACf,aAAO,EAAE,IAAI,MAAM,SAAS,SAAU,MAAgB,SAAS,MAAM,aAAa;AAAA,IACnF;AAAA,EACD;AAEA,WAAS,gBAAkE;AAC1E,WAAO;AAAA,MACN;AAAA,MACA,GAAI,aAAa,CAAC,IAAI,EAAE,gBAAgB,sBAAsB,cAAc;AAAA,IAC7E;AAAA,EACD;AAEA,WAAS,SAAS,QAAkB,eAA+B;AAClE,eAAW,OAAO,eAAe;AAChC,UAAI,IAAI,WAAW,mBAAmB,GAAG;AACxC,YAAI;AACH,iBAAO,KAAK,EAAE,KAAK,IAAI,QAAQ,uBAAuB,EAAE,EAAE,CAAC;AAAA,QAC5D,SAAS,OAAO;AACf,gBAAM,MAAO,MAAgB,WAAW;AACxC,cAAI,CAAC,IAAI,SAAS,uBAAuB,GAAG;AAC3C,kBAAM;AAAA,UACP;AAAA,QACD;AAAA,MACD,OAAO;AACN,eAAO,KAAK,EAAE,IAAI,CAAC;AAAA,MACpB;AAAA,IACD;AAAA,EACD;AAEA,WAAS,QAAQ,IAAY,KAAa,QAAoC;AAC7E,QAAI,CAAC,IAAI;AACR,aAAO,EAAE,IAAI,MAAM,SAAS,SAAS,wBAAwB,MAAM,cAAc;AAAA,IAClF;AACA,QAAI;AACH,SAAG,KAAK,EAAE,KAAK,MAAM,OAAO,CAAC;AAC7B,aAAO,EAAE,IAAI,MAAM,UAAU;AAAA,IAC9B,SAAS,OAAO;AACf,aAAO,EAAE,IAAI,MAAM,SAAS,SAAU,MAAgB,SAAS,MAAM,aAAa;AAAA,IACnF;AAAA,EACD;AAEA,WAAS,MAAM,IAAY,KAAa,QAAoC;AAC3E,QAAI,CAAC,IAAI;AACR,aAAO,EAAE,IAAI,MAAM,SAAS,SAAS,wBAAwB,MAAM,cAAc;AAAA,IAClF;AACA,QAAI;AACH,YAAM,OAAkC,CAAC;AACzC,SAAG,KAAK;AAAA,QACP;AAAA,QACA,MAAM;AAAA,QACN,SAAS;AAAA,QACT,UAAU,CAAC,QAAiC;AAC3C,eAAK,KAAK,EAAE,GAAG,IAAI,CAAC;AAAA,QACrB;AAAA,MACD,CAAC;AACD,aAAO,EAAE,IAAI,MAAM,WAAW,MAAM,KAAK;AAAA,IAC1C,SAAS,OAAO;AACf,aAAO,EAAE,IAAI,MAAM,SAAS,SAAU,MAAgB,SAAS,MAAM,cAAc;AAAA,IACpF;AAAA,EACD;AAEA,WAAS,MAAM,IAA4B;AAC1C,QAAI,IAAI;AACP,SAAG,MAAM;AACT,WAAK;AAAA,IACN;AACA,WAAO,EAAE,IAAI,MAAM,UAAU;AAAA,EAC9B;AAEA,WAAS,QAAQ,IAAY,YAAsC;AAClE,QAAI,CAAC,IAAI;AACR,aAAO,EAAE,IAAI,MAAM,SAAS,SAAS,wBAAwB,MAAM,cAAc;AAAA,IAClF;AACA,QAAI;AACH,iBAAW,OAAO,YAAY;AAC7B,WAAG,KAAK,EAAE,IAAI,CAAC;AAAA,MAChB;AACA,aAAO,EAAE,IAAI,MAAM,UAAU;AAAA,IAC9B,SAAS,OAAO;AACf,aAAO,EAAE,IAAI,MAAM,SAAS,SAAU,MAAgB,SAAS,MAAM,gBAAgB;AAAA,IACtF;AAAA,EACD;AAEA,WAAS,WAAW,IAAY,MAAkC;AACjE,QAAI,CAAC,IAAI;AACR,aAAO,EAAE,IAAI,MAAM,SAAS,SAAS,wBAAwB,MAAM,cAAc;AAAA,IAClF;AACA,UAAM,oBAAoB;AAC1B,QAAI,OAAO,kBAAkB,gBAAgB,YAAY;AACxD,UAAI;AACH,0BAAkB,YAAY,IAAI;AAClC,eAAO,EAAE,IAAI,MAAM,UAAU;AAAA,MAC9B,SAAS,OAAO;AACf,eAAO,EAAE,IAAI,MAAM,SAAS,SAAU,MAAgB,SAAS,MAAM,eAAe;AAAA,MACrF;AAAA,IACD;AACA,QAAI,CAAC,cAAc,OAAO,WAAW,MAAM,wBAAwB,aAAa;AAC/E,aAAO;AAAA,QACN;AAAA,QACA,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,MACP;AAAA,IACD;AACA,WAAO;AAAA,MACN;AAAA,MACA,MAAM;AAAA,MACN,SACC;AAAA,MACD,MAAM;AAAA,IACP;AAAA,EACD;AAEA,iBAAe,OAAO,SAAiD;AACtE,QAAI;AACH,cAAQ,QAAQ,MAAM;AAAA,QACrB,KAAK;AACJ,iBAAO,MAAM,KAAK,QAAQ,IAAI,QAAQ,eAAe,QAAQ,MAAM;AAAA,QACpE,KAAK;AACJ,iBAAO,MAAM,QAAQ,EAAE;AAAA,QACxB,KAAK;AACJ,iBAAO,QAAQ,QAAQ,IAAI,QAAQ,KAAK,QAAQ,MAAM;AAAA,QACvD,KAAK;AACJ,iBAAO,MAAM,QAAQ,IAAI,QAAQ,KAAK,QAAQ,MAAM;AAAA,QACrD,KAAK;AACJ,iBAAO,QAAQ,QAAQ,IAAI,OAAO;AAAA,QACnC,KAAK;AACJ,iBAAO,QAAQ,QAAQ,IAAI,QAAQ;AAAA,QACpC,KAAK;AACJ,iBAAO,QAAQ,QAAQ,IAAI,UAAU;AAAA,QACtC,KAAK;AACJ,iBAAO,QAAQ,QAAQ,IAAI,QAAQ,UAAU;AAAA,QAC9C,KAAK;AACJ,iBAAO,WAAW,QAAQ,IAAI,QAAQ,IAAI;AAAA,QAC3C,KAAK;AACJ,iBAAO;AAAA,YACN,IAAI,QAAQ;AAAA,YACZ,MAAM;AAAA,YACN,SAAS;AAAA,YACT,MAAM;AAAA,UACP;AAAA,QACD;AACC,iBAAO;AAAA,YACN,IAAK,QAA0B;AAAA,YAC/B,MAAM;AAAA,YACN,SAAS;AAAA,YACT,MAAM;AAAA,UACP;AAAA,MACF;AAAA,IACD,SAAS,OAAO;AACf,aAAO;AAAA,QACN,IAAI,QAAQ;AAAA,QACZ,MAAM;AAAA,QACN,SAAU,MAAgB;AAAA,QAC1B,MAAM;AAAA,MACP;AAAA,IACD;AAAA,EACD;AAEA,SAAO,EAAE,OAAO;AACjB;;;ACnVA,IAAM,OAAO,qBAAqB;AAElC,KAAK,YAAY,CAAC,UAA6C;AAC9D,OAAK,KAAK,OAAO,MAAM,IAAI,EAAE,KAAK,CAAC,aAAa;AAC/C,SAAK,YAAY,QAAQ;AAAA,EAC1B,CAAC;AACF;","names":[]}
|
|
@@ -1,261 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createSqliteWasmCore
|
|
3
|
+
} from "../chunk-3Y2IERBF.js";
|
|
4
|
+
|
|
1
5
|
// src/adapters/sqlite-wasm-worker.ts
|
|
2
|
-
var
|
|
3
|
-
var sqlite3Api = null;
|
|
4
|
-
function sendResponse(response) {
|
|
5
|
-
self.postMessage(response);
|
|
6
|
-
}
|
|
7
|
-
function handleExecute(id, sql, params) {
|
|
8
|
-
if (!db) {
|
|
9
|
-
sendResponse({ id, type: "error", message: "Database is not open", code: "DB_NOT_OPEN" });
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
try {
|
|
13
|
-
db.exec({ sql, bind: params });
|
|
14
|
-
sendResponse({ id, type: "success" });
|
|
15
|
-
} catch (error) {
|
|
16
|
-
sendResponse({ id, type: "error", message: error.message, code: "EXEC_ERROR" });
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
function handleQuery(id, sql, params) {
|
|
20
|
-
if (!db) {
|
|
21
|
-
sendResponse({ id, type: "error", message: "Database is not open", code: "DB_NOT_OPEN" });
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
try {
|
|
25
|
-
const rows = [];
|
|
26
|
-
db.exec({
|
|
27
|
-
sql,
|
|
28
|
-
bind: params,
|
|
29
|
-
rowMode: "object",
|
|
30
|
-
callback: (row) => {
|
|
31
|
-
rows.push({ ...row });
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
sendResponse({ id, type: "success", data: rows });
|
|
35
|
-
} catch (error) {
|
|
36
|
-
sendResponse({ id, type: "error", message: error.message, code: "QUERY_ERROR" });
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
function opfsDatabaseFilename(dbName) {
|
|
40
|
-
const base = dbName.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
41
|
-
return base.endsWith(".db") ? base : `${base}.db`;
|
|
42
|
-
}
|
|
43
|
-
var OPFS_INIT_TIMEOUT_MS = 1e4;
|
|
44
|
-
async function withTimeout(promise, timeoutMs, label) {
|
|
45
|
-
let timer;
|
|
46
|
-
try {
|
|
47
|
-
return await Promise.race([
|
|
48
|
-
promise,
|
|
49
|
-
new Promise((_, reject) => {
|
|
50
|
-
timer = setTimeout(
|
|
51
|
-
() => reject(new Error(`${label} timed out after ${timeoutMs}ms`)),
|
|
52
|
-
timeoutMs
|
|
53
|
-
);
|
|
54
|
-
})
|
|
55
|
-
]);
|
|
56
|
-
} finally {
|
|
57
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
async function handleOpen(id, ddlStatements, dbName) {
|
|
61
|
-
try {
|
|
62
|
-
const sqlite3InitModule = (await import("@sqlite.org/sqlite-wasm")).default;
|
|
63
|
-
const wasmUrl = globalThis.__KORA_SQLITE_WASM_URL;
|
|
64
|
-
const initOptions = wasmUrl ? {
|
|
65
|
-
locateFile: (file) => {
|
|
66
|
-
if (file.endsWith(".wasm")) return wasmUrl;
|
|
67
|
-
return file;
|
|
68
|
-
}
|
|
69
|
-
} : void 0;
|
|
70
|
-
const initFn = sqlite3InitModule;
|
|
71
|
-
const sqlite3 = await withTimeout(
|
|
72
|
-
initFn(initOptions),
|
|
73
|
-
6e4,
|
|
74
|
-
"SQLite3 module init"
|
|
75
|
-
);
|
|
76
|
-
sqlite3Api = sqlite3;
|
|
77
|
-
let useOpfs = false;
|
|
78
|
-
let fallbackReason;
|
|
79
|
-
if (sqlite3.installOpfsSAHPoolVfs) {
|
|
80
|
-
try {
|
|
81
|
-
const pool = await withTimeout(
|
|
82
|
-
sqlite3.installOpfsSAHPoolVfs({ name: "kora-opfs" }),
|
|
83
|
-
OPFS_INIT_TIMEOUT_MS,
|
|
84
|
-
"OPFS VFS install"
|
|
85
|
-
);
|
|
86
|
-
db = new pool.OpfsSAHPoolDb(opfsDatabaseFilename(dbName ?? "kora-db"));
|
|
87
|
-
useOpfs = true;
|
|
88
|
-
} catch (error) {
|
|
89
|
-
fallbackReason = classifyOpfsFailure(error);
|
|
90
|
-
console.warn(
|
|
91
|
-
`[kora] OPFS unavailable (${fallbackReason}), falling back to in-memory SQLite`
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
} else {
|
|
95
|
-
fallbackReason = "unsupported";
|
|
96
|
-
}
|
|
97
|
-
if (!useOpfs) {
|
|
98
|
-
db = new sqlite3.oo1.DB({ filename: ":memory:" });
|
|
99
|
-
}
|
|
100
|
-
db?.exec({ sql: "PRAGMA journal_mode = WAL" });
|
|
101
|
-
db?.exec({ sql: "PRAGMA foreign_keys = ON" });
|
|
102
|
-
for (const sql of ddlStatements) {
|
|
103
|
-
if (sql.startsWith("--kora:safe-alter")) {
|
|
104
|
-
try {
|
|
105
|
-
db?.exec({ sql: sql.replace("--kora:safe-alter\n", "") });
|
|
106
|
-
} catch (e) {
|
|
107
|
-
const msg = e.message || "";
|
|
108
|
-
if (!msg.includes("duplicate column name")) {
|
|
109
|
-
throw e;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
} else {
|
|
113
|
-
db?.exec({ sql });
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
sendResponse({
|
|
117
|
-
id,
|
|
118
|
-
type: "success",
|
|
119
|
-
data: { persistent: useOpfs, ...fallbackReason ? { fallbackReason } : {} }
|
|
120
|
-
});
|
|
121
|
-
} catch (error) {
|
|
122
|
-
sendResponse({
|
|
123
|
-
id,
|
|
124
|
-
type: "error",
|
|
125
|
-
message: error.message,
|
|
126
|
-
code: "INIT_ERROR"
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
function classifyOpfsFailure(error) {
|
|
131
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
132
|
-
if (/timed out|timeout/i.test(message)) {
|
|
133
|
-
return "timeout";
|
|
134
|
-
}
|
|
135
|
-
if (/lock|already|in use|in-use|NoModificationAllowed|acquire|SyncAccessHandle|being created/i.test(
|
|
136
|
-
message
|
|
137
|
-
)) {
|
|
138
|
-
return "lock-conflict";
|
|
139
|
-
}
|
|
140
|
-
return "unsupported";
|
|
141
|
-
}
|
|
142
|
-
function handleClose(id) {
|
|
143
|
-
if (db) {
|
|
144
|
-
db.close();
|
|
145
|
-
db = null;
|
|
146
|
-
}
|
|
147
|
-
sendResponse({ id, type: "success" });
|
|
148
|
-
}
|
|
149
|
-
function handleImport(id, data) {
|
|
150
|
-
if (!db) {
|
|
151
|
-
sendResponse({ id, type: "error", message: "Database is not open", code: "DB_NOT_OPEN" });
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
const dbWithDeserialize = db;
|
|
155
|
-
if (typeof dbWithDeserialize.deserialize === "function") {
|
|
156
|
-
try {
|
|
157
|
-
dbWithDeserialize.deserialize(data);
|
|
158
|
-
sendResponse({ id, type: "success" });
|
|
159
|
-
return;
|
|
160
|
-
} catch (error) {
|
|
161
|
-
sendResponse({ id, type: "error", message: error.message, code: "IMPORT_ERROR" });
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
const sqlite3 = sqlite3Api;
|
|
166
|
-
if (!sqlite3 || typeof sqlite3.capi?.sqlite3_deserialize === "undefined") {
|
|
167
|
-
sendResponse({
|
|
168
|
-
id,
|
|
169
|
-
type: "error",
|
|
170
|
-
message: "Import not supported in this SQLite WASM runtime",
|
|
171
|
-
code: "IMPORT_NOT_SUPPORTED"
|
|
172
|
-
});
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
sendResponse({
|
|
176
|
-
id,
|
|
177
|
-
type: "error",
|
|
178
|
-
message: "Import requires runtime-specific deserialize wiring and is unavailable in this worker build",
|
|
179
|
-
code: "IMPORT_NOT_SUPPORTED"
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
function handleMessage(request) {
|
|
183
|
-
try {
|
|
184
|
-
switch (request.type) {
|
|
185
|
-
case "open":
|
|
186
|
-
handleOpen(request.id, request.ddlStatements, request.dbName);
|
|
187
|
-
return;
|
|
188
|
-
case "close":
|
|
189
|
-
handleClose(request.id);
|
|
190
|
-
return;
|
|
191
|
-
case "execute":
|
|
192
|
-
handleExecute(request.id, request.sql, request.params);
|
|
193
|
-
return;
|
|
194
|
-
case "query":
|
|
195
|
-
handleQuery(request.id, request.sql, request.params);
|
|
196
|
-
return;
|
|
197
|
-
case "begin":
|
|
198
|
-
handleExecute(request.id, "BEGIN");
|
|
199
|
-
return;
|
|
200
|
-
case "commit":
|
|
201
|
-
handleExecute(request.id, "COMMIT");
|
|
202
|
-
return;
|
|
203
|
-
case "rollback":
|
|
204
|
-
handleExecute(request.id, "ROLLBACK");
|
|
205
|
-
return;
|
|
206
|
-
case "migrate":
|
|
207
|
-
if (!db) {
|
|
208
|
-
sendResponse({
|
|
209
|
-
id: request.id,
|
|
210
|
-
type: "error",
|
|
211
|
-
message: "Database is not open",
|
|
212
|
-
code: "DB_NOT_OPEN"
|
|
213
|
-
});
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
try {
|
|
217
|
-
for (const sql of request.statements) {
|
|
218
|
-
db.exec({ sql });
|
|
219
|
-
}
|
|
220
|
-
sendResponse({ id: request.id, type: "success" });
|
|
221
|
-
} catch (error) {
|
|
222
|
-
sendResponse({
|
|
223
|
-
id: request.id,
|
|
224
|
-
type: "error",
|
|
225
|
-
message: error.message,
|
|
226
|
-
code: "MIGRATE_ERROR"
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
return;
|
|
230
|
-
case "export":
|
|
231
|
-
sendResponse({
|
|
232
|
-
id: request.id,
|
|
233
|
-
type: "error",
|
|
234
|
-
message: "Export not yet supported in browser worker",
|
|
235
|
-
code: "EXPORT_NOT_SUPPORTED"
|
|
236
|
-
});
|
|
237
|
-
return;
|
|
238
|
-
case "import":
|
|
239
|
-
handleImport(request.id, request.data);
|
|
240
|
-
return;
|
|
241
|
-
default:
|
|
242
|
-
sendResponse({
|
|
243
|
-
id: request.id,
|
|
244
|
-
type: "error",
|
|
245
|
-
message: "Unknown request type",
|
|
246
|
-
code: "UNKNOWN_REQUEST"
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
} catch (error) {
|
|
250
|
-
sendResponse({
|
|
251
|
-
id: request.id,
|
|
252
|
-
type: "error",
|
|
253
|
-
message: error.message,
|
|
254
|
-
code: "WORKER_ERROR"
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
}
|
|
6
|
+
var core = createSqliteWasmCore();
|
|
258
7
|
self.onmessage = (event) => {
|
|
259
|
-
|
|
8
|
+
void core.handle(event.data).then((response) => {
|
|
9
|
+
self.postMessage(response);
|
|
10
|
+
});
|
|
260
11
|
};
|
|
261
12
|
//# sourceMappingURL=sqlite-wasm-worker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/sqlite-wasm-worker.ts"],"sourcesContent":["/// <reference lib=\"webworker\" />\n/**\n * Web Worker script for running SQLite WASM.\n *\n * This file is intended to run inside a Web Worker in browsers.\n * It loads @sqlite.org/sqlite-wasm, initializes SQLite with OPFS persistence\n * (falling back to in-memory if unavailable), and processes messages from\n * the main thread via the WorkerRequest/WorkerResponse protocol.\n *\n * This script cannot be tested in Node.js — it is validated in E2E browser tests.\n */\n\nimport type { WorkerRequest, WorkerResponse } from './sqlite-wasm-channel'\n\ninterface SqliteDb {\n\texec(opts: {\n\t\tsql: string\n\t\tbind?: unknown[]\n\t\treturnValue?: string\n\t\trowMode?: string\n\t\tcallback?: (row: Record<string, unknown>) => void\n\t}): void\n\tclose(): void\n\tdeserialize?: (data: Uint8Array) => void\n}\n\ndeclare const self: DedicatedWorkerGlobalScope\n\nlet db: SqliteDb | null = null\nlet sqlite3Api: unknown = null\n\nfunction sendResponse(response: WorkerResponse): void {\n\tself.postMessage(response)\n}\n\nfunction handleExecute(id: number, sql: string, params?: unknown[]): void {\n\tif (!db) {\n\t\tsendResponse({ id, type: 'error', message: 'Database is not open', code: 'DB_NOT_OPEN' })\n\t\treturn\n\t}\n\ttry {\n\t\tdb.exec({ sql, bind: params })\n\t\tsendResponse({ id, type: 'success' })\n\t} catch (error) {\n\t\tsendResponse({ id, type: 'error', message: (error as Error).message, code: 'EXEC_ERROR' })\n\t}\n}\n\nfunction handleQuery(id: number, sql: string, params?: unknown[]): void {\n\tif (!db) {\n\t\tsendResponse({ id, type: 'error', message: 'Database is not open', code: 'DB_NOT_OPEN' })\n\t\treturn\n\t}\n\ttry {\n\t\tconst rows: Record<string, unknown>[] = []\n\t\tdb.exec({\n\t\t\tsql,\n\t\t\tbind: params,\n\t\t\trowMode: 'object',\n\t\t\tcallback: (row: Record<string, unknown>) => {\n\t\t\t\trows.push({ ...row })\n\t\t\t},\n\t\t})\n\t\tsendResponse({ id, type: 'success', data: rows })\n\t} catch (error) {\n\t\tsendResponse({ id, type: 'error', message: (error as Error).message, code: 'QUERY_ERROR' })\n\t}\n}\n\nfunction opfsDatabaseFilename(dbName: string): string {\n\tconst base = dbName.replace(/[^a-zA-Z0-9._-]/g, '_')\n\treturn base.endsWith('.db') ? base : `${base}.db`\n}\n\n/** Headless browsers and some profiles hang on OPFS VFS install; fall back to memory. */\nconst OPFS_INIT_TIMEOUT_MS = 10_000\n\nasync function withTimeout<T>(promise: Promise<T>, timeoutMs: number, label: string): Promise<T> {\n\tlet timer: ReturnType<typeof setTimeout> | undefined\n\ttry {\n\t\treturn await Promise.race([\n\t\t\tpromise,\n\t\t\tnew Promise<T>((_, reject) => {\n\t\t\t\ttimer = setTimeout(\n\t\t\t\t\t() => reject(new Error(`${label} timed out after ${timeoutMs}ms`)),\n\t\t\t\t\ttimeoutMs,\n\t\t\t\t)\n\t\t\t}),\n\t\t])\n\t} finally {\n\t\tif (timer !== undefined) clearTimeout(timer)\n\t}\n}\n\nasync function handleOpen(id: number, ddlStatements: string[], dbName?: string): Promise<void> {\n\ttry {\n\t\tconst sqlite3InitModule = (await import('@sqlite.org/sqlite-wasm')).default\n\n\t\t// In production builds, Vite hashes asset filenames (e.g. sqlite3-[hash].wasm).\n\t\t// The sqlite3 module's default locateFile resolves the unhashed name, causing a 404.\n\t\t// Templates set __KORA_SQLITE_WASM_URL via `import wasmUrl from '...sqlite3.wasm?url'`\n\t\t// so we can override locateFile with the correct hashed URL.\n\t\tconst wasmUrl = (globalThis as Record<string, unknown>).__KORA_SQLITE_WASM_URL as\n\t\t\t| string\n\t\t\t| undefined\n\t\tconst initOptions = wasmUrl\n\t\t\t? {\n\t\t\t\t\tlocateFile: (file: string) => {\n\t\t\t\t\t\tif (file.endsWith('.wasm')) return wasmUrl\n\t\t\t\t\t\treturn file\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: undefined\n\n\t\t// sqlite3InitModule accepts Emscripten Module overrides but the types don't reflect this\n\t\tconst initFn = sqlite3InitModule as unknown as (\n\t\t\topts?: Record<string, unknown>,\n\t\t) => Promise<unknown>\n\t\tconst sqlite3 = (await withTimeout(\n\t\t\tinitFn(initOptions),\n\t\t\t60_000,\n\t\t\t'SQLite3 module init',\n\t\t)) as Awaited<ReturnType<typeof sqlite3InitModule>>\n\t\tsqlite3Api = sqlite3\n\n\t\t// Try OPFS persistence first\n\t\tlet useOpfs = false\n\t\tlet fallbackReason: 'lock-conflict' | 'timeout' | 'unsupported' | undefined\n\t\tif (sqlite3.installOpfsSAHPoolVfs) {\n\t\t\ttry {\n\t\t\t\tconst pool = await withTimeout(\n\t\t\t\t\tsqlite3.installOpfsSAHPoolVfs({ name: 'kora-opfs' }),\n\t\t\t\t\tOPFS_INIT_TIMEOUT_MS,\n\t\t\t\t\t'OPFS VFS install',\n\t\t\t\t)\n\t\t\t\tdb = new pool.OpfsSAHPoolDb(opfsDatabaseFilename(dbName ?? 'kora-db'))\n\t\t\t\tuseOpfs = true\n\t\t\t} catch (error) {\n\t\t\t\t// OPFS unavailable. Classify WHY so the main thread can surface a clear\n\t\t\t\t// diagnostic instead of a silent, non-persistent in-memory fallback that\n\t\t\t\t// loses the user's data on reload.\n\t\t\t\tfallbackReason = classifyOpfsFailure(error)\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[kora] OPFS unavailable (${fallbackReason}), falling back to in-memory SQLite`,\n\t\t\t\t)\n\t\t\t}\n\t\t} else {\n\t\t\tfallbackReason = 'unsupported'\n\t\t}\n\n\t\tif (!useOpfs) {\n\t\t\tdb = new sqlite3.oo1.DB({ filename: ':memory:' })\n\t\t}\n\n\t\t// Set pragmas\n\t\tdb?.exec({ sql: 'PRAGMA journal_mode = WAL' })\n\t\tdb?.exec({ sql: 'PRAGMA foreign_keys = ON' })\n\n\t\t// Execute DDL statements\n\t\tfor (const sql of ddlStatements) {\n\t\t\tif (sql.startsWith('--kora:safe-alter')) {\n\t\t\t\t// Safe ALTER TABLE — ignore \"duplicate column name\" errors for existing columns\n\t\t\t\ttry {\n\t\t\t\t\tdb?.exec({ sql: sql.replace('--kora:safe-alter\\n', '') })\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconst msg = (e as Error).message || ''\n\t\t\t\t\tif (!msg.includes('duplicate column name')) {\n\t\t\t\t\t\tthrow e\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdb?.exec({ sql })\n\t\t\t}\n\t\t}\n\n\t\t// Report the storage mode so the adapter can emit `store:opfs-unavailable`\n\t\t// when persistence silently degraded to in-memory.\n\t\tsendResponse({\n\t\t\tid,\n\t\t\ttype: 'success',\n\t\t\tdata: { persistent: useOpfs, ...(fallbackReason ? { fallbackReason } : {}) },\n\t\t})\n\t} catch (error) {\n\t\tsendResponse({\n\t\t\tid,\n\t\t\ttype: 'error',\n\t\t\tmessage: (error as Error).message,\n\t\t\tcode: 'INIT_ERROR',\n\t\t})\n\t}\n}\n\n/**\n * Classify why the OPFS SyncAccessHandle pool could not be installed, so the\n * fallback to in-memory is explainable rather than silent.\n *\n * A `lock-conflict` is the important case: another runtime on the same origin\n * (another tab or a logically separate app that reused the database name) already\n * holds the pool's access handles, so this runtime cannot persist.\n */\nfunction classifyOpfsFailure(error: unknown): 'lock-conflict' | 'timeout' | 'unsupported' {\n\tconst message = error instanceof Error ? error.message : String(error)\n\tif (/timed out|timeout/i.test(message)) {\n\t\treturn 'timeout'\n\t}\n\tif (\n\t\t/lock|already|in use|in-use|NoModificationAllowed|acquire|SyncAccessHandle|being created/i.test(\n\t\t\tmessage,\n\t\t)\n\t) {\n\t\treturn 'lock-conflict'\n\t}\n\treturn 'unsupported'\n}\n\nfunction handleClose(id: number): void {\n\tif (db) {\n\t\tdb.close()\n\t\tdb = null\n\t}\n\tsendResponse({ id, type: 'success' })\n}\n\nfunction handleImport(id: number, data: Uint8Array): void {\n\tif (!db) {\n\t\tsendResponse({ id, type: 'error', message: 'Database is not open', code: 'DB_NOT_OPEN' })\n\t\treturn\n\t}\n\n\tconst dbWithDeserialize = db as SqliteDb & { deserialize?: (bytes: Uint8Array) => void }\n\tif (typeof dbWithDeserialize.deserialize === 'function') {\n\t\ttry {\n\t\t\tdbWithDeserialize.deserialize(data)\n\t\t\tsendResponse({ id, type: 'success' })\n\t\t\treturn\n\t\t} catch (error) {\n\t\t\tsendResponse({ id, type: 'error', message: (error as Error).message, code: 'IMPORT_ERROR' })\n\t\t\treturn\n\t\t}\n\t}\n\n\tconst sqlite3 = sqlite3Api as {\n\t\too1?: { DB?: new (...args: unknown[]) => SqliteDb }\n\t\tcapi?: { sqlite3_deserialize?: unknown }\n\t} | null\n\n\tif (!sqlite3 || typeof sqlite3.capi?.sqlite3_deserialize === 'undefined') {\n\t\tsendResponse({\n\t\t\tid,\n\t\t\ttype: 'error',\n\t\t\tmessage: 'Import not supported in this SQLite WASM runtime',\n\t\t\tcode: 'IMPORT_NOT_SUPPORTED',\n\t\t})\n\t\treturn\n\t}\n\n\tsendResponse({\n\t\tid,\n\t\ttype: 'error',\n\t\tmessage:\n\t\t\t'Import requires runtime-specific deserialize wiring and is unavailable in this worker build',\n\t\tcode: 'IMPORT_NOT_SUPPORTED',\n\t})\n}\n\nfunction handleMessage(request: WorkerRequest): void {\n\ttry {\n\t\tswitch (request.type) {\n\t\t\tcase 'open':\n\t\t\t\t// open is async due to WASM loading\n\t\t\t\thandleOpen(request.id, request.ddlStatements, request.dbName)\n\t\t\t\treturn\n\t\t\tcase 'close':\n\t\t\t\thandleClose(request.id)\n\t\t\t\treturn\n\t\t\tcase 'execute':\n\t\t\t\thandleExecute(request.id, request.sql, request.params)\n\t\t\t\treturn\n\t\t\tcase 'query':\n\t\t\t\thandleQuery(request.id, request.sql, request.params)\n\t\t\t\treturn\n\t\t\tcase 'begin':\n\t\t\t\thandleExecute(request.id, 'BEGIN')\n\t\t\t\treturn\n\t\t\tcase 'commit':\n\t\t\t\thandleExecute(request.id, 'COMMIT')\n\t\t\t\treturn\n\t\t\tcase 'rollback':\n\t\t\t\thandleExecute(request.id, 'ROLLBACK')\n\t\t\t\treturn\n\t\t\tcase 'migrate':\n\t\t\t\tif (!db) {\n\t\t\t\t\tsendResponse({\n\t\t\t\t\t\tid: request.id,\n\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\tmessage: 'Database is not open',\n\t\t\t\t\t\tcode: 'DB_NOT_OPEN',\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tfor (const sql of request.statements) {\n\t\t\t\t\t\tdb.exec({ sql })\n\t\t\t\t\t}\n\t\t\t\t\tsendResponse({ id: request.id, type: 'success' })\n\t\t\t\t} catch (error) {\n\t\t\t\t\tsendResponse({\n\t\t\t\t\t\tid: request.id,\n\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\tmessage: (error as Error).message,\n\t\t\t\t\t\tcode: 'MIGRATE_ERROR',\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\tcase 'export':\n\t\t\t\t// Export is not trivially supported via the oo1 API in the browser.\n\t\t\t\t// In a real implementation, we'd use the C API's sqlite3_serialize.\n\t\t\t\tsendResponse({\n\t\t\t\t\tid: request.id,\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tmessage: 'Export not yet supported in browser worker',\n\t\t\t\t\tcode: 'EXPORT_NOT_SUPPORTED',\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\tcase 'import':\n\t\t\t\thandleImport(request.id, request.data)\n\t\t\t\treturn\n\t\t\tdefault:\n\t\t\t\tsendResponse({\n\t\t\t\t\tid: (request as WorkerRequest).id,\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tmessage: 'Unknown request type',\n\t\t\t\t\tcode: 'UNKNOWN_REQUEST',\n\t\t\t\t})\n\t\t}\n\t} catch (error) {\n\t\tsendResponse({\n\t\t\tid: request.id,\n\t\t\ttype: 'error',\n\t\t\tmessage: (error as Error).message,\n\t\t\tcode: 'WORKER_ERROR',\n\t\t})\n\t}\n}\n\n// Listen for messages from the main thread\nself.onmessage = (event: MessageEvent<WorkerRequest>) => {\n\thandleMessage(event.data)\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/sqlite-wasm-worker.ts"],"sourcesContent":["/// <reference lib=\"webworker\" />\n/**\n * Web Worker script for running SQLite WASM in a dedicated worker.\n *\n * This file is intended to run inside a Web Worker in browsers. It wires one\n * {@link createSqliteWasmCore} to the worker's message channel. The database\n * logic lives in `sqlite-wasm-worker-core.ts` so it can be reused by the\n * SharedWorker host, which cannot spawn a nested worker.\n *\n * This script cannot be tested in Node.js; it is validated in E2E browser tests.\n */\n\nimport type { WorkerRequest } from './sqlite-wasm-channel'\nimport { createSqliteWasmCore } from './sqlite-wasm-worker-core'\n\ndeclare const self: DedicatedWorkerGlobalScope\n\nconst core = createSqliteWasmCore()\n\nself.onmessage = (event: MessageEvent<WorkerRequest>): void => {\n\tvoid core.handle(event.data).then((response) => {\n\t\tself.postMessage(response)\n\t})\n}\n"],"mappings":";;;;;AAiBA,IAAM,OAAO,qBAAqB;AAElC,KAAK,YAAY,CAAC,UAA6C;AAC9D,OAAK,KAAK,OAAO,MAAM,IAAI,EAAE,KAAK,CAAC,aAAa;AAC/C,SAAK,YAAY,QAAQ;AAAA,EAC1B,CAAC;AACF;","names":[]}
|
|
@@ -522,7 +522,10 @@ var SqliteWasmAdapter = class {
|
|
|
522
522
|
} else if (this.sharedWorkerUrl && this.workerUrl && isSharedWorkerStorageSupported()) {
|
|
523
523
|
const workerUrlString = typeof this.workerUrl === "string" ? this.workerUrl : this.workerUrl.href;
|
|
524
524
|
const sharedUrl = typeof this.sharedWorkerUrl === "string" ? this.sharedWorkerUrl : this.sharedWorkerUrl.href;
|
|
525
|
-
this.sharedWorker = new SharedWorker(sharedUrl, {
|
|
525
|
+
this.sharedWorker = new SharedWorker(sharedUrl, {
|
|
526
|
+
type: "module",
|
|
527
|
+
name: `kora-sw-${this.dbName}`
|
|
528
|
+
});
|
|
526
529
|
this.bridge = new SharedWorkerClientBridge(this.sharedWorker, this.dbName, workerUrlString);
|
|
527
530
|
} else if (this.workerUrl) {
|
|
528
531
|
this.schema = schema;
|