@korajs/store 1.0.0-beta.12 → 1.0.0-beta.14

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.
Files changed (92) hide show
  1. package/README.md +29 -37
  2. package/dist/adapters/better-sqlite3.cjs +90 -4
  3. package/dist/adapters/better-sqlite3.cjs.map +1 -1
  4. package/dist/adapters/better-sqlite3.d.cts +21 -12
  5. package/dist/adapters/better-sqlite3.d.ts +21 -12
  6. package/dist/adapters/better-sqlite3.js +69 -5
  7. package/dist/adapters/better-sqlite3.js.map +1 -1
  8. package/dist/adapters/indexeddb.cjs +1316 -610
  9. package/dist/adapters/indexeddb.cjs.map +1 -1
  10. package/dist/adapters/indexeddb.d.cts +29 -3
  11. package/dist/adapters/indexeddb.d.ts +29 -3
  12. package/dist/adapters/indexeddb.js +247 -221
  13. package/dist/adapters/indexeddb.js.map +1 -1
  14. package/dist/adapters/sqlite-wasm-worker.cjs +856 -63
  15. package/dist/adapters/sqlite-wasm-worker.cjs.map +1 -1
  16. package/dist/adapters/sqlite-wasm-worker.js +529 -63
  17. package/dist/adapters/sqlite-wasm-worker.js.map +1 -1
  18. package/dist/adapters/sqlite-wasm.cjs +1032 -344
  19. package/dist/adapters/sqlite-wasm.cjs.map +1 -1
  20. package/dist/adapters/sqlite-wasm.d.cts +239 -18
  21. package/dist/adapters/sqlite-wasm.d.ts +239 -18
  22. package/dist/adapters/sqlite-wasm.js +111 -5
  23. package/dist/adapters/sqlite-wasm.js.map +1 -1
  24. package/dist/backup-IHKVMUAM.js +25 -0
  25. package/dist/chunk-5AQSGMJV.js +5471 -0
  26. package/dist/chunk-5AQSGMJV.js.map +1 -0
  27. package/dist/chunk-5JMGMPUE.js +591 -0
  28. package/dist/chunk-5JMGMPUE.js.map +1 -0
  29. package/dist/{chunk-CYO3YKFL.js → chunk-5ZRRF6R2.js} +2 -2
  30. package/dist/chunk-A6GFH5IG.js +36 -0
  31. package/dist/chunk-A6GFH5IG.js.map +1 -0
  32. package/dist/chunk-BILSA6XZ.js +608 -0
  33. package/dist/chunk-BILSA6XZ.js.map +1 -0
  34. package/dist/chunk-BQSIL6TT.js +1095 -0
  35. package/dist/chunk-BQSIL6TT.js.map +1 -0
  36. package/dist/{chunk-GSJ7EEUC.js → chunk-J5AGXF3D.js} +58 -9
  37. package/dist/chunk-J5AGXF3D.js.map +1 -0
  38. package/dist/chunk-KK3GBONL.js +112 -0
  39. package/dist/chunk-KK3GBONL.js.map +1 -0
  40. package/dist/chunk-KTVNANUH.js +876 -0
  41. package/dist/chunk-KTVNANUH.js.map +1 -0
  42. package/dist/chunk-QW4UU7NG.js +1003 -0
  43. package/dist/chunk-QW4UU7NG.js.map +1 -0
  44. package/dist/chunk-SRHDJF5B.js +186 -0
  45. package/dist/chunk-SRHDJF5B.js.map +1 -0
  46. package/dist/chunk-UC2LGFPV.js +810 -0
  47. package/dist/chunk-UC2LGFPV.js.map +1 -0
  48. package/dist/{export-audit-ODGQTQIK.js → export-audit-J2QXRHD2.js} +3 -3
  49. package/dist/index.cjs +9533 -4246
  50. package/dist/index.cjs.map +1 -1
  51. package/dist/index.d.cts +1143 -110
  52. package/dist/index.d.ts +1143 -110
  53. package/dist/index.js +298 -3191
  54. package/dist/index.js.map +1 -1
  55. package/dist/internal.cjs +581 -264
  56. package/dist/internal.cjs.map +1 -1
  57. package/dist/internal.d.cts +15 -85
  58. package/dist/internal.d.ts +15 -85
  59. package/dist/internal.js +10 -8
  60. package/dist/restore-MNDPR557.js +299 -0
  61. package/dist/restore-MNDPR557.js.map +1 -0
  62. package/dist/sql-builder-D0tC3sv9.d.cts +615 -0
  63. package/dist/sql-builder-D5UMzHEo.d.ts +615 -0
  64. package/dist/sqlite-wasm-channel-DVX93Uiq.d.cts +141 -0
  65. package/dist/sqlite-wasm-channel-DVX93Uiq.d.ts +141 -0
  66. package/dist/sqlite-wasm-channel-QCCNBYCU.js +12 -0
  67. package/dist/store-HNGX4KTT.js +16 -0
  68. package/dist/store-HNGX4KTT.js.map +1 -0
  69. package/dist/{types-BslDOTk0.d.ts → types-Dh-xyUjP.d.cts} +99 -26
  70. package/dist/{types-BslDOTk0.d.cts → types-Dh-xyUjP.d.ts} +99 -26
  71. package/package.json +3 -2
  72. package/dist/backup-5S7K2Z35.js +0 -14
  73. package/dist/chunk-GSJ7EEUC.js.map +0 -1
  74. package/dist/chunk-HS6DBMST.js +0 -383
  75. package/dist/chunk-HS6DBMST.js.map +0 -1
  76. package/dist/chunk-RJIEKEN4.js +0 -751
  77. package/dist/chunk-RJIEKEN4.js.map +0 -1
  78. package/dist/chunk-TUR7RGEP.js +0 -84
  79. package/dist/chunk-TUR7RGEP.js.map +0 -1
  80. package/dist/chunk-VDBJQ75K.js +0 -78
  81. package/dist/chunk-VDBJQ75K.js.map +0 -1
  82. package/dist/chunk-YT7MRFCP.js +0 -687
  83. package/dist/chunk-YT7MRFCP.js.map +0 -1
  84. package/dist/sqlite-wasm-channel-GGHA2BXU.js +0 -12
  85. package/dist/sqlite-wasm-channel-L6o3bWQK.d.cts +0 -92
  86. package/dist/sqlite-wasm-channel-L6o3bWQK.d.ts +0 -92
  87. package/dist/types-BOO9EPt1.d.ts +0 -170
  88. package/dist/types-C_GDavG-.d.cts +0 -170
  89. /package/dist/{backup-5S7K2Z35.js.map → backup-IHKVMUAM.js.map} +0 -0
  90. /package/dist/{chunk-CYO3YKFL.js.map → chunk-5ZRRF6R2.js.map} +0 -0
  91. /package/dist/{export-audit-ODGQTQIK.js.map → export-audit-J2QXRHD2.js.map} +0 -0
  92. /package/dist/{sqlite-wasm-channel-GGHA2BXU.js.map → sqlite-wasm-channel-QCCNBYCU.js.map} +0 -0
@@ -1 +1 @@
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`.\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: 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.\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.\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 through the dedicated worker's\n * `postMessage`.\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// Re-run idempotent DDL on the existing handle rather than opening the\n\t\t\t// 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.\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":"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","names":[]}
1
+ {"version":3,"sources":["../../src/adapters/opfs-pool-ownership.ts","../../src/adapters/sqlite-wasm-loader.ts","../../src/adapters/sqlite-wasm-worker-core.ts","../../src/adapters/sqlite-wasm-worker.ts"],"sourcesContent":["/// <reference lib=\"webworker\" />\n/**\n * Worker-side OPFS pool ownership (W8a, NEW-STORE-5/7/8/10).\n *\n * Durable storage on the web is a protocol between tabs, workers and the\n * SyncAccessHandle (SAH) pool, not a single open call:\n *\n * - One pool per database ({@link opfsPoolNameFor}); the tab leader lock already\n * makes one tab the owner of each database.\n * - The worker that installs a pool holds the Web Lock named after it for the\n * pool's whole life. Termination of that worker releases both the lock and the\n * file handles, so the next owner waits on the lock instead of racing.\n * - The lock can be released a few milliseconds before the browser finishes\n * closing the old worker's handles (measured ~90ms). Before installing, the\n * new owner therefore probes every pool file for a free handle and waits.\n * This matters for correctness, not just speed: when sqlite-wasm's install\n * fails half-way it calls `removeVfs()`, which recursively deletes the pool\n * directory's files that are not locked. Installing only once every handle is\n * free keeps that path unreachable.\n * - Contention with a live holder is a wait plus a reported blocking state,\n * never a fallback to non-durable storage.\n *\n * This file runs inside the dedicated SQLite worker; it is exercised by the\n * real-browser suite (tests/repro/browser), not by Node unit tests.\n */\n\nimport { LEGACY_OPFS_POOL_NAME, opfsPoolDirectory, opfsPoolLockName } from './opfs-names'\n\n/** The subset of sqlite-wasm's oo1.DB the worker uses. */\nexport interface 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}): unknown\n\tclose(): void\n\tpointer?: number\n\tdeserialize?: (data: Uint8Array) => void\n}\n\n/** The subset of sqlite-wasm's OpfsSAHPoolUtil the worker uses. */\nexport interface OpfsPool {\n\tOpfsSAHPoolDb: new (filename: string) => SqliteDb\n\tgetFileCount(): number\n\tgetFileNames(): string[]\n\tgetCapacity(): number\n\treserveMinimumCapacity(min: number): Promise<number>\n\texportFile(name: string): Uint8Array\n\timportDb(name: string, bytes: Uint8Array): number | Promise<number>\n\tunlink(name: string): boolean\n\tremoveVfs(): Promise<boolean>\n\tpauseVfs(): unknown\n\tunpauseVfs(): Promise<unknown>\n\tisPaused(): boolean\n}\n\n/** The subset of the sqlite3 namespace the worker uses. */\nexport interface Sqlite3Api {\n\too1: { DB: new (opts: { filename: string }) => SqliteDb }\n\tinstallOpfsSAHPoolVfs?: (opts: {\n\t\tname: string\n\t\tforceReinitIfPreviouslyFailed?: boolean\n\t}) => Promise<OpfsPool>\n\tcapi?: {\n\t\tsqlite3_deserialize?: unknown\n\t\tsqlite3_progress_handler?: (\n\t\t\tdb: number,\n\t\t\tnOps: number,\n\t\t\thandler: (() => number) | 0,\n\t\t\tctx: number,\n\t\t) => void\n\t}\n}\n\n/** Reports the start and end of a wait on another holder. */\nexport interface BlockingReporter {\n\tblocked(): void\n\tunblocked(waitedMs: number): void\n}\n\n/** Free slots kept beyond the database being opened (other journals, imports). */\nconst OPFS_POOL_HEADROOM = 2\n\n/** How long a wait stays silent before it is reported as a blocking state. */\nconst BLOCKED_REPORT_AFTER_MS = 750\n\n/** Install attempts after the handle probe said \"free\" (covers the release race). */\nconst INSTALL_RACE_ATTEMPTS = 20\n\n/** Headless browsers and some profiles hang on OPFS VFS install. */\nconst OPFS_INIT_TIMEOUT_MS = 10_000\n\nconst OPAQUE_DIR_NAME = '.opaque'\n\n/** Why a durable pool could not be obtained. Contention is never a reason: it waits. */\nexport class PoolUnavailableError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly reason: 'unsupported' | 'timeout' | 'lock-conflict',\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'PoolUnavailableError'\n\t}\n}\n\n/** True when this worker has every API the SAH pool needs. */\nexport function opfsSahSupported(sqlite3: Sqlite3Api): boolean {\n\tconst g = globalThis as Record<string, unknown>\n\tconst fileHandle = g.FileSystemFileHandle as { prototype?: Record<string, unknown> } | undefined\n\treturn (\n\t\ttypeof sqlite3.installOpfsSAHPoolVfs === 'function' &&\n\t\ttypeof g.FileSystemDirectoryHandle !== 'undefined' &&\n\t\ttypeof fileHandle?.prototype?.createSyncAccessHandle === 'function' &&\n\t\ttypeof navigator !== 'undefined' &&\n\t\ttypeof navigator.storage?.getDirectory === 'function'\n\t)\n}\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms))\n}\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() =>\n\t\t\t\t\t\treject(new PoolUnavailableError(`${label} timed out after ${timeoutMs}ms`, 'timeout')),\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\n/**\n * Acquire an exclusive Web Lock and hold it until the returned release function\n * is called (or this worker terminates). Waits for a live holder, reporting the\n * wait once it lasts long enough to matter. Without the Web Locks API (very old\n * engines that also lack the SAH pool) it returns a no-op release.\n */\nexport async function holdExclusiveLock(\n\tname: string,\n\treporter?: BlockingReporter,\n): Promise<() => void> {\n\tconst locks = typeof navigator !== 'undefined' ? navigator.locks : undefined\n\tif (!locks || typeof locks.request !== 'function') {\n\t\treturn () => {}\n\t}\n\tconst grab = (ifAvailable: boolean): Promise<(() => void) | null> =>\n\t\tnew Promise<(() => void) | null>((resolve, reject) => {\n\t\t\tlocks\n\t\t\t\t.request(name, { mode: 'exclusive', ifAvailable }, (lock) => {\n\t\t\t\t\tif (lock === null) {\n\t\t\t\t\t\tresolve(null)\n\t\t\t\t\t\treturn undefined\n\t\t\t\t\t}\n\t\t\t\t\treturn new Promise<void>((release) => {\n\t\t\t\t\t\tresolve(() => release())\n\t\t\t\t\t})\n\t\t\t\t})\n\t\t\t\t.catch(reject)\n\t\t})\n\n\tconst immediate = await grab(true)\n\tif (immediate) return immediate\n\tconst start = Date.now()\n\treporter?.blocked()\n\tconst release = await grab(false)\n\tif (!release) {\n\t\tthrow new PoolUnavailableError(`Web Lock \"${name}\" was not granted`, 'lock-conflict')\n\t}\n\treporter?.unblocked(Date.now() - start)\n\treturn release\n}\n\ninterface DirHandle {\n\tgetDirectoryHandle(name: string, options?: { create?: boolean }): Promise<DirHandle>\n\tremoveEntry(name: string, options?: { recursive?: boolean }): Promise<void>\n\tentries(): AsyncIterable<[string, { kind: string }]>\n}\n\ninterface FileHandleWithSah {\n\tkind: 'file'\n\tcreateSyncAccessHandle(): Promise<{ close(): void }>\n}\n\nasync function opfsRoot(): Promise<DirHandle> {\n\treturn (await navigator.storage.getDirectory()) as unknown as DirHandle\n}\n\nasync function childDirectory(parent: DirHandle, name: string): Promise<DirHandle | null> {\n\ttry {\n\t\treturn await parent.getDirectoryHandle(name)\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/** Whether a pool's directory exists in OPFS (it may still be empty). */\nexport async function poolDirectoryExists(poolName: string): Promise<boolean> {\n\treturn (await childDirectory(await opfsRoot(), opfsPoolDirectory(poolName))) !== null\n}\n\nfunction isHandleBusy(error: unknown): boolean {\n\tconst name = (error as { name?: string } | null)?.name\n\treturn name === 'NoModificationAllowedError' || name === 'InvalidStateError'\n}\n\n/**\n * True when some file of the pool still has an open SyncAccessHandle elsewhere\n * (a live owner, or a terminated owner whose handles are still being released).\n */\nasync function poolHandlesBusy(poolName: string): Promise<boolean> {\n\tconst dir = await childDirectory(await opfsRoot(), opfsPoolDirectory(poolName))\n\tif (!dir) return false\n\tconst opaque = await childDirectory(dir, OPAQUE_DIR_NAME)\n\tif (!opaque) return false\n\tfor await (const [, handle] of opaque.entries()) {\n\t\tif (handle.kind !== 'file') continue\n\t\ttry {\n\t\t\tconst access = await (handle as unknown as FileHandleWithSah).createSyncAccessHandle()\n\t\t\taccess.close()\n\t\t} catch (error) {\n\t\t\tif (isHandleBusy(error)) return true\n\t\t\tthrow error\n\t\t}\n\t}\n\treturn false\n}\n\n/**\n * Wait until every file in the pool can be opened by this worker. Waits as long\n * as a holder exists (a beta.12 tab that never takes the pool lock, or a raw\n * user of the pool), reporting the blocking state; never gives up and falls back.\n */\nasync function waitForPoolHandles(poolName: string, reporter?: BlockingReporter): Promise<void> {\n\tconst start = Date.now()\n\tlet reported = false\n\tlet delay = 15\n\twhile (await poolHandlesBusy(poolName)) {\n\t\tif (!reported && Date.now() - start >= BLOCKED_REPORT_AFTER_MS) {\n\t\t\treported = true\n\t\t\treporter?.blocked()\n\t\t}\n\t\tawait sleep(delay)\n\t\tdelay = Math.min(delay * 2, 500)\n\t}\n\tif (reported) reporter?.unblocked(Date.now() - start)\n}\n\n/**\n * Install (or resume) a pool this worker already holds the pool lock for. The\n * bounded retry with `forceReinitIfPreviouslyFailed` covers only the residual\n * handle-release window; sqlite-wasm otherwise caches a failed install forever.\n */\nexport async function installPool(\n\tsqlite3: Sqlite3Api,\n\tpoolName: string,\n\treporter?: BlockingReporter,\n): Promise<OpfsPool> {\n\tconst install = sqlite3.installOpfsSAHPoolVfs\n\tif (!install || !opfsSahSupported(sqlite3)) {\n\t\tthrow new PoolUnavailableError('OPFS SyncAccessHandle pool is not supported', 'unsupported')\n\t}\n\tlet lastError: unknown = null\n\tfor (let attempt = 0; attempt < INSTALL_RACE_ATTEMPTS; attempt += 1) {\n\t\tawait waitForPoolHandles(poolName, reporter)\n\t\ttry {\n\t\t\tconst pool = await withTimeout(\n\t\t\t\tinstall({ name: poolName, forceReinitIfPreviouslyFailed: true }),\n\t\t\t\tOPFS_INIT_TIMEOUT_MS,\n\t\t\t\t'OPFS VFS install',\n\t\t\t)\n\t\t\tif (pool.isPaused()) {\n\t\t\t\tawait pool.unpauseVfs()\n\t\t\t}\n\t\t\treturn pool\n\t\t} catch (error) {\n\t\t\tif (error instanceof PoolUnavailableError) throw error\n\t\t\tlastError = error\n\t\t\tif (!isHandleBusy(error)) break\n\t\t\tawait sleep(Math.min(25 * 2 ** attempt, 250))\n\t\t}\n\t}\n\tconst message = lastError instanceof Error ? lastError.message : String(lastError)\n\tif (isHandleBusy(lastError)) {\n\t\tthrow new PoolUnavailableError(\n\t\t\t`OPFS pool \"${poolName}\" stayed busy: ${message}`,\n\t\t\t'lock-conflict',\n\t\t)\n\t}\n\tthrow new PoolUnavailableError(\n\t\t`OPFS pool \"${poolName}\" could not be installed: ${message}`,\n\t\t'unsupported',\n\t)\n}\n\n/**\n * Grow the pool to fit the database about to be opened plus its journal before\n * opening it (NEW-STORE-7). Slots are empty pre-allocated files, so this is\n * cheap; files are never evicted.\n */\nexport async function ensurePoolCapacity(pool: OpfsPool): Promise<void> {\n\tawait pool.reserveMinimumCapacity(pool.getFileCount() + 2 + OPFS_POOL_HEADROOM)\n}\n\n/** Runs `PRAGMA quick_check` and throws unless the database reports `ok`. */\nexport function assertDatabaseHealthy(db: SqliteDb, label: string): void {\n\tconst rows = db.exec({\n\t\tsql: 'PRAGMA quick_check',\n\t\treturnValue: 'resultRows',\n\t\trowMode: 'array',\n\t}) as unknown[][]\n\tconst verdict = rows?.[0]?.[0]\n\tif (verdict !== 'ok') {\n\t\tthrow new Error(`${label} failed integrity check: ${String(verdict)}`)\n\t}\n}\n\n/** Release the pool's handles (database files must already be closed). */\nexport function pausePool(pool: OpfsPool): void {\n\tif (!pool.isPaused()) {\n\t\tpool.pauseVfs()\n\t}\n}\n\n/**\n * Move a database file from the origin-wide beta.12 pool (`kora-opfs`) into its\n * own pool, the first time the database opens under W8a.\n *\n * - Runs only when the legacy pool directory exists. Holders of the legacy pool\n * (another migrating worker, or a beta.12 tab still open) are waited for, never\n * raced: a beta.12 tab keeps the new tab in the reported blocking state.\n * - Opening the legacy file first lets SQLite roll back a hot journal, so the\n * exported image is consistent. The imported copy must pass `quick_check`\n * before the legacy copy is removed.\n * - The legacy pool is kept while it still holds other databases and removed\n * once its last one has moved.\n *\n * @returns true when this call moved the database.\n */\nexport async function migrateFromLegacyPool(\n\tsqlite3: Sqlite3Api,\n\ttarget: OpfsPool,\n\tpoolPath: string,\n\treporter?: BlockingReporter,\n): Promise<boolean> {\n\tif (!(await poolDirectoryExists(LEGACY_OPFS_POOL_NAME))) {\n\t\treturn false\n\t}\n\tconst releaseLegacyLock = await holdExclusiveLock(\n\t\topfsPoolLockName(LEGACY_OPFS_POOL_NAME),\n\t\treporter,\n\t)\n\ttry {\n\t\t// Another worker may have finished the last migration while we waited.\n\t\tif (!(await poolDirectoryExists(LEGACY_OPFS_POOL_NAME))) {\n\t\t\treturn false\n\t\t}\n\t\tconst legacy = await installPool(sqlite3, LEGACY_OPFS_POOL_NAME, reporter)\n\t\ttry {\n\t\t\tif (!legacy.getFileNames().includes(poolPath)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst legacyDb = new legacy.OpfsSAHPoolDb(poolPath)\n\t\t\ttry {\n\t\t\t\tassertDatabaseHealthy(legacyDb, `Legacy database ${poolPath}`)\n\t\t\t} finally {\n\t\t\t\tlegacyDb.close()\n\t\t\t}\n\t\t\tconst bytes = legacy.exportFile(poolPath)\n\t\t\tif (bytes.byteLength === 0) {\n\t\t\t\t// An empty file left by a failed beta.12 open holds no data.\n\t\t\t\tlegacy.unlink(poolPath)\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tawait ensurePoolCapacity(target)\n\t\t\tawait target.importDb(poolPath, bytes)\n\t\t\tlet migratedDb: SqliteDb | null = null\n\t\t\ttry {\n\t\t\t\tmigratedDb = new target.OpfsSAHPoolDb(poolPath)\n\t\t\t\tassertDatabaseHealthy(migratedDb, `Migrated database ${poolPath}`)\n\t\t\t} catch (error) {\n\t\t\t\tmigratedDb?.close()\n\t\t\t\tmigratedDb = null\n\t\t\t\t// Keep the legacy copy as the source of truth; drop the bad import.\n\t\t\t\ttarget.unlink(poolPath)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t\tmigratedDb.close()\n\t\t\tlegacy.unlink(poolPath)\n\t\t\tlegacy.unlink(`${poolPath}-journal`)\n\t\t\treturn true\n\t\t} finally {\n\t\t\tif (legacy.getFileCount() === 0) {\n\t\t\t\tawait legacy.removeVfs()\n\t\t\t} else {\n\t\t\t\tpausePool(legacy)\n\t\t\t}\n\t\t}\n\t} finally {\n\t\treleaseLegacyLock()\n\t}\n}\n","import { WorkerInitError } from '../errors'\n\n/** How long SQLite WASM may take to initialize before the open fails. */\nexport const SQLITE_INIT_TIMEOUT_MS = 60_000\n\n/** Subscribes to unhandled promise rejections; returns the unsubscribe function. */\nexport type UnhandledRejectionSource = (listener: (reason: unknown) => void) => () => void\n\n/** Options for {@link loadSqliteModule}. */\nexport interface LoadSqliteModuleOptions {\n\t/** Options passed to the module's init function (Emscripten module arguments). */\n\tinitOptions?: Record<string, unknown>\n\t/** Where unhandled rejections are observed. Defaults to the global scope's event. */\n\tunhandledRejections?: UnhandledRejectionSource\n\t/** Init timeout in milliseconds. Defaults to {@link SQLITE_INIT_TIMEOUT_MS}. */\n\ttimeoutMs?: number\n}\n\n/**\n * Initialize the SQLite WASM module, failing fast when the `.wasm` cannot be fetched\n * or compiled (F15).\n *\n * The sqlite-wasm build installs its own `instantiateWasm` hook, which fetches and\n * compiles the binary but drops the resulting promise: when the fetch fails (the\n * device is offline before the binary was ever cached) or the response is not WASM\n * (a 404 page), that rejection is unhandled and the module's init promise never\n * settles. Waiting for the init timeout then holds the app for a full minute. While\n * init runs, an unhandled fetch or WebAssembly error is therefore taken as the init's\n * failure and rejects at once.\n *\n * @param init - The module's init function (`@sqlite.org/sqlite-wasm`'s default export)\n * @param options - Init options, the rejection source (tests) and the timeout\n * @returns The initialized module\n * @throws {WorkerInitError} When the binary cannot be loaded, or init times out\n */\nexport async function loadSqliteModule<T>(\n\tinit: (options?: Record<string, unknown>) => Promise<unknown>,\n\toptions: LoadSqliteModuleOptions = {},\n): Promise<T> {\n\tconst timeoutMs = options.timeoutMs ?? SQLITE_INIT_TIMEOUT_MS\n\tconst source = options.unhandledRejections ?? globalUnhandledRejections\n\tlet timer: ReturnType<typeof setTimeout> | undefined\n\tlet unsubscribe: (() => void) | undefined\n\ttry {\n\t\treturn (await Promise.race([\n\t\t\tinit(options.initOptions),\n\t\t\tnew Promise<never>((_, reject) => {\n\t\t\t\tunsubscribe = source((reason) => {\n\t\t\t\t\tif (!isWasmLoadFailure(reason)) return\n\t\t\t\t\treject(\n\t\t\t\t\t\tnew WorkerInitError(\n\t\t\t\t\t\t\t`could not load the SQLite WebAssembly binary (sqlite3.wasm): ${describe(reason)}. The device may be offline before the app was cached, or the file is not served (check the URL and the application/wasm MIME type).`,\n\t\t\t\t\t\t\t{ cause: describe(reason) },\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t})\n\t\t\t\ttimer = setTimeout(\n\t\t\t\t\t() =>\n\t\t\t\t\t\treject(\n\t\t\t\t\t\t\tnew WorkerInitError(`SQLite3 module init timed out after ${String(timeoutMs)}ms`),\n\t\t\t\t\t\t),\n\t\t\t\t\ttimeoutMs,\n\t\t\t\t)\n\t\t\t}),\n\t\t])) as T\n\t} finally {\n\t\tif (timer !== undefined) clearTimeout(timer)\n\t\tunsubscribe?.()\n\t}\n}\n\n/**\n * True for the errors a failed `.wasm` fetch or compile produces: `TypeError` from\n * `fetch` or `instantiateStreaming` (network failure, wrong MIME type) and the\n * WebAssembly compile, link and runtime errors.\n */\nfunction isWasmLoadFailure(reason: unknown): boolean {\n\tif (reason instanceof TypeError) return true\n\tconst wasm = (globalThis as { WebAssembly?: Record<string, unknown> }).WebAssembly\n\tif (!wasm) return false\n\tfor (const name of ['CompileError', 'LinkError', 'RuntimeError']) {\n\t\tconst ctor = wasm[name]\n\t\tif (typeof ctor === 'function' && reason instanceof (ctor as new () => Error)) return true\n\t}\n\treturn false\n}\n\nfunction describe(reason: unknown): string {\n\treturn reason instanceof Error ? reason.message : String(reason)\n}\n\n/** Unhandled rejections of the current global scope (a worker or a window). */\nconst globalUnhandledRejections: UnhandledRejectionSource = (listener) => {\n\tconst scope = globalThis as {\n\t\taddEventListener?: (type: string, handler: (event: { reason?: unknown }) => void) => void\n\t\tremoveEventListener?: (type: string, handler: (event: { reason?: unknown }) => void) => void\n\t}\n\tif (typeof scope.addEventListener !== 'function') return () => {}\n\tconst handler = (event: { reason?: unknown }): void => listener(event.reason)\n\tscope.addEventListener('unhandledrejection', handler)\n\treturn () => scope.removeEventListener?.('unhandledrejection', handler)\n}\n","/// <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`. Each worker serves exactly one database\n * and owns that database's OPFS SyncAccessHandle pool (one pool per database,\n * W8a). Pool ownership, the pool Web Lock and the beta.12 legacy-pool migration\n * live in {@link file://./opfs-pool-ownership.ts}.\n *\n * This file cannot be unit-tested in Node (no WASM/OPFS); it is exercised through\n * the real-browser suite.\n */\n\nimport {\n\tSTORED_SCHEMA_VERSION_SQL,\n\tparseSchemaCeiling,\n\tschemaAheadMessage,\n\tstoredSchemaVersion,\n} from '../migrations/schema-ceiling'\nimport { opfsPoolLockName, opfsPoolNameFor, opfsPoolPath } from './opfs-names'\nimport {\n\ttype BlockingReporter,\n\ttype OpfsPool,\n\tPoolUnavailableError,\n\ttype Sqlite3Api,\n\ttype SqliteDb,\n\tensurePoolCapacity,\n\tholdExclusiveLock,\n\tinstallPool,\n\tmigrateFromLegacyPool,\n\topfsSahSupported,\n\tpausePool,\n} from './opfs-pool-ownership'\nimport type { WorkerRequest, WorkerResponse, WorkerStatusEvent } from './sqlite-wasm-channel'\nimport { loadSqliteModule } from './sqlite-wasm-loader'\n\n/** Minimum gap between progress heartbeats sent from inside a long statement. */\nconst PROGRESS_HEARTBEAT_MS = 500\n/** SQLite VM instructions between progress-handler callbacks. */\nconst PROGRESS_HANDLER_OPS = 20_000\n\nlet sqlite3Promise: Promise<Sqlite3Api> | null = null\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\t// Fails fast when the .wasm cannot be fetched or compiled, instead of waiting out\n\t// the init timeout (F15).\n\treturn loadSqliteModule<Sqlite3Api>(initFn, initOptions ? { initOptions } : {})\n}\n\nfunction getSqlite3(): Promise<Sqlite3Api> {\n\tif (!sqlite3Promise) {\n\t\tconst loading = loadSqlite3()\n\t\tsqlite3Promise = loading\n\t\t// A failed load is not kept: the next open in this worker tries again (F15).\n\t\tloading.catch(() => {\n\t\t\tif (sqlite3Promise === loading) sqlite3Promise = null\n\t\t})\n\t}\n\treturn sqlite3Promise\n}\n\n/** Options for {@link createSqliteWasmCore}. */\nexport interface SqliteWasmCoreOptions {\n\t/** Posts unsolicited status (blocking state) to the tab that owns this worker. */\n\tpostEvent?: (event: WorkerStatusEvent) => void\n\t/**\n\t * Called from inside long-running statements (sqlite progress handler) so the\n\t * worker can keep announcing liveness to follower tabs while it is busy.\n\t */\n\tonProgress?: () => void\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 through the dedicated worker's\n * `postMessage`.\n */\nexport function createSqliteWasmCore(options: SqliteWasmCoreOptions = {}): SqliteWasmCore {\n\tlet db: SqliteDb | null = null\n\tlet sqlite3Api: Sqlite3Api | null = null\n\tlet persistent = false\n\tlet fallbackReason: 'timeout' | 'unsupported' | 'lock-conflict' | undefined\n\tlet pool: OpfsPool | null = null\n\tlet poolName: string | null = null\n\tlet releasePoolLock: (() => void) | null = null\n\tlet openInfo: { created: boolean; migratedFromLegacy: boolean } = {\n\t\tcreated: false,\n\t\tmigratedFromLegacy: false,\n\t}\n\tlet lastProgressBeat = 0\n\n\tfunction reporterFor(resource: 'pool' | 'legacy-pool', name: string): BlockingReporter {\n\t\treturn {\n\t\t\tblocked: () => options.postEvent?.({ kind: 'storage-blocked', resource, poolName: name }),\n\t\t\tunblocked: (waitedMs) =>\n\t\t\t\toptions.postEvent?.({ kind: 'storage-unblocked', resource, poolName: name, waitedMs }),\n\t\t}\n\t}\n\n\t/** Close the database and give the pool back: handles first, then the lock. */\n\tasync function releaseStorage(mode: 'pause' | 'remove'): Promise<void> {\n\t\tif (db) {\n\t\t\tdetachProgressHandler(db)\n\t\t\ttry {\n\t\t\t\tdb.close()\n\t\t\t} finally {\n\t\t\t\tdb = null\n\t\t\t}\n\t\t}\n\t\tif (pool) {\n\t\t\tif (mode === 'remove') {\n\t\t\t\tawait pool.removeVfs()\n\t\t\t} else {\n\t\t\t\tpausePool(pool)\n\t\t\t}\n\t\t\tpool = null\n\t\t}\n\t\treleasePoolLock?.()\n\t\treleasePoolLock = null\n\t}\n\n\tfunction attachProgressHandler(target: SqliteDb): void {\n\t\tconst register = sqlite3Api?.capi?.sqlite3_progress_handler\n\t\tif (!options.onProgress || typeof register !== 'function' || !target.pointer) return\n\t\tregister(\n\t\t\ttarget.pointer,\n\t\t\tPROGRESS_HANDLER_OPS,\n\t\t\t() => {\n\t\t\t\tconst now = Date.now()\n\t\t\t\tif (now - lastProgressBeat >= PROGRESS_HEARTBEAT_MS) {\n\t\t\t\t\tlastProgressBeat = now\n\t\t\t\t\toptions.onProgress?.()\n\t\t\t\t}\n\t\t\t\treturn 0\n\t\t\t},\n\t\t\t0,\n\t\t)\n\t}\n\n\tfunction detachProgressHandler(target: SqliteDb): void {\n\t\tconst register = sqlite3Api?.capi?.sqlite3_progress_handler\n\t\tif (typeof register !== 'function' || !target.pointer) return\n\t\ttry {\n\t\t\tregister(target.pointer, 0, 0, 0)\n\t\t} catch {\n\t\t\t// Closing the database releases the handler binding anyway.\n\t\t}\n\t}\n\n\tasync function openOpfs(\n\t\tsqlite3: Sqlite3Api,\n\t\tdbName: string,\n\t\tmustExist: boolean,\n\t): Promise<WorkerResponse | null> {\n\t\tconst name = opfsPoolNameFor(dbName)\n\t\tconst path = opfsPoolPath(dbName)\n\t\tpoolName = name\n\t\treleasePoolLock = await holdExclusiveLock(opfsPoolLockName(name), reporterFor('pool', name))\n\t\tpool = await installPool(sqlite3, name, reporterFor('pool', name))\n\n\t\tlet migratedFromLegacy = false\n\t\tif (!pool.getFileNames().includes(path)) {\n\t\t\tmigratedFromLegacy = await migrateFromLegacyPool(\n\t\t\t\tsqlite3,\n\t\t\t\tpool,\n\t\t\t\tpath,\n\t\t\t\treporterFor('legacy-pool', name),\n\t\t\t)\n\t\t}\n\t\tconst existedBefore = pool.getFileNames().includes(path)\n\t\tif (!existedBefore && mustExist) {\n\t\t\t// Do not leave behind the empty pool this probe just created.\n\t\t\tawait releaseStorage(pool.getFileCount() === 0 ? 'remove' : 'pause')\n\t\t\treturn { id: 0, type: 'error', message: `Database file ${path} not found`, code: 'NOT_FOUND' }\n\t\t}\n\t\tawait ensurePoolCapacity(pool)\n\t\ttry {\n\t\t\tdb = new pool.OpfsSAHPoolDb(path)\n\t\t} catch (error) {\n\t\t\tif (!existedBefore) pool.unlink(path)\n\t\t\tthrow error\n\t\t}\n\t\tpersistent = true\n\t\topenInfo = { created: !existedBefore, migratedFromLegacy }\n\t\treturn null\n\t}\n\n\tasync function open(\n\t\tid: number,\n\t\tddlStatements: string[],\n\t\tdbName: string,\n\t\tstorage: 'opfs' | 'memory',\n\t\tmustExist: boolean,\n\t): Promise<WorkerResponse> {\n\t\t// Re-run idempotent DDL on the existing handle rather than opening the\n\t\t// database a second time (a follower's open lands here on the leader).\n\t\tif (db) {\n\t\t\ttry {\n\t\t\t\tapplyDdl(db, ddlStatements)\n\t\t\t\treturn { id, type: 'success', data: buildOpenData() }\n\t\t\t} catch (error) {\n\t\t\t\treturn { id, type: 'error', message: (error as Error).message, code: 'INIT_ERROR' }\n\t\t\t}\n\t\t}\n\n\t\tlet createdPath: string | null = null\n\t\ttry {\n\t\t\tconst sqlite3 = await getSqlite3()\n\t\t\tsqlite3Api = sqlite3\n\t\t\tif (storage === 'opfs' && opfsSahSupported(sqlite3)) {\n\t\t\t\ttry {\n\t\t\t\t\tconst early = await openOpfs(sqlite3, dbName, mustExist)\n\t\t\t\t\tif (early) return { ...early, id }\n\t\t\t\t\tif (openInfo.created) createdPath = opfsPoolPath(dbName)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!(error instanceof PoolUnavailableError) || error.reason === 'lock-conflict') {\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t\t// Only an unsupported or hung OPFS selects memory here; the adapter\n\t\t\t\t\t// then reports it (and refuses writes unless the app opted in).\n\t\t\t\t\tawait releaseStorage('pause')\n\t\t\t\t\tfallbackReason = error.reason\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfallbackReason = 'unsupported'\n\t\t\t}\n\t\t\tif (!db) {\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\t// NEW-STORE-11: no `PRAGMA journal_mode = WAL` here. WAL needs the VFS's\n\t\t\t// shared-memory methods, which opfs-sahpool does not implement, so the pragma\n\t\t\t// was a silent no-op (the mode stayed `delete`). The OPFS database uses\n\t\t\t// SQLite's default rollback journal (DELETE), the in-memory fallback uses\n\t\t\t// `memory`; the actual mode is reported in the open result (`journalMode`).\n\t\t\tdb.exec({ sql: 'PRAGMA foreign_keys = ON' })\n\t\t\tapplyDdl(db, ddlStatements)\n\t\t\tattachProgressHandler(db)\n\t\t\treturn { id, type: 'success', data: buildOpenData() }\n\t\t} catch (error) {\n\t\t\t// A failed open removes only the file this open created (never existing\n\t\t\t// or migrated data) and gives the pool and its lock back (NEW-STORE-8).\n\t\t\tconst currentPool = pool\n\t\t\tif (db) {\n\t\t\t\ttry {\n\t\t\t\t\tdb.close()\n\t\t\t\t} catch {\n\t\t\t\t\t// Already failing; the original error is what matters.\n\t\t\t\t}\n\t\t\t\tdb = null\n\t\t\t}\n\t\t\tif (createdPath && currentPool) {\n\t\t\t\ttry {\n\t\t\t\t\tcurrentPool.unlink(createdPath)\n\t\t\t\t\tcurrentPool.unlink(`${createdPath}-journal`)\n\t\t\t\t} catch {\n\t\t\t\t\t// Best effort: an empty leftover slot is harmless.\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait releaseStorage('pause')\n\t\t\t} catch {\n\t\t\t\t// The worker is about to be terminated by the adapter anyway.\n\t\t\t}\n\t\t\tconst reason = error instanceof PoolUnavailableError ? error.reason : undefined\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\ttype: 'error',\n\t\t\t\tmessage: (error as Error).message,\n\t\t\t\tcode: 'INIT_ERROR',\n\t\t\t\tcontext: {\n\t\t\t\t\t...(reason ? { reason } : {}),\n\t\t\t\t\t...(createdPath ? { removedCreatedFile: createdPath } : {}),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction readJournalMode(): string | undefined {\n\t\tif (!db) return undefined\n\t\ttry {\n\t\t\tlet mode: string | undefined\n\t\t\tdb.exec({\n\t\t\t\tsql: 'PRAGMA journal_mode',\n\t\t\t\trowMode: 'object',\n\t\t\t\tcallback: (row: Record<string, unknown>) => {\n\t\t\t\t\tif (typeof row.journal_mode === 'string') mode = row.journal_mode\n\t\t\t\t},\n\t\t\t})\n\t\t\treturn mode\n\t\t} catch {\n\t\t\t// Diagnostic only: an unreadable mode must not fail the open.\n\t\t\treturn undefined\n\t\t}\n\t}\n\n\tfunction buildOpenData(): Record<string, unknown> {\n\t\tconst journalMode = readJournalMode()\n\t\treturn {\n\t\t\t...(journalMode ? { journalMode } : {}),\n\t\t\tpersistent,\n\t\t\t...(persistent ? {} : { fallbackReason: fallbackReason ?? 'unsupported' }),\n\t\t\t...(poolName && persistent ? { poolName } : {}),\n\t\t\tcreated: openInfo.created,\n\t\t\tmigratedFromLegacy: openInfo.migratedFromLegacy,\n\t\t}\n\t}\n\n\tfunction applyDdl(target: SqliteDb, ddlStatements: string[]): void {\n\t\tfor (const sql of ddlStatements) {\n\t\t\tconst ceiling = parseSchemaCeiling(sql)\n\t\t\tif (ceiling !== null) {\n\t\t\t\t// A database a newer build migrated gets none of this build's DDL (RT-109).\n\t\t\t\tconst rows: Array<{ value: unknown }> = []\n\t\t\t\ttarget.exec({\n\t\t\t\t\tsql: STORED_SCHEMA_VERSION_SQL,\n\t\t\t\t\trowMode: 'object',\n\t\t\t\t\tcallback: (row: Record<string, unknown>) => {\n\t\t\t\t\t\trows.push({ value: row.value })\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\tconst stored = storedSchemaVersion(rows)\n\t\t\t\tif (stored > ceiling) throw new Error(schemaAheadMessage(stored, ceiling))\n\t\t\t\tcontinue\n\t\t\t}\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\tasync function close(id: number, mode: 'pause' | 'remove'): Promise<WorkerResponse> {\n\t\ttry {\n\t\t\tawait releaseStorage(mode)\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: 'CLOSE_ERROR' }\n\t\t}\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\tif (typeof db.deserialize === 'function') {\n\t\t\ttry {\n\t\t\t\tdb.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(\n\t\t\t\t\t\trequest.id,\n\t\t\t\t\t\trequest.ddlStatements,\n\t\t\t\t\t\trequest.dbName ?? 'kora-db',\n\t\t\t\t\t\trequest.storage ?? 'opfs',\n\t\t\t\t\t\trequest.mustExist === true,\n\t\t\t\t\t)\n\t\t\t\tcase 'close':\n\t\t\t\t\treturn await close(request.id, 'pause')\n\t\t\t\tcase 'destroy':\n\t\t\t\t\treturn await close(request.id, 'remove')\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\tcase 'serve':\n\t\t\t\t\t// Handled by the worker entry, which owns the BroadcastChannel.\n\t\t\t\t\treturn { id: request.id, type: 'success' }\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 * One worker serves one database. Requests from the owning (leader) tab arrive\n * by postMessage; requests from follower tabs arrive on the database's\n * BroadcastChannel once the leader sends `serve`. Both go through one\n * {@link TransactionSerializingWorkerBridge}, so transaction spans from different\n * tabs never interleave, and the leader tab's main thread is not on the\n * follower path at all.\n *\n * This script cannot be tested in Node.js; it is validated in browser suites.\n */\n\nimport { TransactionSerializingWorkerBridge, startWorkerRpcRelay } from '../multi-tab/tab-storage'\nimport type { WorkerRpcRelay } from '../multi-tab/tab-storage'\nimport type {\n\tWorkerEventMessage,\n\tWorkerInboundMessage,\n\tWorkerResponse,\n} from './sqlite-wasm-channel'\nimport { createSqliteWasmCore } from './sqlite-wasm-worker-core'\n\ndeclare const self: DedicatedWorkerGlobalScope\n\nlet relay: WorkerRpcRelay | null = null\n\nconst core = createSqliteWasmCore({\n\tpostEvent: (event) => {\n\t\tconst message: WorkerEventMessage = { id: -1, type: 'event', event }\n\t\tself.postMessage(message)\n\t},\n\t// Keep followers' watchdogs fed while a long statement blocks this worker.\n\tonProgress: () => relay?.beat(),\n})\n\nconst serializer = new TransactionSerializingWorkerBridge({\n\tsend: (request) => core.handle(request),\n\tterminate: () => {},\n})\n\nself.onmessage = (event: MessageEvent<WorkerInboundMessage>): void => {\n\tconst { clientId, ...request } = event.data\n\tif (request.type === 'serve') {\n\t\tif (!relay) {\n\t\t\trelay = startWorkerRpcRelay(request.channelName, serializer)\n\t\t}\n\t\tconst response: WorkerResponse = { id: request.id, type: 'success' }\n\t\tself.postMessage(response)\n\t\treturn\n\t}\n\tvoid serializer.send(request, clientId).then(\n\t\t(response) => {\n\t\t\tif (request.type === 'close' || request.type === 'destroy') {\n\t\t\t\t// The pool is released; stop answering followers for this database.\n\t\t\t\trelay?.stop()\n\t\t\t\trelay = null\n\t\t\t}\n\t\t\tself.postMessage(response)\n\t\t},\n\t\t(error: unknown) => {\n\t\t\tconst response: WorkerResponse = {\n\t\t\t\tid: request.id,\n\t\t\t\ttype: 'error',\n\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\tcode: 'WORKER_ERROR',\n\t\t\t}\n\t\t\tself.postMessage(response)\n\t\t},\n\t)\n}\n"],"mappings":"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","names":["release"]}