@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.
Files changed (58) hide show
  1. package/dist/adapters/better-sqlite3.d.cts +1 -1
  2. package/dist/adapters/better-sqlite3.d.ts +1 -1
  3. package/dist/adapters/indexeddb.cjs +4 -1
  4. package/dist/adapters/indexeddb.cjs.map +1 -1
  5. package/dist/adapters/indexeddb.d.cts +2 -2
  6. package/dist/adapters/indexeddb.d.ts +2 -2
  7. package/dist/adapters/indexeddb.js +1 -1
  8. package/dist/adapters/sqlite-wasm-shared-host.cjs +292 -42
  9. package/dist/adapters/sqlite-wasm-shared-host.cjs.map +1 -1
  10. package/dist/adapters/sqlite-wasm-shared-host.d.cts +43 -25
  11. package/dist/adapters/sqlite-wasm-shared-host.d.ts +43 -25
  12. package/dist/adapters/sqlite-wasm-shared-host.js +33 -42
  13. package/dist/adapters/sqlite-wasm-shared-host.js.map +1 -1
  14. package/dist/adapters/sqlite-wasm-worker.cjs +206 -208
  15. package/dist/adapters/sqlite-wasm-worker.cjs.map +1 -1
  16. package/dist/adapters/sqlite-wasm-worker.js +8 -257
  17. package/dist/adapters/sqlite-wasm-worker.js.map +1 -1
  18. package/dist/adapters/sqlite-wasm.cjs +4 -1
  19. package/dist/adapters/sqlite-wasm.cjs.map +1 -1
  20. package/dist/adapters/sqlite-wasm.d.cts +3 -3
  21. package/dist/adapters/sqlite-wasm.d.ts +3 -3
  22. package/dist/adapters/sqlite-wasm.js +1 -1
  23. package/dist/{backup-IQE4QC7Q.js → backup-5S7K2Z35.js} +3 -3
  24. package/dist/chunk-3Y2IERBF.js +255 -0
  25. package/dist/chunk-3Y2IERBF.js.map +1 -0
  26. package/dist/{chunk-RCTG3IJG.js → chunk-CYO3YKFL.js} +2 -2
  27. package/dist/{chunk-6NKLDBTY.js → chunk-GSJ7EEUC.js} +2 -1
  28. package/dist/chunk-GSJ7EEUC.js.map +1 -0
  29. package/dist/{chunk-OCOGQRHW.js → chunk-HS6DBMST.js} +2 -2
  30. package/dist/{chunk-2ZRQGFEF.js → chunk-Q57CHIIN.js} +5 -2
  31. package/dist/chunk-Q57CHIIN.js.map +1 -0
  32. package/dist/{chunk-UXRWVXBP.js → chunk-RL43UYQZ.js} +2 -2
  33. package/dist/{export-audit-MT2LTMIN.js → export-audit-ODGQTQIK.js} +3 -3
  34. package/dist/index.cjs +120 -3
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +27 -4
  37. package/dist/index.d.ts +27 -4
  38. package/dist/index.js +128 -11
  39. package/dist/index.js.map +1 -1
  40. package/dist/internal.cjs +1 -0
  41. package/dist/internal.cjs.map +1 -1
  42. package/dist/internal.d.cts +3 -3
  43. package/dist/internal.d.ts +3 -3
  44. package/dist/internal.js +2 -2
  45. package/dist/{sqlite-wasm-channel-CNHRf-m2.d.cts → sqlite-wasm-channel-Bx57s8Cq.d.cts} +1 -1
  46. package/dist/{sqlite-wasm-channel-CNHRf-m2.d.ts → sqlite-wasm-channel-Bx57s8Cq.d.ts} +1 -1
  47. package/dist/{types-5h4Hqcwc.d.ts → types-C1kigrWz.d.ts} +1 -1
  48. package/dist/{types-k6AZgiH4.d.ts → types-D1MzKVmk.d.cts} +10 -0
  49. package/dist/{types-k6AZgiH4.d.cts → types-D1MzKVmk.d.ts} +10 -0
  50. package/dist/{types-DfPiPwKr.d.cts → types-DAo9oduO.d.cts} +1 -1
  51. package/package.json +2 -2
  52. package/dist/chunk-2ZRQGFEF.js.map +0 -1
  53. package/dist/chunk-6NKLDBTY.js.map +0 -1
  54. /package/dist/{backup-IQE4QC7Q.js.map → backup-5S7K2Z35.js.map} +0 -0
  55. /package/dist/{chunk-RCTG3IJG.js.map → chunk-CYO3YKFL.js.map} +0 -0
  56. /package/dist/{chunk-OCOGQRHW.js.map → chunk-HS6DBMST.js.map} +0 -0
  57. /package/dist/{chunk-UXRWVXBP.js.map → chunk-RL43UYQZ.js.map} +0 -0
  58. /package/dist/{export-audit-MT2LTMIN.js.map → export-audit-ODGQTQIK.js.map} +0 -0
@@ -1,31 +1,19 @@
1
+ import {
2
+ createSqliteWasmCore
3
+ } from "../chunk-3Y2IERBF.js";
4
+
1
5
  // src/adapters/sqlite-wasm-shared-host.ts
2
6
  var SW_REQUEST = "kora-sw-request";
3
7
  var SW_RESPONSE = "kora-sw-response";
4
8
  function createSharedWorkerHost(options) {
5
- const pools = /* @__PURE__ */ new Map();
6
- function getPool(dbName, workerUrl) {
7
- const existing = pools.get(dbName);
8
- if (existing) {
9
- return existing;
9
+ const cores = /* @__PURE__ */ new Map();
10
+ function coreFor(dbName) {
11
+ let core = cores.get(dbName);
12
+ if (!core) {
13
+ core = options.createCore();
14
+ cores.set(dbName, core);
10
15
  }
11
- const worker = options.spawnWorker(workerUrl);
12
- const entry = { worker, nextInnerId: 1, pending: /* @__PURE__ */ new Map() };
13
- worker.onmessage = (event) => {
14
- const response = event.data;
15
- const waiting = entry.pending.get(response.id);
16
- if (!waiting) {
17
- return;
18
- }
19
- entry.pending.delete(response.id);
20
- const msg = {
21
- type: SW_RESPONSE,
22
- requestId: waiting.requestId,
23
- response
24
- };
25
- waiting.port.postMessage(msg);
26
- };
27
- pools.set(dbName, entry);
28
- return entry;
16
+ return core;
29
17
  }
30
18
  function connect(port) {
31
19
  port.start();
@@ -34,35 +22,38 @@ function createSharedWorkerHost(options) {
34
22
  if (data?.type !== SW_REQUEST) {
35
23
  return;
36
24
  }
37
- const entry = getPool(data.dbName, data.workerUrl);
38
- const innerId = entry.nextInnerId;
39
- entry.nextInnerId += 1;
40
- entry.pending.set(innerId, { requestId: data.requestId, port });
41
- entry.worker.postMessage({ ...data.request, id: innerId });
42
- });
43
- port.addEventListener("messageerror", () => {
44
- for (const entry of pools.values()) {
45
- for (const [innerId, waiting] of entry.pending) {
46
- if (waiting.port === port) {
47
- entry.pending.delete(innerId);
48
- }
25
+ const core = coreFor(data.dbName);
26
+ void core.handle(data.request).then(
27
+ (response) => {
28
+ port.postMessage({ type: SW_RESPONSE, requestId: data.requestId, response });
29
+ },
30
+ (error) => {
31
+ const message = error instanceof Error ? error.message : "SharedWorker core failed";
32
+ port.postMessage({
33
+ type: SW_RESPONSE,
34
+ requestId: data.requestId,
35
+ response: {
36
+ id: data.request.id,
37
+ type: "error",
38
+ message,
39
+ code: "SHARED_WORKER_CORE_ERROR"
40
+ }
41
+ });
49
42
  }
50
- }
43
+ );
51
44
  });
52
45
  }
53
46
  return { connect };
54
47
  }
55
- if (typeof self !== "undefined" && "onconnect" in self) {
56
- const host = createSharedWorkerHost({
57
- spawnWorker: (workerUrl) => new Worker(workerUrl, { type: "module" })
58
- });
59
- self.onconnect = (event) => {
48
+ if (typeof SharedWorkerGlobalScope !== "undefined" && typeof self !== "undefined" && self instanceof SharedWorkerGlobalScope) {
49
+ const host = createSharedWorkerHost({ createCore: createSqliteWasmCore });
50
+ self.addEventListener("connect", (event) => {
60
51
  const port = event.ports[0];
61
52
  if (!port) {
62
53
  return;
63
54
  }
64
55
  host.connect(port);
65
- };
56
+ });
66
57
  }
67
58
  export {
68
59
  createSharedWorkerHost
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/adapters/sqlite-wasm-shared-host.ts"],"sourcesContent":["/// <reference lib=\"webworker\" />\n/**\n * SharedWorker host: one DedicatedWorker (SQLite WASM) per `dbName` per browser origin.\n *\n * Bundle this file separately and pass its URL as `store.sharedWorkerUrl` alongside `workerUrl`.\n *\n * @example\n * ```typescript\n * createApp({\n * store: {\n * workerUrl: '/sqlite-wasm-worker.js',\n * sharedWorkerUrl: '/sqlite-wasm-shared-host.js',\n * },\n * })\n * ```\n */\n\nimport type { WorkerRequest, WorkerResponse } from './sqlite-wasm-channel'\n\nconst SW_REQUEST = 'kora-sw-request'\nconst SW_RESPONSE = 'kora-sw-response'\n\ninterface SharedWorkerRpcRequest {\n\ttype: typeof SW_REQUEST\n\trequestId: string\n\tdbName: string\n\tworkerUrl: string\n\trequest: WorkerRequest\n}\n\ninterface SharedWorkerRpcResponse {\n\ttype: typeof SW_RESPONSE\n\trequestId: string\n\tresponse: WorkerResponse\n}\n\n/**\n * Minimal structural view of the inner SQLite DedicatedWorker the host owns.\n * Declared here (rather than using the DOM `Worker` type directly) so the host\n * routing can be unit-tested with a mock worker.\n */\nexport interface HostWorker {\n\tpostMessage(message: WorkerRequest): void\n\tonmessage: ((event: { data: WorkerResponse }) => void) | null\n\tterminate?(): void\n}\n\n/** Minimal structural view of a connected client `MessagePort`. */\nexport interface HostPort {\n\tstart(): void\n\tpostMessage(message: SharedWorkerRpcResponse): void\n\taddEventListener(\n\t\ttype: 'message' | 'messageerror',\n\t\thandler: (event: { data: unknown }) => void,\n\t): void\n}\n\nexport interface SharedWorkerHostOptions {\n\t/** Spawns the inner SQLite worker for a database. Injectable for tests. */\n\tspawnWorker: (workerUrl: string) => HostWorker\n}\n\ninterface WorkerEntry {\n\tworker: HostWorker\n\t/**\n\t * Monotonic id assigned to each request FORWARDED to the inner worker. The\n\t * adapter always sends `request.id === 0` (uniqueness is a bridge concern), and\n\t * every tab shares one inner worker, so the host must mint its own unique id per\n\t * request or concurrent requests collide on the correlation key. This mirrors\n\t * `WebWorkerBridge`, which reassigns `id` before posting to its worker.\n\t */\n\tnextInnerId: number\n\t/** innerId -> the client waiting for that response. */\n\tpending: Map<number, { requestId: string; port: HostPort }>\n}\n\nexport interface SharedWorkerHost {\n\t/** Wire a newly connected client port into the host. */\n\tconnect(port: HostPort): void\n}\n\n/**\n * Creates the SharedWorker host routing core: one inner SQLite worker per\n * `dbName`, fanning requests from every connected tab through it and routing each\n * response back to the exact requester.\n *\n * Correlation is keyed on a host-minted inner id, never on the incoming\n * `request.id` (which is `0` for every request from every tab). This is what keeps\n * concurrent and multi-tab requests from resolving each other's responses.\n */\nexport function createSharedWorkerHost(options: SharedWorkerHostOptions): SharedWorkerHost {\n\tconst pools = new Map<string, WorkerEntry>()\n\n\tfunction getPool(dbName: string, workerUrl: string): WorkerEntry {\n\t\tconst existing = pools.get(dbName)\n\t\tif (existing) {\n\t\t\treturn existing\n\t\t}\n\n\t\tconst worker = options.spawnWorker(workerUrl)\n\t\tconst entry: WorkerEntry = { worker, nextInnerId: 1, pending: new Map() }\n\n\t\tworker.onmessage = (event: { data: WorkerResponse }): void => {\n\t\t\tconst response = event.data\n\t\t\tconst waiting = entry.pending.get(response.id)\n\t\t\tif (!waiting) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tentry.pending.delete(response.id)\n\t\t\tconst msg: SharedWorkerRpcResponse = {\n\t\t\t\ttype: SW_RESPONSE,\n\t\t\t\trequestId: waiting.requestId,\n\t\t\t\tresponse,\n\t\t\t}\n\t\t\twaiting.port.postMessage(msg)\n\t\t}\n\n\t\tpools.set(dbName, entry)\n\t\treturn entry\n\t}\n\n\tfunction connect(port: HostPort): void {\n\t\tport.start()\n\n\t\tport.addEventListener('message', (event: { data: unknown }): void => {\n\t\t\tconst data = event.data as SharedWorkerRpcRequest | undefined\n\t\t\tif (data?.type !== SW_REQUEST) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst entry = getPool(data.dbName, data.workerUrl)\n\t\t\tconst innerId = entry.nextInnerId\n\t\t\tentry.nextInnerId += 1\n\t\t\tentry.pending.set(innerId, { requestId: data.requestId, port })\n\t\t\t// Reassign a unique inner id. The client bridge correlates on the outer\n\t\t\t// requestId, so rewriting request.id here is transparent to the caller.\n\t\t\tentry.worker.postMessage({ ...data.request, id: innerId })\n\t\t})\n\n\t\tport.addEventListener('messageerror', (): void => {\n\t\t\t// Best-effort cleanup: drop any in-flight requests routed to this port so a\n\t\t\t// disconnected tab does not leak pending entries.\n\t\t\tfor (const entry of pools.values()) {\n\t\t\t\tfor (const [innerId, waiting] of entry.pending) {\n\t\t\t\t\tif (waiting.port === port) {\n\t\t\t\t\t\tentry.pending.delete(innerId)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\treturn { connect }\n}\n\n// Wire the host to the SharedWorker global only when running as an actual\n// SharedWorker. Guarding this keeps the module importable in Node test runtimes,\n// where `createSharedWorkerHost` is unit-tested directly with mock ports/workers.\ndeclare const self: SharedWorkerGlobalScope\nif (typeof self !== 'undefined' && 'onconnect' in self) {\n\tconst host = createSharedWorkerHost({\n\t\tspawnWorker: (workerUrl: string): HostWorker =>\n\t\t\tnew Worker(workerUrl, { type: 'module' }) as unknown as HostWorker,\n\t})\n\n\tself.onconnect = (event: MessageEvent): void => {\n\t\tconst port = event.ports[0]\n\t\tif (!port) {\n\t\t\treturn\n\t\t}\n\t\thost.connect(port as unknown as HostPort)\n\t}\n}\n"],"mappings":";AAmBA,IAAM,aAAa;AACnB,IAAM,cAAc;AAsEb,SAAS,uBAAuB,SAAoD;AAC1F,QAAM,QAAQ,oBAAI,IAAyB;AAE3C,WAAS,QAAQ,QAAgB,WAAgC;AAChE,UAAM,WAAW,MAAM,IAAI,MAAM;AACjC,QAAI,UAAU;AACb,aAAO;AAAA,IACR;AAEA,UAAM,SAAS,QAAQ,YAAY,SAAS;AAC5C,UAAM,QAAqB,EAAE,QAAQ,aAAa,GAAG,SAAS,oBAAI,IAAI,EAAE;AAExE,WAAO,YAAY,CAAC,UAA0C;AAC7D,YAAM,WAAW,MAAM;AACvB,YAAM,UAAU,MAAM,QAAQ,IAAI,SAAS,EAAE;AAC7C,UAAI,CAAC,SAAS;AACb;AAAA,MACD;AACA,YAAM,QAAQ,OAAO,SAAS,EAAE;AAChC,YAAM,MAA+B;AAAA,QACpC,MAAM;AAAA,QACN,WAAW,QAAQ;AAAA,QACnB;AAAA,MACD;AACA,cAAQ,KAAK,YAAY,GAAG;AAAA,IAC7B;AAEA,UAAM,IAAI,QAAQ,KAAK;AACvB,WAAO;AAAA,EACR;AAEA,WAAS,QAAQ,MAAsB;AACtC,SAAK,MAAM;AAEX,SAAK,iBAAiB,WAAW,CAAC,UAAmC;AACpE,YAAM,OAAO,MAAM;AACnB,UAAI,MAAM,SAAS,YAAY;AAC9B;AAAA,MACD;AAEA,YAAM,QAAQ,QAAQ,KAAK,QAAQ,KAAK,SAAS;AACjD,YAAM,UAAU,MAAM;AACtB,YAAM,eAAe;AACrB,YAAM,QAAQ,IAAI,SAAS,EAAE,WAAW,KAAK,WAAW,KAAK,CAAC;AAG9D,YAAM,OAAO,YAAY,EAAE,GAAG,KAAK,SAAS,IAAI,QAAQ,CAAC;AAAA,IAC1D,CAAC;AAED,SAAK,iBAAiB,gBAAgB,MAAY;AAGjD,iBAAW,SAAS,MAAM,OAAO,GAAG;AACnC,mBAAW,CAAC,SAAS,OAAO,KAAK,MAAM,SAAS;AAC/C,cAAI,QAAQ,SAAS,MAAM;AAC1B,kBAAM,QAAQ,OAAO,OAAO;AAAA,UAC7B;AAAA,QACD;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF;AAEA,SAAO,EAAE,QAAQ;AAClB;AAMA,IAAI,OAAO,SAAS,eAAe,eAAe,MAAM;AACvD,QAAM,OAAO,uBAAuB;AAAA,IACnC,aAAa,CAAC,cACb,IAAI,OAAO,WAAW,EAAE,MAAM,SAAS,CAAC;AAAA,EAC1C,CAAC;AAED,OAAK,YAAY,CAAC,UAA8B;AAC/C,UAAM,OAAO,MAAM,MAAM,CAAC;AAC1B,QAAI,CAAC,MAAM;AACV;AAAA,IACD;AACA,SAAK,QAAQ,IAA2B;AAAA,EACzC;AACD;","names":[]}
1
+ {"version":3,"sources":["../../src/adapters/sqlite-wasm-shared-host.ts"],"sourcesContent":["/// <reference lib=\"webworker\" />\n/**\n * SharedWorker host: runs SQLite WASM directly inside the SharedWorker, one\n * database core per `dbName`, shared by every tab on the origin.\n *\n * A SharedWorker CANNOT spawn a nested `Worker` (the `Worker` constructor is not\n * defined in `SharedWorkerGlobalScope` in Chromium), so the host does not delegate\n * to a dedicated worker. It runs {@link createSqliteWasmCore} in its own scope.\n * Because each request is answered by a Promise from the core, responses are\n * correlated to their caller directly, with no inner-id bookkeeping.\n *\n * Bundle this file separately and pass its URL as `store.sharedWorkerUrl` alongside\n * `workerUrl`. The entry that bundles it must set `__KORA_SQLITE_WASM_URL` (via a\n * `?url` import of the sqlite wasm binary) the same way the dedicated worker entry\n * does, so the core can locate the hashed WASM asset in production builds.\n *\n * @example\n * ```typescript\n * createApp({\n * store: {\n * workerUrl: '/sqlite-wasm-worker.js',\n * sharedWorkerUrl: '/sqlite-wasm-shared-host.js',\n * },\n * })\n * ```\n */\n\nimport type { WorkerRequest, WorkerResponse } from './sqlite-wasm-channel'\nimport { type SqliteWasmCore, createSqliteWasmCore } from './sqlite-wasm-worker-core'\n\nconst SW_REQUEST = 'kora-sw-request'\nconst SW_RESPONSE = 'kora-sw-response'\n\ninterface SharedWorkerRpcRequest {\n\ttype: typeof SW_REQUEST\n\trequestId: string\n\tdbName: string\n\tworkerUrl: string\n\trequest: WorkerRequest\n}\n\ninterface SharedWorkerRpcResponse {\n\ttype: typeof SW_RESPONSE\n\trequestId: string\n\tresponse: WorkerResponse\n}\n\n/** Minimal structural view of a connected client `MessagePort`. */\nexport interface HostPort {\n\tstart(): void\n\tpostMessage(message: SharedWorkerRpcResponse): void\n\taddEventListener(\n\t\ttype: 'message' | 'messageerror',\n\t\thandler: (event: { data: unknown }) => void,\n\t): void\n}\n\nexport interface SharedWorkerHostOptions {\n\t/** Creates a database core. Injectable so the host routing can be unit-tested. */\n\tcreateCore: () => SqliteWasmCore\n}\n\nexport interface SharedWorkerHost {\n\t/** Wire a newly connected client port into the host. */\n\tconnect(port: HostPort): void\n}\n\n/**\n * Creates the SharedWorker host routing core: one SQLite core per `dbName`, shared\n * by every connected tab, with each request answered directly by the core.\n */\nexport function createSharedWorkerHost(options: SharedWorkerHostOptions): SharedWorkerHost {\n\tconst cores = new Map<string, SqliteWasmCore>()\n\n\tfunction coreFor(dbName: string): SqliteWasmCore {\n\t\tlet core = cores.get(dbName)\n\t\tif (!core) {\n\t\t\tcore = options.createCore()\n\t\t\tcores.set(dbName, core)\n\t\t}\n\t\treturn core\n\t}\n\n\tfunction connect(port: HostPort): void {\n\t\tport.start()\n\n\t\tport.addEventListener('message', (event: { data: unknown }): void => {\n\t\t\tconst data = event.data as SharedWorkerRpcRequest | undefined\n\t\t\tif (data?.type !== SW_REQUEST) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst core = coreFor(data.dbName)\n\t\t\tvoid core.handle(data.request).then(\n\t\t\t\t(response) => {\n\t\t\t\t\tport.postMessage({ type: SW_RESPONSE, requestId: data.requestId, response })\n\t\t\t\t},\n\t\t\t\t(error: unknown) => {\n\t\t\t\t\t// The core catches its own errors, so this only fires on an unexpected\n\t\t\t\t\t// throw. Relay it so the client never hangs waiting for a response.\n\t\t\t\t\tconst message = error instanceof Error ? error.message : 'SharedWorker core failed'\n\t\t\t\t\tport.postMessage({\n\t\t\t\t\t\ttype: SW_RESPONSE,\n\t\t\t\t\t\trequestId: data.requestId,\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tid: data.request.id,\n\t\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\t\tmessage,\n\t\t\t\t\t\t\tcode: 'SHARED_WORKER_CORE_ERROR',\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t)\n\t\t})\n\t}\n\n\treturn { connect }\n}\n\n// Wire the host to the SharedWorker global only when running as an actual\n// SharedWorker. The guard uses `instanceof SharedWorkerGlobalScope` so it is true\n// in a real SharedWorker and false everywhere else (Node test runtimes, the main\n// thread, a dedicated worker), which keeps `createSharedWorkerHost` unit-testable\n// in isolation. A connection is delivered as a `connect` event whose `ports[0]` is\n// the client MessagePort.\ndeclare const self: SharedWorkerGlobalScope\nif (\n\ttypeof SharedWorkerGlobalScope !== 'undefined' &&\n\ttypeof self !== 'undefined' &&\n\tself instanceof SharedWorkerGlobalScope\n) {\n\tconst host = createSharedWorkerHost({ createCore: createSqliteWasmCore })\n\n\tself.addEventListener('connect', (event: MessageEvent): void => {\n\t\tconst port = event.ports[0]\n\t\tif (!port) {\n\t\t\treturn\n\t\t}\n\t\thost.connect(port as unknown as HostPort)\n\t})\n}\n"],"mappings":";;;;;AA8BA,IAAM,aAAa;AACnB,IAAM,cAAc;AAwCb,SAAS,uBAAuB,SAAoD;AAC1F,QAAM,QAAQ,oBAAI,IAA4B;AAE9C,WAAS,QAAQ,QAAgC;AAChD,QAAI,OAAO,MAAM,IAAI,MAAM;AAC3B,QAAI,CAAC,MAAM;AACV,aAAO,QAAQ,WAAW;AAC1B,YAAM,IAAI,QAAQ,IAAI;AAAA,IACvB;AACA,WAAO;AAAA,EACR;AAEA,WAAS,QAAQ,MAAsB;AACtC,SAAK,MAAM;AAEX,SAAK,iBAAiB,WAAW,CAAC,UAAmC;AACpE,YAAM,OAAO,MAAM;AACnB,UAAI,MAAM,SAAS,YAAY;AAC9B;AAAA,MACD;AAEA,YAAM,OAAO,QAAQ,KAAK,MAAM;AAChC,WAAK,KAAK,OAAO,KAAK,OAAO,EAAE;AAAA,QAC9B,CAAC,aAAa;AACb,eAAK,YAAY,EAAE,MAAM,aAAa,WAAW,KAAK,WAAW,SAAS,CAAC;AAAA,QAC5E;AAAA,QACA,CAAC,UAAmB;AAGnB,gBAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,eAAK,YAAY;AAAA,YAChB,MAAM;AAAA,YACN,WAAW,KAAK;AAAA,YAChB,UAAU;AAAA,cACT,IAAI,KAAK,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN;AAAA,cACA,MAAM;AAAA,YACP;AAAA,UACD,CAAC;AAAA,QACF;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF;AAEA,SAAO,EAAE,QAAQ;AAClB;AASA,IACC,OAAO,4BAA4B,eACnC,OAAO,SAAS,eAChB,gBAAgB,yBACf;AACD,QAAM,OAAO,uBAAuB,EAAE,YAAY,qBAAqB,CAAC;AAExE,OAAK,iBAAiB,WAAW,CAAC,UAA8B;AAC/D,UAAM,OAAO,MAAM,MAAM,CAAC;AAC1B,QAAI,CAAC,MAAM;AACV;AAAA,IACD;AACA,SAAK,QAAQ,IAA2B;AAAA,EACzC,CAAC;AACF;","names":[]}
@@ -22,48 +22,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
22
  mod
23
23
  ));
24
24
 
25
- // src/adapters/sqlite-wasm-worker.ts
26
- var db = null;
27
- var sqlite3Api = null;
28
- function sendResponse(response) {
29
- self.postMessage(response);
30
- }
31
- function handleExecute(id, sql, params) {
32
- if (!db) {
33
- sendResponse({ id, type: "error", message: "Database is not open", code: "DB_NOT_OPEN" });
34
- return;
35
- }
36
- try {
37
- db.exec({ sql, bind: params });
38
- sendResponse({ id, type: "success" });
39
- } catch (error) {
40
- sendResponse({ id, type: "error", message: error.message, code: "EXEC_ERROR" });
41
- }
42
- }
43
- function handleQuery(id, sql, params) {
44
- if (!db) {
45
- sendResponse({ id, type: "error", message: "Database is not open", code: "DB_NOT_OPEN" });
46
- return;
47
- }
48
- try {
49
- const rows = [];
50
- db.exec({
51
- sql,
52
- bind: params,
53
- rowMode: "object",
54
- callback: (row) => {
55
- rows.push({ ...row });
56
- }
57
- });
58
- sendResponse({ id, type: "success", data: rows });
59
- } catch (error) {
60
- sendResponse({ id, type: "error", message: error.message, code: "QUERY_ERROR" });
61
- }
62
- }
63
- function opfsDatabaseFilename(dbName) {
64
- const base = dbName.replace(/[^a-zA-Z0-9._-]/g, "_");
65
- return base.endsWith(".db") ? base : `${base}.db`;
66
- }
25
+ // src/adapters/sqlite-wasm-worker-core.ts
26
+ var OPFS_POOL_NAME = "kora-opfs";
67
27
  var OPFS_INIT_TIMEOUT_MS = 1e4;
68
28
  async function withTimeout(promise, timeoutMs, label) {
69
29
  let timer;
@@ -81,205 +41,243 @@ async function withTimeout(promise, timeoutMs, label) {
81
41
  if (timer !== void 0) clearTimeout(timer);
82
42
  }
83
43
  }
84
- async function handleOpen(id, ddlStatements, dbName) {
44
+ function opfsDatabaseFilename(dbName) {
45
+ const base = dbName.replace(/[^a-zA-Z0-9._-]/g, "_");
46
+ return base.endsWith(".db") ? base : `${base}.db`;
47
+ }
48
+ function classifyOpfsFailure(error) {
49
+ const message = error instanceof Error ? error.message : String(error);
50
+ if (/timed out|timeout/i.test(message)) {
51
+ return "timeout";
52
+ }
53
+ if (/lock|already|in use|in-use|NoModificationAllowed|acquire|SyncAccessHandle|being created/i.test(
54
+ message
55
+ )) {
56
+ return "lock-conflict";
57
+ }
58
+ return "unsupported";
59
+ }
60
+ var sqlite3Promise = null;
61
+ var opfsPoolPromise = null;
62
+ var opfsFallbackReason;
63
+ async function loadSqlite3() {
64
+ const sqlite3InitModule = (await import("@sqlite.org/sqlite-wasm")).default;
65
+ const wasmUrl = globalThis.__KORA_SQLITE_WASM_URL;
66
+ const initOptions = wasmUrl ? {
67
+ locateFile: (file) => file.endsWith(".wasm") ? wasmUrl : file
68
+ } : void 0;
69
+ const initFn = sqlite3InitModule;
70
+ return await withTimeout(initFn(initOptions), 6e4, "SQLite3 module init");
71
+ }
72
+ function getSqlite3() {
73
+ if (!sqlite3Promise) {
74
+ sqlite3Promise = loadSqlite3();
75
+ }
76
+ return sqlite3Promise;
77
+ }
78
+ async function installOpfsPool(sqlite3) {
79
+ if (!sqlite3.installOpfsSAHPoolVfs) {
80
+ opfsFallbackReason = "unsupported";
81
+ return null;
82
+ }
85
83
  try {
86
- const sqlite3InitModule = (await import("@sqlite.org/sqlite-wasm")).default;
87
- const wasmUrl = globalThis.__KORA_SQLITE_WASM_URL;
88
- const initOptions = wasmUrl ? {
89
- locateFile: (file) => {
90
- if (file.endsWith(".wasm")) return wasmUrl;
91
- return file;
92
- }
93
- } : void 0;
94
- const initFn = sqlite3InitModule;
95
- const sqlite3 = await withTimeout(
96
- initFn(initOptions),
97
- 6e4,
98
- "SQLite3 module init"
84
+ return await withTimeout(
85
+ sqlite3.installOpfsSAHPoolVfs({ name: OPFS_POOL_NAME }),
86
+ OPFS_INIT_TIMEOUT_MS,
87
+ "OPFS VFS install"
99
88
  );
100
- sqlite3Api = sqlite3;
101
- let useOpfs = false;
102
- let fallbackReason;
103
- if (sqlite3.installOpfsSAHPoolVfs) {
104
- try {
105
- const pool = await withTimeout(
106
- sqlite3.installOpfsSAHPoolVfs({ name: "kora-opfs" }),
107
- OPFS_INIT_TIMEOUT_MS,
108
- "OPFS VFS install"
109
- );
89
+ } catch (error) {
90
+ opfsFallbackReason = classifyOpfsFailure(error);
91
+ return null;
92
+ }
93
+ }
94
+ function getOpfsPool(sqlite3) {
95
+ if (!opfsPoolPromise) {
96
+ opfsPoolPromise = installOpfsPool(sqlite3);
97
+ }
98
+ return opfsPoolPromise;
99
+ }
100
+ function createSqliteWasmCore() {
101
+ let db = null;
102
+ let sqlite3Api = null;
103
+ let persistent = false;
104
+ async function open(id, ddlStatements, dbName) {
105
+ try {
106
+ if (db) {
107
+ applyDdl(db, ddlStatements);
108
+ return { id, type: "success", data: buildOpenData() };
109
+ }
110
+ const sqlite3 = await getSqlite3();
111
+ sqlite3Api = sqlite3;
112
+ const pool = await getOpfsPool(sqlite3);
113
+ if (pool) {
110
114
  db = new pool.OpfsSAHPoolDb(opfsDatabaseFilename(dbName ?? "kora-db"));
111
- useOpfs = true;
112
- } catch (error) {
113
- fallbackReason = classifyOpfsFailure(error);
114
- console.warn(
115
- `[kora] OPFS unavailable (${fallbackReason}), falling back to in-memory SQLite`
116
- );
115
+ persistent = true;
116
+ } else {
117
+ db = new sqlite3.oo1.DB({ filename: ":memory:" });
118
+ persistent = false;
117
119
  }
118
- } else {
119
- fallbackReason = "unsupported";
120
- }
121
- if (!useOpfs) {
122
- db = new sqlite3.oo1.DB({ filename: ":memory:" });
120
+ db.exec({ sql: "PRAGMA journal_mode = WAL" });
121
+ db.exec({ sql: "PRAGMA foreign_keys = ON" });
122
+ applyDdl(db, ddlStatements);
123
+ return { id, type: "success", data: buildOpenData() };
124
+ } catch (error) {
125
+ return { id, type: "error", message: error.message, code: "INIT_ERROR" };
123
126
  }
124
- db?.exec({ sql: "PRAGMA journal_mode = WAL" });
125
- db?.exec({ sql: "PRAGMA foreign_keys = ON" });
127
+ }
128
+ function buildOpenData() {
129
+ return {
130
+ persistent,
131
+ ...persistent ? {} : { fallbackReason: opfsFallbackReason ?? "unsupported" }
132
+ };
133
+ }
134
+ function applyDdl(target, ddlStatements) {
126
135
  for (const sql of ddlStatements) {
127
136
  if (sql.startsWith("--kora:safe-alter")) {
128
137
  try {
129
- db?.exec({ sql: sql.replace("--kora:safe-alter\n", "") });
130
- } catch (e) {
131
- const msg = e.message || "";
138
+ target.exec({ sql: sql.replace("--kora:safe-alter\n", "") });
139
+ } catch (error) {
140
+ const msg = error.message || "";
132
141
  if (!msg.includes("duplicate column name")) {
133
- throw e;
142
+ throw error;
134
143
  }
135
144
  }
136
145
  } else {
137
- db?.exec({ sql });
146
+ target.exec({ sql });
138
147
  }
139
148
  }
140
- sendResponse({
141
- id,
142
- type: "success",
143
- data: { persistent: useOpfs, ...fallbackReason ? { fallbackReason } : {} }
144
- });
145
- } catch (error) {
146
- sendResponse({
147
- id,
148
- type: "error",
149
- message: error.message,
150
- code: "INIT_ERROR"
151
- });
152
- }
153
- }
154
- function classifyOpfsFailure(error) {
155
- const message = error instanceof Error ? error.message : String(error);
156
- if (/timed out|timeout/i.test(message)) {
157
- return "timeout";
158
149
  }
159
- if (/lock|already|in use|in-use|NoModificationAllowed|acquire|SyncAccessHandle|being created/i.test(
160
- message
161
- )) {
162
- return "lock-conflict";
150
+ function execute(id, sql, params) {
151
+ if (!db) {
152
+ return { id, type: "error", message: "Database is not open", code: "DB_NOT_OPEN" };
153
+ }
154
+ try {
155
+ db.exec({ sql, bind: params });
156
+ return { id, type: "success" };
157
+ } catch (error) {
158
+ return { id, type: "error", message: error.message, code: "EXEC_ERROR" };
159
+ }
163
160
  }
164
- return "unsupported";
165
- }
166
- function handleClose(id) {
167
- if (db) {
168
- db.close();
169
- db = null;
161
+ function query(id, sql, params) {
162
+ if (!db) {
163
+ return { id, type: "error", message: "Database is not open", code: "DB_NOT_OPEN" };
164
+ }
165
+ try {
166
+ const rows = [];
167
+ db.exec({
168
+ sql,
169
+ bind: params,
170
+ rowMode: "object",
171
+ callback: (row) => {
172
+ rows.push({ ...row });
173
+ }
174
+ });
175
+ return { id, type: "success", data: rows };
176
+ } catch (error) {
177
+ return { id, type: "error", message: error.message, code: "QUERY_ERROR" };
178
+ }
170
179
  }
171
- sendResponse({ id, type: "success" });
172
- }
173
- function handleImport(id, data) {
174
- if (!db) {
175
- sendResponse({ id, type: "error", message: "Database is not open", code: "DB_NOT_OPEN" });
176
- return;
180
+ function close(id) {
181
+ if (db) {
182
+ db.close();
183
+ db = null;
184
+ }
185
+ return { id, type: "success" };
177
186
  }
178
- const dbWithDeserialize = db;
179
- if (typeof dbWithDeserialize.deserialize === "function") {
187
+ function migrate(id, statements) {
188
+ if (!db) {
189
+ return { id, type: "error", message: "Database is not open", code: "DB_NOT_OPEN" };
190
+ }
180
191
  try {
181
- dbWithDeserialize.deserialize(data);
182
- sendResponse({ id, type: "success" });
183
- return;
192
+ for (const sql of statements) {
193
+ db.exec({ sql });
194
+ }
195
+ return { id, type: "success" };
184
196
  } catch (error) {
185
- sendResponse({ id, type: "error", message: error.message, code: "IMPORT_ERROR" });
186
- return;
197
+ return { id, type: "error", message: error.message, code: "MIGRATE_ERROR" };
187
198
  }
188
199
  }
189
- const sqlite3 = sqlite3Api;
190
- if (!sqlite3 || typeof sqlite3.capi?.sqlite3_deserialize === "undefined") {
191
- sendResponse({
200
+ function importData(id, data) {
201
+ if (!db) {
202
+ return { id, type: "error", message: "Database is not open", code: "DB_NOT_OPEN" };
203
+ }
204
+ const dbWithDeserialize = db;
205
+ if (typeof dbWithDeserialize.deserialize === "function") {
206
+ try {
207
+ dbWithDeserialize.deserialize(data);
208
+ return { id, type: "success" };
209
+ } catch (error) {
210
+ return { id, type: "error", message: error.message, code: "IMPORT_ERROR" };
211
+ }
212
+ }
213
+ if (!sqlite3Api || typeof sqlite3Api.capi?.sqlite3_deserialize === "undefined") {
214
+ return {
215
+ id,
216
+ type: "error",
217
+ message: "Import not supported in this SQLite WASM runtime",
218
+ code: "IMPORT_NOT_SUPPORTED"
219
+ };
220
+ }
221
+ return {
192
222
  id,
193
223
  type: "error",
194
- message: "Import not supported in this SQLite WASM runtime",
224
+ message: "Import requires runtime-specific deserialize wiring and is unavailable in this worker build",
195
225
  code: "IMPORT_NOT_SUPPORTED"
196
- });
197
- return;
226
+ };
198
227
  }
199
- sendResponse({
200
- id,
201
- type: "error",
202
- message: "Import requires runtime-specific deserialize wiring and is unavailable in this worker build",
203
- code: "IMPORT_NOT_SUPPORTED"
204
- });
205
- }
206
- function handleMessage(request) {
207
- try {
208
- switch (request.type) {
209
- case "open":
210
- handleOpen(request.id, request.ddlStatements, request.dbName);
211
- return;
212
- case "close":
213
- handleClose(request.id);
214
- return;
215
- case "execute":
216
- handleExecute(request.id, request.sql, request.params);
217
- return;
218
- case "query":
219
- handleQuery(request.id, request.sql, request.params);
220
- return;
221
- case "begin":
222
- handleExecute(request.id, "BEGIN");
223
- return;
224
- case "commit":
225
- handleExecute(request.id, "COMMIT");
226
- return;
227
- case "rollback":
228
- handleExecute(request.id, "ROLLBACK");
229
- return;
230
- case "migrate":
231
- if (!db) {
232
- sendResponse({
228
+ async function handle(request) {
229
+ try {
230
+ switch (request.type) {
231
+ case "open":
232
+ return await open(request.id, request.ddlStatements, request.dbName);
233
+ case "close":
234
+ return close(request.id);
235
+ case "execute":
236
+ return execute(request.id, request.sql, request.params);
237
+ case "query":
238
+ return query(request.id, request.sql, request.params);
239
+ case "begin":
240
+ return execute(request.id, "BEGIN");
241
+ case "commit":
242
+ return execute(request.id, "COMMIT");
243
+ case "rollback":
244
+ return execute(request.id, "ROLLBACK");
245
+ case "migrate":
246
+ return migrate(request.id, request.statements);
247
+ case "import":
248
+ return importData(request.id, request.data);
249
+ case "export":
250
+ return {
233
251
  id: request.id,
234
252
  type: "error",
235
- message: "Database is not open",
236
- code: "DB_NOT_OPEN"
237
- });
238
- return;
239
- }
240
- try {
241
- for (const sql of request.statements) {
242
- db.exec({ sql });
243
- }
244
- sendResponse({ id: request.id, type: "success" });
245
- } catch (error) {
246
- sendResponse({
253
+ message: "Export not yet supported in browser worker",
254
+ code: "EXPORT_NOT_SUPPORTED"
255
+ };
256
+ default:
257
+ return {
247
258
  id: request.id,
248
259
  type: "error",
249
- message: error.message,
250
- code: "MIGRATE_ERROR"
251
- });
252
- }
253
- return;
254
- case "export":
255
- sendResponse({
256
- id: request.id,
257
- type: "error",
258
- message: "Export not yet supported in browser worker",
259
- code: "EXPORT_NOT_SUPPORTED"
260
- });
261
- return;
262
- case "import":
263
- handleImport(request.id, request.data);
264
- return;
265
- default:
266
- sendResponse({
267
- id: request.id,
268
- type: "error",
269
- message: "Unknown request type",
270
- code: "UNKNOWN_REQUEST"
271
- });
260
+ message: "Unknown request type",
261
+ code: "UNKNOWN_REQUEST"
262
+ };
263
+ }
264
+ } catch (error) {
265
+ return {
266
+ id: request.id,
267
+ type: "error",
268
+ message: error.message,
269
+ code: "WORKER_ERROR"
270
+ };
272
271
  }
273
- } catch (error) {
274
- sendResponse({
275
- id: request.id,
276
- type: "error",
277
- message: error.message,
278
- code: "WORKER_ERROR"
279
- });
280
272
  }
273
+ return { handle };
281
274
  }
275
+
276
+ // src/adapters/sqlite-wasm-worker.ts
277
+ var core = createSqliteWasmCore();
282
278
  self.onmessage = (event) => {
283
- handleMessage(event.data);
279
+ void core.handle(event.data).then((response) => {
280
+ self.postMessage(response);
281
+ });
284
282
  };
285
283
  //# sourceMappingURL=sqlite-wasm-worker.cjs.map