@statewalker/cellb 0.8.9 → 0.9.2

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 (40) hide show
  1. package/README.md +10 -6
  2. package/dist/adapters/node-sqlite-module.d.ts +6 -0
  3. package/dist/adapters/node-sqlite-module.js +12 -0
  4. package/dist/adapters/node-sqlite-module.js.map +1 -1
  5. package/dist/adapters/node-sqlite.js +3 -3
  6. package/dist/adapters/node-sqlite.js.map +1 -1
  7. package/dist/adapters/wasm-sqlite.d.ts +2 -0
  8. package/dist/adapters/wasm-sqlite.js +15 -0
  9. package/dist/adapters/wasm-sqlite.js.map +1 -1
  10. package/dist/bindings/cron.js +9 -2
  11. package/dist/bindings/cron.js.map +1 -1
  12. package/dist/bindings/module-registry.d.ts +19 -9
  13. package/dist/bindings/module-registry.js +42 -30
  14. package/dist/bindings/module-registry.js.map +1 -1
  15. package/dist/bucket/sqlite-object-store.js +2 -2
  16. package/dist/bucket/sqlite-object-store.js.map +1 -1
  17. package/dist/core/alarms.js +12 -2
  18. package/dist/core/alarms.js.map +1 -1
  19. package/dist/isolate/function-imports.d.ts +10 -0
  20. package/dist/isolate/function-imports.js +93 -0
  21. package/dist/isolate/function-imports.js.map +1 -0
  22. package/dist/isolate/isolate-worker.js +5 -1
  23. package/dist/isolate/isolate-worker.js.map +1 -1
  24. package/dist/isolate/protocol.js +17 -3
  25. package/dist/isolate/protocol.js.map +1 -1
  26. package/dist/project/browser-host.d.ts +2 -0
  27. package/dist/project/browser-host.js +2 -0
  28. package/dist/project/browser-host.js.map +1 -1
  29. package/dist/project/browser-load.js +1 -0
  30. package/dist/project/browser-load.js.map +1 -1
  31. package/dist/project/browser-modules.d.ts +7 -1
  32. package/dist/project/browser-modules.js +5 -1
  33. package/dist/project/browser-modules.js.map +1 -1
  34. package/dist/project/browser-tabs.d.ts +1 -1
  35. package/dist/project/browser-tabs.js.map +1 -1
  36. package/dist/project/built-project.d.ts +7 -0
  37. package/dist/project/built-project.js.map +1 -1
  38. package/dist/project/node-project.js +9 -6
  39. package/dist/project/node-project.js.map +1 -1
  40. package/package.json +2 -2
package/README.md CHANGED
@@ -404,21 +404,25 @@ Run from `packages/cellb` after `pnpm install` at the repository root.
404
404
 
405
405
  Releases are made by CI, the same pipeline as the other statewalker monorepos
406
406
  (`.github/workflows/ci.yml`). A change to the package carries a changeset (`pnpm changeset` at
407
- the repository root); without one, the release planner (statewalker/.github's
407
+ the repository root); without one, the release planner (statewalker/statewalker-ci's
408
408
  `scripts/release-changesets.mjs`) writes a patch for a package whose published contents changed.
409
409
  On every push to `main`, after the `cellb` checks pass:
410
410
 
411
411
  1. `version` applies the pending changesets in a "chore: version packages" pull request
412
- (versions, `CHANGELOG.md`). It never publishes.
412
+ (versions, `CHANGELOG.md`). It never publishes. It opens the pull request with the
413
+ `statewalker-release` GitHub App's token (organization variable `RELEASE_APP_CLIENT_ID`,
414
+ secret `RELEASE_APP_KEY`), not `GITHUB_TOKEN`, so the checks run on it: GitHub does not run
415
+ CI on what `GITHUB_TOKEN` pushes until a maintainer approves the run.
413
416
  2. Once that pull request is merged, `pack` packs every public package whose version npm lacks
414
417
  (`pnpm pack`: `prepack` builds `dist/`, and `catalog:` ranges are resolved).
415
- 3. `publish` waits for a maintainer's approval (the `npm` GitHub environment), then publishes
416
- the tarballs with npm trusted publishing (OIDC, with provenance) and creates a GitHub release
417
- per package. No npm token is stored in GitHub.
418
+ 3. `publish` runs in the `npm` GitHub environment (only `main`, no approval) and publishes the
419
+ tarballs at once with npm trusted publishing (OIDC, with provenance), creating a GitHub
420
+ release per package. No npm token is stored in GitHub.
418
421
 
419
422
  One-time setup on npm: `@statewalker/cellb` → Settings → Trusted publishing → GitHub Actions,
420
423
  repository `statewalker/cellb.dev`, workflow `ci.yml`, environment `npm`. On GitHub: an
421
- environment named `npm` with required reviewers. A new package's first version is published by
424
+ environment named `npm` whose deployment branch policy admits only `main`, with no required
425
+ reviewers. A new package's first version is published by
422
426
  hand (`pnpm publish` in its directory, with the maintainer's 2FA), since a trusted publisher can
423
427
  only be added to a package that exists.
424
428
 
@@ -7,3 +7,9 @@
7
7
  * builtin and then fail to resolve "sqlite".
8
8
  */
9
9
  export declare function requireNodeSqlite(): typeof import("node:sqlite");
10
+ /**
11
+ * Bytes as node:sqlite binds them. Node 22 binds a view whose buffer has no backing store (the
12
+ * buffer of `new ArrayBuffer(0)` or of a `Uint8Array` made from one) as NULL, not as an empty
13
+ * BLOB: zero-length bytes are bound as EMPTY_BLOB instead. An ArrayBuffer becomes a view.
14
+ */
15
+ export declare function nodeSqliteBytes(v: ArrayBuffer | ArrayBufferView): Uint8Array;
@@ -25,4 +25,16 @@ export function requireNodeSqlite() {
25
25
  process.emitWarning = emitWarning;
26
26
  }
27
27
  }
28
+ /** A zero-length view over a real buffer: node:sqlite binds it as an empty BLOB. */
29
+ const EMPTY_BLOB = new Uint8Array(1).subarray(0, 0);
30
+ /**
31
+ * Bytes as node:sqlite binds them. Node 22 binds a view whose buffer has no backing store (the
32
+ * buffer of `new ArrayBuffer(0)` or of a `Uint8Array` made from one) as NULL, not as an empty
33
+ * BLOB: zero-length bytes are bound as EMPTY_BLOB instead. An ArrayBuffer becomes a view.
34
+ */
35
+ export function nodeSqliteBytes(v) {
36
+ if (v.byteLength === 0)
37
+ return EMPTY_BLOB;
38
+ return v instanceof ArrayBuffer ? new Uint8Array(v) : v;
39
+ }
28
40
  //# sourceMappingURL=node-sqlite-module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"node-sqlite-module.js","sourceRoot":"","sources":["../../src/adapters/node-sqlite-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IACxC,OAAO,CAAC,WAAW,GAAG,UAAyB,OAAuB,EAAE,GAAG,IAAe;QACxF,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,CAAC,CAAuB,EAAE,IAAI,CAAC;QAC1F,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC;QACtE,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI,CAAC,CAAC;QAC1E,IAAI,IAAI,KAAK,qBAAqB,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAAE,OAAO;QAC9E,OAAQ,WAAyC,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACpF,CAA+B,CAAC;IAChC,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,aAAa,CAAiC,CAAC;IAChE,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC;IACpC,CAAC;AACH,CAAC","sourcesContent":["import { createRequire } from \"node:module\";\n\nconst require = createRequire(import.meta.url);\n\n/**\n * `node:sqlite`, loaded without Node's \"SQLite is an experimental feature\" warning. cellb is\n * the one choosing the module, not its user, so the warning would only be noise on every start\n * (`loadProject`, `nodeSqliteOpener`). Only that warning is held back; any other passes.\n *\n * Loaded with `require`: bundlers (vite/vitest) strip the \"node:\" prefix of the experimental\n * builtin and then fail to resolve \"sqlite\".\n */\nexport function requireNodeSqlite(): typeof import(\"node:sqlite\") {\n const emitWarning = process.emitWarning;\n process.emitWarning = function (this: unknown, warning: string | Error, ...rest: unknown[]) {\n const type = typeof rest[0] === \"string\" ? rest[0] : (rest[0] as { type?: string })?.type;\n const text = typeof warning === \"string\" ? warning : warning?.message;\n const name = typeof warning === \"string\" ? type : (warning?.name ?? type);\n if (name === \"ExperimentalWarning\" && /\\bSQLite\\b/.test(String(text))) return;\n return (emitWarning as (...a: unknown[]) => void).call(process, warning, ...rest);\n } as typeof process.emitWarning;\n try {\n return require(\"node:sqlite\") as typeof import(\"node:sqlite\");\n } finally {\n process.emitWarning = emitWarning;\n }\n}\n"]}
1
+ {"version":3,"file":"node-sqlite-module.js","sourceRoot":"","sources":["../../src/adapters/node-sqlite-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IACxC,OAAO,CAAC,WAAW,GAAG,UAAyB,OAAuB,EAAE,GAAG,IAAe;QACxF,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,CAAC,CAAuB,EAAE,IAAI,CAAC;QAC1F,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC;QACtE,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI,CAAC,CAAC;QAC1E,IAAI,IAAI,KAAK,qBAAqB,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAAE,OAAO;QAC9E,OAAQ,WAAyC,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACpF,CAA+B,CAAC;IAChC,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,aAAa,CAAiC,CAAC;IAChE,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC;IACpC,CAAC;AACH,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAEpD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,CAAgC;IAC9D,IAAI,CAAC,CAAC,UAAU,KAAK,CAAC;QAAE,OAAO,UAAU,CAAC;IAC1C,OAAO,CAAC,YAAY,WAAW,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAgB,CAAC;AAC1E,CAAC","sourcesContent":["import { createRequire } from \"node:module\";\n\nconst require = createRequire(import.meta.url);\n\n/**\n * `node:sqlite`, loaded without Node's \"SQLite is an experimental feature\" warning. cellb is\n * the one choosing the module, not its user, so the warning would only be noise on every start\n * (`loadProject`, `nodeSqliteOpener`). Only that warning is held back; any other passes.\n *\n * Loaded with `require`: bundlers (vite/vitest) strip the \"node:\" prefix of the experimental\n * builtin and then fail to resolve \"sqlite\".\n */\nexport function requireNodeSqlite(): typeof import(\"node:sqlite\") {\n const emitWarning = process.emitWarning;\n process.emitWarning = function (this: unknown, warning: string | Error, ...rest: unknown[]) {\n const type = typeof rest[0] === \"string\" ? rest[0] : (rest[0] as { type?: string })?.type;\n const text = typeof warning === \"string\" ? warning : warning?.message;\n const name = typeof warning === \"string\" ? type : (warning?.name ?? type);\n if (name === \"ExperimentalWarning\" && /\\bSQLite\\b/.test(String(text))) return;\n return (emitWarning as (...a: unknown[]) => void).call(process, warning, ...rest);\n } as typeof process.emitWarning;\n try {\n return require(\"node:sqlite\") as typeof import(\"node:sqlite\");\n } finally {\n process.emitWarning = emitWarning;\n }\n}\n\n/** A zero-length view over a real buffer: node:sqlite binds it as an empty BLOB. */\nconst EMPTY_BLOB = new Uint8Array(1).subarray(0, 0);\n\n/**\n * Bytes as node:sqlite binds them. Node 22 binds a view whose buffer has no backing store (the\n * buffer of `new ArrayBuffer(0)` or of a `Uint8Array` made from one) as NULL, not as an empty\n * BLOB: zero-length bytes are bound as EMPTY_BLOB instead. An ArrayBuffer becomes a view.\n */\nexport function nodeSqliteBytes(v: ArrayBuffer | ArrayBufferView): Uint8Array {\n if (v.byteLength === 0) return EMPTY_BLOB;\n return v instanceof ArrayBuffer ? new Uint8Array(v) : (v as Uint8Array);\n}\n"]}
@@ -3,7 +3,7 @@ import { createRequire } from "node:module";
3
3
  import { tmpdir } from "node:os";
4
4
  import { dirname, join } from "node:path";
5
5
  import { splitSqlStatements } from "../core/sql-split.js";
6
- import { requireNodeSqlite } from "./node-sqlite-module.js";
6
+ import { nodeSqliteBytes, requireNodeSqlite } from "./node-sqlite-module.js";
7
7
  const { DatabaseSync } = requireNodeSqlite();
8
8
  const requireCjs = createRequire(import.meta.url);
9
9
  const KNOWN_EXTENSIONS = {
@@ -297,8 +297,8 @@ export class NodeSqliteDriver {
297
297
  }
298
298
  }
299
299
  function toSqlite(v) {
300
- if (v instanceof ArrayBuffer)
301
- return new Uint8Array(v);
300
+ if (v instanceof ArrayBuffer || ArrayBuffer.isView(v))
301
+ return nodeSqliteBytes(v);
302
302
  if (typeof v === "boolean")
303
303
  return v ? 1 : 0;
304
304
  return v === undefined ? null : v;
@@ -1 +1 @@
1
- {"version":3,"file":"node-sqlite.js","sourceRoot":"","sources":["../../src/adapters/node-sqlite.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n closeSync,\n existsSync,\n fstatSync,\n mkdtempSync,\n openSync,\n readFileSync,\n readSync,\n rmdirSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { DatabaseSync as DatabaseSyncT } from \"node:sqlite\";\n\nimport { splitSqlStatements } from \"../core/sql-split.js\";\nimport type { OpenCellSql, SqlResult, SyncSqlDriver } from \"../ports.js\";\nimport { requireNodeSqlite } from \"./node-sqlite-module.js\";\n\nconst { DatabaseSync } = requireNodeSqlite();\n\nconst requireCjs = createRequire(import.meta.url);\nconst KNOWN_EXTENSIONS: Record<string, () => string> = {\n sqlite_vec: () => (requireCjs(\"sqlite-vec\") as { getLoadablePath(): string }).getLoadablePath(),\n};\n\n/** Server-side SyncSqlDriver over node:sqlite (Node >= 22.13). */\nexport class NodeSqliteDriver implements SyncSqlDriver {\n #db: DatabaseSyncT;\n #path: string;\n readonly #exclusive: boolean;\n readonly #pageCapture: boolean;\n /** A file of its own that close() removes (a cell \"in memory\" that needs a WAL). */\n readonly #temporary: boolean;\n constructor(\n path = \":memory:\",\n opts: { exclusive?: boolean; pageCapture?: boolean; temporary?: boolean } = {},\n ) {\n this.#path = path;\n this.#temporary = !!opts.temporary && path !== \":memory:\";\n this.#exclusive = !!opts.exclusive;\n this.#pageCapture = !!opts.pageCapture && path !== \":memory:\";\n this.#db = this.#connect();\n this.#walSetup();\n }\n\n /** Extensions loaded so far, by name: a new connection (restore()) loads them again. */\n #extensions: string[] = [];\n /** The directory restore() made for an in-memory database's file. */\n #restoredDir: string | undefined;\n\n /** A connection to `#path`, set up as every connection of this driver is. */\n #connect(): DatabaseSyncT {\n // As celld and workerd: a double-quoted name that is no column is a string literal.\n const db = new DatabaseSync(this.#path, {\n allowExtension: true,\n enableDoubleQuotedStringLiterals: true,\n });\n db.enableLoadExtension(false); // only loadExtension() below may load, by name\n // EXCLUSIVE locking: the first write takes an OS lock on the file that is\n // kept until close (or process death) — a second process can neither read\n // nor write the cell. Storage-level fencing on one host, no lease needed.\n if (this.#exclusive) db.exec(\"PRAGMA locking_mode = EXCLUSIVE; PRAGMA busy_timeout = 0;\");\n try {\n for (const name of this.#extensions) this.#load(db, name);\n } catch (e) {\n db.close(); // not left open behind the error\n throw e;\n }\n return db;\n }\n\n // ---- page capture through the WAL (what the WASM driver does with its xWrite hook) ----\n // In WAL mode every commit appends its changed pages to `<db>-wal` as frames (24-byte frame\n // header + page; a commit frame carries the database size in pages). Reading the frames\n // appended since the last read gives exactly the committed transaction's pages, O(changed),\n // instead of reading the whole file. Automatic checkpoints are off; take() checkpoints\n // (TRUNCATE) itself once the WAL grows, and restarts from its start.\n #walOffset = 0;\n /** Whether anyone reads the captured pages; until then exec() keeps the WAL bounded itself. */\n #taken = false;\n #writes = 0;\n #walSetup(): void {\n if (!this.#pageCapture) return;\n this.#db.exec(\"PRAGMA journal_mode = WAL; PRAGMA wal_autocheckpoint = 0;\");\n // A temporary file is only the WAL's carrier (the bucket keeps the cell): no fsync per commit.\n if (this.#temporary) this.#db.exec(\"PRAGMA synchronous = OFF\");\n this.#db.exec(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n this.#walOffset = 0;\n }\n /** The pages of the transactions committed since the previous call (WAL frames). */\n takeDirtyPages():\n | { pageSize: number; pageCount: number; pages: Map<number, Uint8Array> }\n | undefined {\n if (!this.#pageCapture) return undefined;\n this.#taken = true;\n const walPath = `${this.#path}-wal`;\n let fd: number;\n try {\n fd = openSync(walPath, \"r\");\n } catch {\n return undefined;\n }\n try {\n const size = fstatSync(fd).size;\n if (size < 32) return undefined;\n const header = Buffer.alloc(32);\n readSync(fd, header, 0, 32, 0);\n const pageSize = header.readUInt32BE(8) === 1 ? 65536 : header.readUInt32BE(8);\n const [salt1, salt2] = [header.readUInt32BE(16), header.readUInt32BE(20)];\n const frameSize = 24 + pageSize;\n let offset = Math.max(32, this.#walOffset);\n const pending = new Map<number, Uint8Array>();\n const pages = new Map<number, Uint8Array>();\n let pageCount = 0;\n let committedTo = offset;\n const frame = Buffer.alloc(frameSize);\n while (offset + frameSize <= size) {\n readSync(fd, frame, 0, frameSize, offset);\n if (frame.readUInt32BE(8) !== salt1 || frame.readUInt32BE(12) !== salt2) break; // stale frames\n pending.set(frame.readUInt32BE(0), new Uint8Array(frame.subarray(24)));\n offset += frameSize;\n const commit = frame.readUInt32BE(4);\n if (commit) {\n for (const [p, d] of pending) pages.set(p, d);\n pending.clear();\n pageCount = commit;\n committedTo = offset;\n }\n }\n this.#walOffset = committedTo;\n if (!pageCount)\n return {\n pageSize,\n pageCount: Number(this.exec(\"PRAGMA page_count\", []).rows[0][0]),\n pages,\n };\n for (const p of [...pages.keys()]) if (p > pageCount) pages.delete(p);\n // keep the WAL bounded: fold it into the database and start over\n if (committedTo > 4 * 1024 * 1024) {\n this.#db.exec(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n this.#walOffset = 0;\n }\n return { pageSize, pageCount, pages };\n } finally {\n closeSync(fd);\n }\n }\n exec(sql: string, params: unknown[]): SqlResult {\n const statements = params.length === 0 ? splitSqlStatements(sql) : [sql];\n // Several statements: the result of the last one, with the rows written by all of them.\n let last: SqlResult = { columnNames: [], rows: [], rowsWritten: 0 };\n let written = 0;\n for (const text of statements) {\n last = this.#one(text, params);\n written += last.rowsWritten;\n }\n if (this.#pageCapture && !this.#taken && ++this.#writes % 64 === 0) this.#boundWal();\n return { ...last, rowsWritten: written };\n }\n #one(sql: string, params: unknown[]): SqlResult {\n const stmt = this.#db.prepare(sql);\n const columnNames = stmt.columns().map((c) => c.name);\n const args = params.map(toSqlite) as any[];\n if (columnNames.length === 0) {\n const r = stmt.run(...args);\n return { columnNames, rows: [], rowsWritten: Number(r.changes) };\n }\n stmt.setReturnArrays(true);\n const rows = (stmt.all(...args) as unknown as unknown[][]).map((row) => row.map(fromSqlite));\n return { columnNames, rows, rowsWritten: 0 };\n }\n /**\n * A database whose pages nobody takes (the runtime's own tables, a storage that logs no pages)\n * has no one to checkpoint its WAL (automatic checkpoints are off): past 4 MiB, fold it in.\n */\n #boundWal(): void {\n if (this.inTransaction()) return;\n try {\n if (statSync(`${this.#path}-wal`).size <= 4 * 1024 * 1024) return;\n } catch {\n return;\n }\n this.#db.exec(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n this.#walOffset = 0;\n }\n inTransaction(): boolean {\n return (this.#db as unknown as { isTransaction: boolean }).isTransaction;\n }\n databaseSize(): number {\n const [pc] = this.exec(\"PRAGMA page_count\", []).rows[0] as [number];\n const [ps] = this.exec(\"PRAGMA page_size\", []).rows[0] as [number];\n return Number(pc) * Number(ps);\n }\n close(): void {\n this.#db.close();\n if (this.#restoredDir) {\n rmSync(this.#restoredDir, { recursive: true, force: true });\n temporaryDirs.delete(this.#restoredDir);\n this.#restoredDir = undefined;\n }\n if (!this.#temporary) return;\n for (const suffix of [\"\", \"-wal\", \"-shm\", \"-journal\"])\n rmSync(this.#path + suffix, { force: true });\n try {\n rmdirSync(dirname(this.#path)); // the opener's directory, once its last cell is closed\n temporaryDirs.delete(dirname(this.#path));\n } catch {}\n }\n\n // ---- change capture (session extension) for transaction logs -------------------------\n #session: { changeset(): Uint8Array; close(): void } | undefined;\n /** node:sqlite exposes no ROWID session option: PK-less tables are logged as statements. */\n readonly captureCoversRowidTables = false;\n captureStart(): void {\n this.#session?.close();\n this.#session = (\n this.#db as unknown as { createSession(): { changeset(): Uint8Array; close(): void } }\n ).createSession();\n }\n captureTake(): Uint8Array {\n const s = this.#session;\n this.#session = undefined;\n if (!s) return new Uint8Array();\n try {\n return s.changeset();\n } finally {\n s.close();\n }\n }\n captureDiscard(): void {\n this.#session?.close();\n this.#session = undefined;\n }\n applyChangeset(changeset: Uint8Array): void {\n if (!changeset.byteLength) return;\n const SQLITE_CHANGESET_REPLACE = 1;\n (this.#db as unknown as { applyChangeset(c: Uint8Array, o: unknown): boolean }).applyChangeset(\n changeset,\n {\n onConflict: () => SQLITE_CHANGESET_REPLACE,\n },\n );\n }\n\n /** Known extensions only: \"sqlite_vec\" → the sqlite-vec npm package's loadable library. */\n loadExtension(name: string): void {\n this.#load(this.#db, name);\n if (!this.#extensions.includes(name)) this.#extensions.push(name);\n }\n #load(db: DatabaseSyncT, name: string): void {\n const path = KNOWN_EXTENSIONS[name]?.();\n if (!path) throw new Error(`Unknown SQLite extension \"${name}\"`);\n db.enableLoadExtension(true);\n try {\n db.loadExtension(path);\n } finally {\n db.enableLoadExtension(false);\n }\n }\n\n /**\n * The database file as SQLite wrote it (page for page), for page-level logs; an in-memory\n * database falls back to image(). Valid between transactions (rollback journal mode).\n */\n pageImage(): Uint8Array {\n if (this.#path === \":memory:\") return this.image();\n // A database restored from celld's files is in WAL mode (litestream needs it): its last\n // commits are in the -wal file until a checkpoint moves them into the main file.\n const mode = String(this.#db.prepare(\"PRAGMA journal_mode\").get()?.journal_mode ?? \"\");\n if (mode.toLowerCase() === \"wal\") {\n this.#db.exec(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n this.#walOffset = 0; // the WAL starts over\n }\n return new Uint8Array(readFileSync(this.#path));\n }\n\n /** `VACUUM INTO` a temp file: a consistent, compact image (no open transaction allowed). */\n image(): Uint8Array {\n const tmp = join(mkdtempSync(join(tmpdir(), \"cell-snap-\")), \"db.sqlite\");\n try {\n this.#db.exec(`VACUUM INTO '${tmp.replace(/'/g, \"''\")}'`);\n return new Uint8Array(readFileSync(tmp));\n } finally {\n rmSync(dirname(tmp), { recursive: true, force: true });\n }\n }\n\n /** Replaces the database file with `image` and reopens it (an in-memory DB becomes file-backed). */\n restore(image: Uint8Array): void {\n this.#db.close();\n if (this.#path === \":memory:\") {\n // A directory of its own, removed with the driver (close() or process exit).\n this.#restoredDir = mkdtempSync(join(tmpdir(), \"cell-mem-\"));\n removeAtExit(this.#restoredDir);\n this.#path = join(this.#restoredDir, \"db.sqlite\");\n }\n for (const suffix of [\"-wal\", \"-shm\", \"-journal\"]) rmSync(this.#path + suffix, { force: true });\n writeFileSync(this.#path, image);\n this.#db = this.#connect(); // with the extensions loaded before\n this.#walSetup(); // a new file: a new WAL\n }\n}\n\nfunction toSqlite(v: unknown): unknown {\n if (v instanceof ArrayBuffer) return new Uint8Array(v);\n if (typeof v === \"boolean\") return v ? 1 : 0;\n return v === undefined ? null : v;\n}\n/** Workers return BLOBs as ArrayBuffer. */\nfunction fromSqlite(v: unknown): unknown {\n if (v instanceof Uint8Array) return v.buffer.slice(v.byteOffset, v.byteOffset + v.byteLength);\n return v;\n}\n\n/** Temporary cell directories still present: removed if the process exits without closing them. */\nconst temporaryDirs = new Set<string>();\nlet exitHook = false;\nfunction removeAtExit(dir: string): void {\n temporaryDirs.add(dir);\n if (exitHook) return;\n exitHook = true;\n process.once(\"exit\", () => {\n for (const d of temporaryDirs) rmSync(d, { recursive: true, force: true });\n });\n}\n\n/**\n * One file per cell in `dir`; without `dir`, each cell in memory.\n *\n * `pageCapture`: WAL mode, and each commit's changed pages read from the WAL (takeDirtyPages),\n * so LTX logs (a celld bucket) cost O(changed pages) on Node as with SQLite WASM, instead of an\n * image of the whole database (VACUUM INTO) and a page-by-page diff per commit. A WAL needs a\n * file: without `dir`, each cell opened gets a temporary file (in a `cellb-cells-…` directory\n * under the OS temp directory), removed when the cell closes, so it still starts empty each\n * time as in memory (a bucket restores it).\n */\nexport function nodeSqliteOpener(\n dir?: string,\n opts: { exclusive?: boolean; pageCapture?: boolean } = {},\n): OpenCellSql {\n let temp: string | undefined;\n let opened = 0;\n return (cellKey) => {\n const name = cellKey.replace(/[^\\w.-]/g, \"_\");\n // The runtime's own databases (alarms index, cron state) log no pages: never captured.\n const capture = !!opts.pageCapture && !cellKey.startsWith(\"__cellb/\");\n const o = { ...opts, pageCapture: capture };\n if (dir) return new NodeSqliteDriver(`${dir}/${name}.sqlite`, o);\n if (!capture) return new NodeSqliteDriver(\":memory:\", o);\n if (!temp || !existsSync(temp)) {\n temp = mkdtempSync(join(tmpdir(), \"cellb-cells-\"));\n removeAtExit(temp);\n }\n // A file per opening: a cell reopened while its previous database is still closing gets\n // a fresh one, as in memory.\n return new NodeSqliteDriver(join(temp, `${name}-${++opened}.sqlite`), {\n ...o,\n temporary: true,\n });\n };\n}\n"]}
1
+ {"version":3,"file":"node-sqlite.js","sourceRoot":"","sources":["../../src/adapters/node-sqlite.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n closeSync,\n existsSync,\n fstatSync,\n mkdtempSync,\n openSync,\n readFileSync,\n readSync,\n rmdirSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { DatabaseSync as DatabaseSyncT } from \"node:sqlite\";\n\nimport { splitSqlStatements } from \"../core/sql-split.js\";\nimport type { OpenCellSql, SqlResult, SyncSqlDriver } from \"../ports.js\";\nimport { nodeSqliteBytes, requireNodeSqlite } from \"./node-sqlite-module.js\";\n\nconst { DatabaseSync } = requireNodeSqlite();\n\nconst requireCjs = createRequire(import.meta.url);\nconst KNOWN_EXTENSIONS: Record<string, () => string> = {\n sqlite_vec: () => (requireCjs(\"sqlite-vec\") as { getLoadablePath(): string }).getLoadablePath(),\n};\n\n/** Server-side SyncSqlDriver over node:sqlite (Node >= 22.13). */\nexport class NodeSqliteDriver implements SyncSqlDriver {\n #db: DatabaseSyncT;\n #path: string;\n readonly #exclusive: boolean;\n readonly #pageCapture: boolean;\n /** A file of its own that close() removes (a cell \"in memory\" that needs a WAL). */\n readonly #temporary: boolean;\n constructor(\n path = \":memory:\",\n opts: { exclusive?: boolean; pageCapture?: boolean; temporary?: boolean } = {},\n ) {\n this.#path = path;\n this.#temporary = !!opts.temporary && path !== \":memory:\";\n this.#exclusive = !!opts.exclusive;\n this.#pageCapture = !!opts.pageCapture && path !== \":memory:\";\n this.#db = this.#connect();\n this.#walSetup();\n }\n\n /** Extensions loaded so far, by name: a new connection (restore()) loads them again. */\n #extensions: string[] = [];\n /** The directory restore() made for an in-memory database's file. */\n #restoredDir: string | undefined;\n\n /** A connection to `#path`, set up as every connection of this driver is. */\n #connect(): DatabaseSyncT {\n // As celld and workerd: a double-quoted name that is no column is a string literal.\n const db = new DatabaseSync(this.#path, {\n allowExtension: true,\n enableDoubleQuotedStringLiterals: true,\n });\n db.enableLoadExtension(false); // only loadExtension() below may load, by name\n // EXCLUSIVE locking: the first write takes an OS lock on the file that is\n // kept until close (or process death) — a second process can neither read\n // nor write the cell. Storage-level fencing on one host, no lease needed.\n if (this.#exclusive) db.exec(\"PRAGMA locking_mode = EXCLUSIVE; PRAGMA busy_timeout = 0;\");\n try {\n for (const name of this.#extensions) this.#load(db, name);\n } catch (e) {\n db.close(); // not left open behind the error\n throw e;\n }\n return db;\n }\n\n // ---- page capture through the WAL (what the WASM driver does with its xWrite hook) ----\n // In WAL mode every commit appends its changed pages to `<db>-wal` as frames (24-byte frame\n // header + page; a commit frame carries the database size in pages). Reading the frames\n // appended since the last read gives exactly the committed transaction's pages, O(changed),\n // instead of reading the whole file. Automatic checkpoints are off; take() checkpoints\n // (TRUNCATE) itself once the WAL grows, and restarts from its start.\n #walOffset = 0;\n /** Whether anyone reads the captured pages; until then exec() keeps the WAL bounded itself. */\n #taken = false;\n #writes = 0;\n #walSetup(): void {\n if (!this.#pageCapture) return;\n this.#db.exec(\"PRAGMA journal_mode = WAL; PRAGMA wal_autocheckpoint = 0;\");\n // A temporary file is only the WAL's carrier (the bucket keeps the cell): no fsync per commit.\n if (this.#temporary) this.#db.exec(\"PRAGMA synchronous = OFF\");\n this.#db.exec(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n this.#walOffset = 0;\n }\n /** The pages of the transactions committed since the previous call (WAL frames). */\n takeDirtyPages():\n | { pageSize: number; pageCount: number; pages: Map<number, Uint8Array> }\n | undefined {\n if (!this.#pageCapture) return undefined;\n this.#taken = true;\n const walPath = `${this.#path}-wal`;\n let fd: number;\n try {\n fd = openSync(walPath, \"r\");\n } catch {\n return undefined;\n }\n try {\n const size = fstatSync(fd).size;\n if (size < 32) return undefined;\n const header = Buffer.alloc(32);\n readSync(fd, header, 0, 32, 0);\n const pageSize = header.readUInt32BE(8) === 1 ? 65536 : header.readUInt32BE(8);\n const [salt1, salt2] = [header.readUInt32BE(16), header.readUInt32BE(20)];\n const frameSize = 24 + pageSize;\n let offset = Math.max(32, this.#walOffset);\n const pending = new Map<number, Uint8Array>();\n const pages = new Map<number, Uint8Array>();\n let pageCount = 0;\n let committedTo = offset;\n const frame = Buffer.alloc(frameSize);\n while (offset + frameSize <= size) {\n readSync(fd, frame, 0, frameSize, offset);\n if (frame.readUInt32BE(8) !== salt1 || frame.readUInt32BE(12) !== salt2) break; // stale frames\n pending.set(frame.readUInt32BE(0), new Uint8Array(frame.subarray(24)));\n offset += frameSize;\n const commit = frame.readUInt32BE(4);\n if (commit) {\n for (const [p, d] of pending) pages.set(p, d);\n pending.clear();\n pageCount = commit;\n committedTo = offset;\n }\n }\n this.#walOffset = committedTo;\n if (!pageCount)\n return {\n pageSize,\n pageCount: Number(this.exec(\"PRAGMA page_count\", []).rows[0][0]),\n pages,\n };\n for (const p of [...pages.keys()]) if (p > pageCount) pages.delete(p);\n // keep the WAL bounded: fold it into the database and start over\n if (committedTo > 4 * 1024 * 1024) {\n this.#db.exec(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n this.#walOffset = 0;\n }\n return { pageSize, pageCount, pages };\n } finally {\n closeSync(fd);\n }\n }\n exec(sql: string, params: unknown[]): SqlResult {\n const statements = params.length === 0 ? splitSqlStatements(sql) : [sql];\n // Several statements: the result of the last one, with the rows written by all of them.\n let last: SqlResult = { columnNames: [], rows: [], rowsWritten: 0 };\n let written = 0;\n for (const text of statements) {\n last = this.#one(text, params);\n written += last.rowsWritten;\n }\n if (this.#pageCapture && !this.#taken && ++this.#writes % 64 === 0) this.#boundWal();\n return { ...last, rowsWritten: written };\n }\n #one(sql: string, params: unknown[]): SqlResult {\n const stmt = this.#db.prepare(sql);\n const columnNames = stmt.columns().map((c) => c.name);\n const args = params.map(toSqlite) as any[];\n if (columnNames.length === 0) {\n const r = stmt.run(...args);\n return { columnNames, rows: [], rowsWritten: Number(r.changes) };\n }\n stmt.setReturnArrays(true);\n const rows = (stmt.all(...args) as unknown as unknown[][]).map((row) => row.map(fromSqlite));\n return { columnNames, rows, rowsWritten: 0 };\n }\n /**\n * A database whose pages nobody takes (the runtime's own tables, a storage that logs no pages)\n * has no one to checkpoint its WAL (automatic checkpoints are off): past 4 MiB, fold it in.\n */\n #boundWal(): void {\n if (this.inTransaction()) return;\n try {\n if (statSync(`${this.#path}-wal`).size <= 4 * 1024 * 1024) return;\n } catch {\n return;\n }\n this.#db.exec(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n this.#walOffset = 0;\n }\n inTransaction(): boolean {\n return (this.#db as unknown as { isTransaction: boolean }).isTransaction;\n }\n databaseSize(): number {\n const [pc] = this.exec(\"PRAGMA page_count\", []).rows[0] as [number];\n const [ps] = this.exec(\"PRAGMA page_size\", []).rows[0] as [number];\n return Number(pc) * Number(ps);\n }\n close(): void {\n this.#db.close();\n if (this.#restoredDir) {\n rmSync(this.#restoredDir, { recursive: true, force: true });\n temporaryDirs.delete(this.#restoredDir);\n this.#restoredDir = undefined;\n }\n if (!this.#temporary) return;\n for (const suffix of [\"\", \"-wal\", \"-shm\", \"-journal\"])\n rmSync(this.#path + suffix, { force: true });\n try {\n rmdirSync(dirname(this.#path)); // the opener's directory, once its last cell is closed\n temporaryDirs.delete(dirname(this.#path));\n } catch {}\n }\n\n // ---- change capture (session extension) for transaction logs -------------------------\n #session: { changeset(): Uint8Array; close(): void } | undefined;\n /** node:sqlite exposes no ROWID session option: PK-less tables are logged as statements. */\n readonly captureCoversRowidTables = false;\n captureStart(): void {\n this.#session?.close();\n this.#session = (\n this.#db as unknown as { createSession(): { changeset(): Uint8Array; close(): void } }\n ).createSession();\n }\n captureTake(): Uint8Array {\n const s = this.#session;\n this.#session = undefined;\n if (!s) return new Uint8Array();\n try {\n return s.changeset();\n } finally {\n s.close();\n }\n }\n captureDiscard(): void {\n this.#session?.close();\n this.#session = undefined;\n }\n applyChangeset(changeset: Uint8Array): void {\n if (!changeset.byteLength) return;\n const SQLITE_CHANGESET_REPLACE = 1;\n (this.#db as unknown as { applyChangeset(c: Uint8Array, o: unknown): boolean }).applyChangeset(\n changeset,\n {\n onConflict: () => SQLITE_CHANGESET_REPLACE,\n },\n );\n }\n\n /** Known extensions only: \"sqlite_vec\" → the sqlite-vec npm package's loadable library. */\n loadExtension(name: string): void {\n this.#load(this.#db, name);\n if (!this.#extensions.includes(name)) this.#extensions.push(name);\n }\n #load(db: DatabaseSyncT, name: string): void {\n const path = KNOWN_EXTENSIONS[name]?.();\n if (!path) throw new Error(`Unknown SQLite extension \"${name}\"`);\n db.enableLoadExtension(true);\n try {\n db.loadExtension(path);\n } finally {\n db.enableLoadExtension(false);\n }\n }\n\n /**\n * The database file as SQLite wrote it (page for page), for page-level logs; an in-memory\n * database falls back to image(). Valid between transactions (rollback journal mode).\n */\n pageImage(): Uint8Array {\n if (this.#path === \":memory:\") return this.image();\n // A database restored from celld's files is in WAL mode (litestream needs it): its last\n // commits are in the -wal file until a checkpoint moves them into the main file.\n const mode = String(this.#db.prepare(\"PRAGMA journal_mode\").get()?.journal_mode ?? \"\");\n if (mode.toLowerCase() === \"wal\") {\n this.#db.exec(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n this.#walOffset = 0; // the WAL starts over\n }\n return new Uint8Array(readFileSync(this.#path));\n }\n\n /** `VACUUM INTO` a temp file: a consistent, compact image (no open transaction allowed). */\n image(): Uint8Array {\n const tmp = join(mkdtempSync(join(tmpdir(), \"cell-snap-\")), \"db.sqlite\");\n try {\n this.#db.exec(`VACUUM INTO '${tmp.replace(/'/g, \"''\")}'`);\n return new Uint8Array(readFileSync(tmp));\n } finally {\n rmSync(dirname(tmp), { recursive: true, force: true });\n }\n }\n\n /** Replaces the database file with `image` and reopens it (an in-memory DB becomes file-backed). */\n restore(image: Uint8Array): void {\n this.#db.close();\n if (this.#path === \":memory:\") {\n // A directory of its own, removed with the driver (close() or process exit).\n this.#restoredDir = mkdtempSync(join(tmpdir(), \"cell-mem-\"));\n removeAtExit(this.#restoredDir);\n this.#path = join(this.#restoredDir, \"db.sqlite\");\n }\n for (const suffix of [\"-wal\", \"-shm\", \"-journal\"]) rmSync(this.#path + suffix, { force: true });\n writeFileSync(this.#path, image);\n this.#db = this.#connect(); // with the extensions loaded before\n this.#walSetup(); // a new file: a new WAL\n }\n}\n\nfunction toSqlite(v: unknown): unknown {\n if (v instanceof ArrayBuffer || ArrayBuffer.isView(v)) return nodeSqliteBytes(v);\n if (typeof v === \"boolean\") return v ? 1 : 0;\n return v === undefined ? null : v;\n}\n/** Workers return BLOBs as ArrayBuffer. */\nfunction fromSqlite(v: unknown): unknown {\n if (v instanceof Uint8Array) return v.buffer.slice(v.byteOffset, v.byteOffset + v.byteLength);\n return v;\n}\n\n/** Temporary cell directories still present: removed if the process exits without closing them. */\nconst temporaryDirs = new Set<string>();\nlet exitHook = false;\nfunction removeAtExit(dir: string): void {\n temporaryDirs.add(dir);\n if (exitHook) return;\n exitHook = true;\n process.once(\"exit\", () => {\n for (const d of temporaryDirs) rmSync(d, { recursive: true, force: true });\n });\n}\n\n/**\n * One file per cell in `dir`; without `dir`, each cell in memory.\n *\n * `pageCapture`: WAL mode, and each commit's changed pages read from the WAL (takeDirtyPages),\n * so LTX logs (a celld bucket) cost O(changed pages) on Node as with SQLite WASM, instead of an\n * image of the whole database (VACUUM INTO) and a page-by-page diff per commit. A WAL needs a\n * file: without `dir`, each cell opened gets a temporary file (in a `cellb-cells-…` directory\n * under the OS temp directory), removed when the cell closes, so it still starts empty each\n * time as in memory (a bucket restores it).\n */\nexport function nodeSqliteOpener(\n dir?: string,\n opts: { exclusive?: boolean; pageCapture?: boolean } = {},\n): OpenCellSql {\n let temp: string | undefined;\n let opened = 0;\n return (cellKey) => {\n const name = cellKey.replace(/[^\\w.-]/g, \"_\");\n // The runtime's own databases (alarms index, cron state) log no pages: never captured.\n const capture = !!opts.pageCapture && !cellKey.startsWith(\"__cellb/\");\n const o = { ...opts, pageCapture: capture };\n if (dir) return new NodeSqliteDriver(`${dir}/${name}.sqlite`, o);\n if (!capture) return new NodeSqliteDriver(\":memory:\", o);\n if (!temp || !existsSync(temp)) {\n temp = mkdtempSync(join(tmpdir(), \"cellb-cells-\"));\n removeAtExit(temp);\n }\n // A file per opening: a cell reopened while its previous database is still closing gets\n // a fresh one, as in memory.\n return new NodeSqliteDriver(join(temp, `${name}-${++opened}.sqlite`), {\n ...o,\n temporary: true,\n });\n };\n}\n"]}
@@ -88,6 +88,7 @@ export declare function sahpoolOpener(sqlite3: {
88
88
  getCapacity(): number;
89
89
  getFileCount(): number;
90
90
  getFileNames?(): string[];
91
+ exportFile?(name: string): Uint8Array;
91
92
  pauseVfs?(): unknown;
92
93
  isPaused?(): boolean;
93
94
  unpauseVfs?(): Promise<unknown>;
@@ -98,5 +99,6 @@ export declare function sahpoolOpener(sqlite3: {
98
99
  }): Promise<OpenCellSql & {
99
100
  reserve(n: number): Promise<number>;
100
101
  release(): void;
102
+ exportFiles?(): [string, Uint8Array][];
101
103
  }>;
102
104
  export {};
@@ -334,6 +334,21 @@ export async function sahpoolOpener(sqlite3, opts = {}) {
334
334
  * (another tab's) can open the pool at once instead of when this worker is gone.
335
335
  */
336
336
  release: () => void pool.pauseVfs?.(),
337
+ /**
338
+ * Every cell database in the pool, as `[file name, bytes]` (`<cell key with [^\w.-] as _>.sqlite`,
339
+ * the name `nodeSqliteOpener(dir)` gives the same cell): what a deployment needs to start
340
+ * from this browser's data. Journals are left out; a database with a transaction under way
341
+ * is read as of its last commit only if the transaction is still in its journal (call it
342
+ * between events).
343
+ */
344
+ exportFiles: pool.getFileNames && pool.exportFile
345
+ ? () => (pool.getFileNames?.() ?? [])
346
+ .filter((name) => name.endsWith(".sqlite"))
347
+ .map((name) => [
348
+ name.replace(/^\/+/, ""),
349
+ pool.exportFile?.(name),
350
+ ])
351
+ : undefined,
337
352
  });
338
353
  }
339
354
  //# sourceMappingURL=wasm-sqlite.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wasm-sqlite.js","sourceRoot":"","sources":["../../src/adapters/wasm-sqlite.ts"],"names":[],"mappings":"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","sourcesContent":["import { splitSqlStatements } from \"../core/sql-split.js\";\nimport type { OpenCellSql, SqlResult, SyncSqlDriver } from \"../ports.js\";\nimport { type DirtyPages, installPageHook } from \"./wasm-page-hook.js\";\nimport { type WasmSqlite3, wasmSessionCapture } from \"./wasm-session.js\";\n\n/** Minimal slice of the @sqlite.org/sqlite-wasm `oo1.DB` API we rely on. */\nexport interface Oo1Db {\n prepare(sql: string): Oo1Stmt;\n exec(sql: string): unknown;\n changes(): number;\n close(): void;\n}\ninterface Oo1Stmt {\n bind(values: unknown[]): Oo1Stmt;\n getColumnNames(): string[];\n columnCount: number;\n step(): boolean;\n get(target: unknown[]): unknown[];\n finalize(): void;\n}\n\n/**\n * SyncSqlDriver over the official SQLite WASM build (oo1 API). Synchronous,\n * so it satisfies `ctx.storage.sql`. Works in Node (in-memory, for tests) and\n * in browsers; persistence comes from the VFS behind the DB (see sahpoolOpener).\n */\n/** Backup hooks: how to export an image of the DB and how to replace it (returns the reopened DB). */\nexport interface WasmImageHooks {\n image(db: Oo1Db): Uint8Array;\n restore(db: Oo1Db, image: Uint8Array): Oo1Db;\n}\n\nexport class WasmSqliteDriver implements SyncSqlDriver {\n captureStart?: () => void;\n captureTake?: () => Uint8Array;\n captureDiscard?: () => void;\n applyChangeset?: (changeset: Uint8Array) => void;\n captureCoversRowidTables?: boolean;\n #db: Oo1Db;\n readonly #hooks?: WasmImageHooks;\n readonly #sqlite3?: WasmSqlite3;\n readonly #capi?: { sqlite3_get_autocommit(db: number): number };\n #pageHook?: ReturnType<typeof installPageHook>;\n constructor(\n db: Oo1Db,\n hooks?: WasmImageHooks,\n sqlite3?: WasmSqlite3,\n /** SQLite's C API, for `inTransaction()` alone (when `sqlite3` is not given). */\n capi?: { sqlite3_get_autocommit(db: number): number },\n ) {\n this.#db = db;\n this.#hooks = hooks;\n this.#sqlite3 = sqlite3;\n this.#capi = capi ?? sqlite3?.capi;\n if (!this.#capi?.sqlite3_get_autocommit)\n (this as { inTransaction?: unknown }).inTransaction = undefined;\n this.#enableDqs();\n this.#hookPages();\n if (sqlite3?.capi?.sqlite3session_create) {\n // Transaction-log capture (session extension), following the current DB handle.\n Object.assign(\n this,\n wasmSessionCapture(sqlite3, () => (this.#db as unknown as { pointer: number }).pointer),\n );\n }\n if (!hooks) {\n // No image support for this driver: hide the optional port methods.\n (this as { image?: unknown }).image = undefined;\n (this as { restore?: unknown }).restore = undefined;\n }\n }\n image(): Uint8Array {\n return this.#hooks!.image(this.#db);\n }\n\n /**\n * As celld and workerd: a double-quoted name that is no column is a string literal (SQLite's\n * DQS misfeature, off in this build).\n */\n #enableDqs(): void {\n const capi = this.#sqlite3?.capi;\n if (!capi?.sqlite3_db_config) return;\n const db = (this.#db as unknown as { pointer: number }).pointer;\n capi.sqlite3_db_config(db, capi.SQLITE_DBCONFIG_DQS_DML, 1, 0);\n capi.sqlite3_db_config(db, capi.SQLITE_DBCONFIG_DQS_DDL, 1, 0);\n }\n\n /** Installs the page hook on the current main database file (see wasm-page-hook.ts). */\n #hookPages(): void {\n this.#pageHook = undefined;\n if (!this.#sqlite3?.capi?.sqlite3_file_control) return;\n try {\n this.#pageHook = installPageHook(\n this.#sqlite3,\n (this.#db as unknown as { pointer: number }).pointer,\n );\n } catch {\n this.#pageHook = undefined;\n }\n }\n /** Pages written since the previous call — a committed transaction's changed pages. */\n takeDirtyPages(): DirtyPages | undefined {\n if (!this.#pageHook) return undefined;\n const pageSize = Number(this.exec(\"PRAGMA page_size\", []).rows[0][0]);\n const pageCount = Number(this.exec(\"PRAGMA page_count\", []).rows[0][0]);\n return this.#pageHook.take(pageSize, pageCount);\n }\n discardDirtyPages(): void {\n this.#pageHook?.discard();\n }\n /**\n * WASM builds cannot load extensions at run time; an extension must be compiled into the\n * build (e.g. the `sqlite-vec-wasm-demo` package for \"sqlite_vec\"). This only checks it is.\n */\n loadExtension(name: string): void {\n const probe: Record<string, string> = { sqlite_vec: \"SELECT vec_version()\" };\n if (!probe[name]) throw new Error(`Unknown SQLite extension \"${name}\"`);\n try {\n this.exec(probe[name], []);\n } catch {\n throw new Error(`SQLite extension \"${name}\" is not compiled into this SQLite WASM build`);\n }\n }\n restore(image: Uint8Array): void {\n // celld's databases are in WAL mode (header bytes 18–19 = 2); the WASM VFSes (memdb,\n // opfs-sahpool) have no shared memory for WAL and refuse to open such a file. The pages\n // are the same in rollback-journal mode: switch the header to 1 (celld sets WAL again\n // when it opens the database).\n if (image.length > 19 && image[18] === 2 && image[19] === 2) {\n image = image.slice();\n image[18] = 1;\n image[19] = 1;\n }\n this.#db = this.#hooks!.restore(this.#db, image);\n this.#enableDqs();\n this.#hookPages(); // a new database file behind the connection\n }\n exec(sql: string, params: unknown[]): SqlResult {\n const statements = params.length === 0 ? splitSqlStatements(sql) : [sql];\n // Several statements: the result of the last one, with the rows written by all of them.\n let last: SqlResult = { columnNames: [], rows: [], rowsWritten: 0 };\n let written = 0;\n for (const text of statements) {\n last = this.#one(text, params);\n written += last.rowsWritten;\n }\n return { ...last, rowsWritten: written };\n }\n #one(sql: string, params: unknown[]): SqlResult {\n const st = this.#db.prepare(sql);\n try {\n if (params.length) st.bind(params.map(toSqlite));\n const columnNames = st.columnCount ? st.getColumnNames() : [];\n const rows: unknown[][] = [];\n while (st.step()) if (columnNames.length) rows.push(st.get([]).map(fromSqlite));\n return { columnNames, rows, rowsWritten: columnNames.length ? 0 : this.#db.changes() };\n } finally {\n st.finalize();\n }\n }\n inTransaction(): boolean {\n const pointer = (this.#db as unknown as { pointer: number }).pointer;\n return this.#capi!.sqlite3_get_autocommit(pointer) === 0;\n }\n databaseSize(): number {\n const pc = this.exec(\"PRAGMA page_count\", []).rows[0][0];\n const ps = this.exec(\"PRAGMA page_size\", []).rows[0][0];\n return Number(pc) * Number(ps);\n }\n close(): void {\n this.#db.close();\n }\n}\n\nfunction toSqlite(v: unknown): unknown {\n if (v instanceof ArrayBuffer) return new Uint8Array(v);\n if (typeof v === \"boolean\") return v ? 1 : 0;\n return v === undefined ? null : v;\n}\nfunction fromSqlite(v: unknown): unknown {\n if (v instanceof Uint8Array) return v.buffer.slice(v.byteOffset, v.byteOffset + v.byteLength);\n return v;\n}\n\n/** In-memory WASM databases (tests, ephemeral cells). `sqlite3` = await sqlite3InitModule(). */\n/** Image hooks for an in-memory DB: `sqlite3_js_db_export` / `sqlite3_deserialize`. */\nexport function memoryImageHooks(sqlite3: any): WasmImageHooks {\n const { capi, wasm } = sqlite3;\n return {\n image: (db) => sqlite3.capi.sqlite3_js_db_export(db),\n restore(db, image) {\n const p = wasm.allocFromTypedArray(image);\n const rc = capi.sqlite3_deserialize(\n (db as any).pointer,\n \"main\",\n p,\n image.byteLength,\n image.byteLength,\n capi.SQLITE_DESERIALIZE_FREEONCLOSE | capi.SQLITE_DESERIALIZE_RESIZEABLE,\n );\n if (rc) throw new Error(`sqlite3_deserialize failed: ${capi.sqlite3_js_rc_str?.(rc) ?? rc}`);\n return db;\n },\n };\n}\n\n/**\n * Sets up a new SQLite WASM connection for a cell. One worker holds many small cells, and SQLite\n * WASM's heap is capped at 2 GiB and never shrinks, so each connection's fixed memory decides how\n * many cells can be open at once:\n * - no lookaside: SQLite's per-connection allocator of small blocks, about 45 KiB each;\n * - 4 KiB pages for a database that is still empty (celld's page size: SQLite's native default;\n * the WASM build's is 8 KiB). The page cache starts with a block of pages, so the page size\n * sets most of a connection's memory. A database that already holds data keeps its page size.\n * Together they bring a connection with one small table from about 258 KiB to about 120 KiB.\n */\nexport function tuneCellConnection(sqlite3: unknown, db: Oo1Db): void {\n const capi = (sqlite3 as { capi?: Record<string, any> }).capi;\n const pointer = (db as unknown as { pointer?: number }).pointer;\n // Before the connection runs any statement: SQLite refuses (SQLITE_BUSY) while lookaside is used.\n if (capi?.sqlite3_db_config && pointer) {\n capi.sqlite3_db_config(pointer, capi.SQLITE_DBCONFIG_LOOKASIDE, 0, 0, 0);\n }\n db.exec(\"PRAGMA page_size=4096\");\n}\n\nlet memdbCounter = 0;\nexport function wasmMemoryOpener(sqlite3: {\n oo1: { DB: new (path: string, mode?: string) => Oo1Db };\n}): OpenCellSql {\n return () => {\n // memdb (not \":memory:\"): an in-memory database that IS a VFS file, so the page hook works.\n const db = new sqlite3.oo1.DB(`file:/cells-mem-${++memdbCounter}?vfs=memdb`, \"c\");\n tuneCellConnection(sqlite3, db);\n return new WasmSqliteDriver(db, memoryImageHooks(sqlite3), sqlite3 as never);\n };\n}\n\n/**\n * Browser persistence: one OPFS \"SyncAccessHandle pool\" database per cell.\n * Must run in a Dedicated Worker; needs neither COOP/COEP nor SharedArrayBuffer.\n * Not runnable in Node (installOpfsSAHPoolVfs is browser-only) — covered by P04's Playwright spec.\n */\nexport async function sahpoolOpener(\n sqlite3: {\n installOpfsSAHPoolVfs(opts: { name?: string; initialCapacity?: number }): Promise<{\n OpfsSAHPoolDb: new (path: string) => Oo1Db;\n reserveMinimumCapacity(n: number): Promise<number>;\n addCapacity?(n: number): Promise<number>;\n getCapacity(): number;\n getFileCount(): number;\n getFileNames?(): string[];\n // Not in older SQLite WASM builds (sqlite-vec's): there `release()` does nothing.\n pauseVfs?(): unknown;\n isPaused?(): boolean;\n unpauseVfs?(): Promise<unknown>;\n }>;\n },\n opts: { name?: string; initialCapacity?: number } = {},\n): Promise<OpenCellSql & { reserve(n: number): Promise<number>; release(): void }> {\n const pool = await sqlite3.installOpfsSAHPoolVfs({\n name: opts.name ?? \"cellb\",\n initialCapacity: opts.initialCapacity ?? 16,\n });\n // The same pool again in this worker (SQLite WASM keeps one per name), after a `release()`.\n if (pool.isPaused?.()) await pool.unpauseVfs?.();\n // A full pool fails the open (`SAH pool is full`), and opening is synchronous while growing\n // the pool is not. Each new slot is an OPFS file with a sync access handle, made one at a time,\n // and once the worker is busy each one takes seconds (about 5 s with 32 Flue conversations in\n // one worker), so the pool grows ahead of need, in small steps:\n // - a cell about to open reserves room first (`room`, awaited by the runtime before the cell's\n // first event): its database, its journal and a spare, and it waits until what was needed\n // when it asked fits, one step of 16 slots at a time (not a doubling, nor later reservations);\n // - an open cell counts its journal until it has one (SQLite makes it at the cell's first\n // write), so the pool grows while it still has room, not once the journals fill it;\n // - at each open (failed ones too: a cell can reopen without `room`), the pool grows in the\n // background until two thirds of it are free: an unused slot costs a small file, a missing\n // one a wait of seconds per slot, so it grows while the worker is still quiet.\n const SLOTS_PER_CELL = 3; // the database, its journal, and one spare\n const STEP = 16; // slots per growth step, made in parallel\n const AHEAD = 3; // the pool's size, in multiples of what it needs, kept by the background growth\n const reserved = new Set<string>();\n const opened = new Map<string, { path: string }>(); // the open cells' databases\n let growing: Promise<void> | undefined;\n /**\n * One growth step toward `target` (one at a time: a second caller joins it). SQLite makes a\n * pool's new slots one after another, two awaited OPFS calls each, and in a busy worker each\n * await waits seconds for the event loop: the step asks for its slots in parallel instead,\n * one `addCapacity(1)` each, so it costs about one slot's wait.\n */\n const step = (target: number): Promise<void> => {\n const n = Math.min(target, pool.getCapacity() + STEP) - pool.getCapacity();\n growing ??= (\n pool.addCapacity && n > 0\n ? Promise.all(Array.from({ length: n }, () => pool.addCapacity?.(1)))\n : pool.reserveMinimumCapacity(pool.getCapacity() + Math.max(n, 0))\n )\n .then(() => {})\n .finally(() => {\n growing = undefined;\n });\n return growing;\n };\n const needed = () => {\n // Journals not made yet. Without the pool's file names (older SQLite WASM builds) none\n // is counted, as before: the files that exist are.\n let journals = 0;\n if (pool.getFileNames) {\n const files = new Set(pool.getFileNames());\n for (const { path } of opened.values()) if (!files.has(`${path}-journal`)) journals++;\n }\n return pool.getFileCount() + journals + SLOTS_PER_CELL * reserved.size;\n };\n /** Grows until `target()` fits; stops when a step of its own adds nothing (the open says why). */\n const growTo = async (target: () => number): Promise<void> => {\n while (target() > pool.getCapacity()) {\n // A step already under way may have added its slots and not ended yet: joining it says\n // nothing about whether the pool can grow.\n const joined = growing !== undefined;\n const before = pool.getCapacity();\n await step(target());\n if (!joined && pool.getCapacity() <= before) return;\n }\n };\n const room = (cellKey: string): Promise<void> | undefined => {\n reserved.add(cellKey);\n const target = needed();\n if (target <= pool.getCapacity()) return undefined;\n return growTo(() => target);\n };\n let ahead: Promise<void> | undefined;\n const keepRoom = () => {\n if (ahead || pool.getCapacity() >= AHEAD * needed()) return;\n ahead = growTo(() => AHEAD * needed())\n .catch(() => {})\n .finally(() => {\n ahead = undefined;\n });\n };\n // The rollback journal stays in the pool between transactions (PERSIST): DELETE gives its pool\n // slot back and takes it again on every commit, which costs a header write each time. The\n // database file is the same in both modes (only WAL marks it).\n const openDb = (path: string) => {\n const db = new pool.OpfsSAHPoolDb(path);\n tuneCellConnection(sqlite3, db);\n db.exec(\"PRAGMA journal_mode=PERSIST\");\n return db;\n };\n const open: OpenCellSql = (cellKey) => {\n const path = `/${cellKey.replace(/[^\\w.-]/g, \"_\")}.sqlite`;\n reserved.delete(cellKey);\n // Counted from now on, with its journal until it has one; no longer once it is closed.\n const entry = { path };\n opened.set(cellKey, entry);\n keepRoom();\n let driver: WasmSqliteDriver;\n try {\n driver = new WasmSqliteDriver(\n openDb(path),\n {\n image: (db) => (sqlite3 as any).capi.sqlite3_js_db_export(db),\n // Replace the file inside the pool, then reopen it.\n restore(db, image) {\n db.close();\n (pool as any).importDb(path, image);\n return openDb(path);\n },\n },\n sqlite3 as never,\n );\n } catch (err) {\n if (opened.get(cellKey) === entry) opened.delete(cellKey);\n throw err;\n }\n const close = driver.close.bind(driver);\n driver.close = () => {\n // Only this driver's entry: the cell may have been opened again since.\n if (opened.get(cellKey) === entry) opened.delete(cellKey);\n close();\n };\n return driver;\n };\n return Object.assign(open, {\n room,\n reserve: (n: number) => pool.reserveMinimumCapacity(n),\n /**\n * Gives the pool's OPFS files back once every database is closed, so that another worker\n * (another tab's) can open the pool at once instead of when this worker is gone.\n */\n release: () => void pool.pauseVfs?.(),\n });\n}\n"]}
1
+ {"version":3,"file":"wasm-sqlite.js","sourceRoot":"","sources":["../../src/adapters/wasm-sqlite.ts"],"names":[],"mappings":"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","sourcesContent":["import { splitSqlStatements } from \"../core/sql-split.js\";\nimport type { OpenCellSql, SqlResult, SyncSqlDriver } from \"../ports.js\";\nimport { type DirtyPages, installPageHook } from \"./wasm-page-hook.js\";\nimport { type WasmSqlite3, wasmSessionCapture } from \"./wasm-session.js\";\n\n/** Minimal slice of the @sqlite.org/sqlite-wasm `oo1.DB` API we rely on. */\nexport interface Oo1Db {\n prepare(sql: string): Oo1Stmt;\n exec(sql: string): unknown;\n changes(): number;\n close(): void;\n}\ninterface Oo1Stmt {\n bind(values: unknown[]): Oo1Stmt;\n getColumnNames(): string[];\n columnCount: number;\n step(): boolean;\n get(target: unknown[]): unknown[];\n finalize(): void;\n}\n\n/**\n * SyncSqlDriver over the official SQLite WASM build (oo1 API). Synchronous,\n * so it satisfies `ctx.storage.sql`. Works in Node (in-memory, for tests) and\n * in browsers; persistence comes from the VFS behind the DB (see sahpoolOpener).\n */\n/** Backup hooks: how to export an image of the DB and how to replace it (returns the reopened DB). */\nexport interface WasmImageHooks {\n image(db: Oo1Db): Uint8Array;\n restore(db: Oo1Db, image: Uint8Array): Oo1Db;\n}\n\nexport class WasmSqliteDriver implements SyncSqlDriver {\n captureStart?: () => void;\n captureTake?: () => Uint8Array;\n captureDiscard?: () => void;\n applyChangeset?: (changeset: Uint8Array) => void;\n captureCoversRowidTables?: boolean;\n #db: Oo1Db;\n readonly #hooks?: WasmImageHooks;\n readonly #sqlite3?: WasmSqlite3;\n readonly #capi?: { sqlite3_get_autocommit(db: number): number };\n #pageHook?: ReturnType<typeof installPageHook>;\n constructor(\n db: Oo1Db,\n hooks?: WasmImageHooks,\n sqlite3?: WasmSqlite3,\n /** SQLite's C API, for `inTransaction()` alone (when `sqlite3` is not given). */\n capi?: { sqlite3_get_autocommit(db: number): number },\n ) {\n this.#db = db;\n this.#hooks = hooks;\n this.#sqlite3 = sqlite3;\n this.#capi = capi ?? sqlite3?.capi;\n if (!this.#capi?.sqlite3_get_autocommit)\n (this as { inTransaction?: unknown }).inTransaction = undefined;\n this.#enableDqs();\n this.#hookPages();\n if (sqlite3?.capi?.sqlite3session_create) {\n // Transaction-log capture (session extension), following the current DB handle.\n Object.assign(\n this,\n wasmSessionCapture(sqlite3, () => (this.#db as unknown as { pointer: number }).pointer),\n );\n }\n if (!hooks) {\n // No image support for this driver: hide the optional port methods.\n (this as { image?: unknown }).image = undefined;\n (this as { restore?: unknown }).restore = undefined;\n }\n }\n image(): Uint8Array {\n return this.#hooks!.image(this.#db);\n }\n\n /**\n * As celld and workerd: a double-quoted name that is no column is a string literal (SQLite's\n * DQS misfeature, off in this build).\n */\n #enableDqs(): void {\n const capi = this.#sqlite3?.capi;\n if (!capi?.sqlite3_db_config) return;\n const db = (this.#db as unknown as { pointer: number }).pointer;\n capi.sqlite3_db_config(db, capi.SQLITE_DBCONFIG_DQS_DML, 1, 0);\n capi.sqlite3_db_config(db, capi.SQLITE_DBCONFIG_DQS_DDL, 1, 0);\n }\n\n /** Installs the page hook on the current main database file (see wasm-page-hook.ts). */\n #hookPages(): void {\n this.#pageHook = undefined;\n if (!this.#sqlite3?.capi?.sqlite3_file_control) return;\n try {\n this.#pageHook = installPageHook(\n this.#sqlite3,\n (this.#db as unknown as { pointer: number }).pointer,\n );\n } catch {\n this.#pageHook = undefined;\n }\n }\n /** Pages written since the previous call — a committed transaction's changed pages. */\n takeDirtyPages(): DirtyPages | undefined {\n if (!this.#pageHook) return undefined;\n const pageSize = Number(this.exec(\"PRAGMA page_size\", []).rows[0][0]);\n const pageCount = Number(this.exec(\"PRAGMA page_count\", []).rows[0][0]);\n return this.#pageHook.take(pageSize, pageCount);\n }\n discardDirtyPages(): void {\n this.#pageHook?.discard();\n }\n /**\n * WASM builds cannot load extensions at run time; an extension must be compiled into the\n * build (e.g. the `sqlite-vec-wasm-demo` package for \"sqlite_vec\"). This only checks it is.\n */\n loadExtension(name: string): void {\n const probe: Record<string, string> = { sqlite_vec: \"SELECT vec_version()\" };\n if (!probe[name]) throw new Error(`Unknown SQLite extension \"${name}\"`);\n try {\n this.exec(probe[name], []);\n } catch {\n throw new Error(`SQLite extension \"${name}\" is not compiled into this SQLite WASM build`);\n }\n }\n restore(image: Uint8Array): void {\n // celld's databases are in WAL mode (header bytes 18–19 = 2); the WASM VFSes (memdb,\n // opfs-sahpool) have no shared memory for WAL and refuse to open such a file. The pages\n // are the same in rollback-journal mode: switch the header to 1 (celld sets WAL again\n // when it opens the database).\n if (image.length > 19 && image[18] === 2 && image[19] === 2) {\n image = image.slice();\n image[18] = 1;\n image[19] = 1;\n }\n this.#db = this.#hooks!.restore(this.#db, image);\n this.#enableDqs();\n this.#hookPages(); // a new database file behind the connection\n }\n exec(sql: string, params: unknown[]): SqlResult {\n const statements = params.length === 0 ? splitSqlStatements(sql) : [sql];\n // Several statements: the result of the last one, with the rows written by all of them.\n let last: SqlResult = { columnNames: [], rows: [], rowsWritten: 0 };\n let written = 0;\n for (const text of statements) {\n last = this.#one(text, params);\n written += last.rowsWritten;\n }\n return { ...last, rowsWritten: written };\n }\n #one(sql: string, params: unknown[]): SqlResult {\n const st = this.#db.prepare(sql);\n try {\n if (params.length) st.bind(params.map(toSqlite));\n const columnNames = st.columnCount ? st.getColumnNames() : [];\n const rows: unknown[][] = [];\n while (st.step()) if (columnNames.length) rows.push(st.get([]).map(fromSqlite));\n return { columnNames, rows, rowsWritten: columnNames.length ? 0 : this.#db.changes() };\n } finally {\n st.finalize();\n }\n }\n inTransaction(): boolean {\n const pointer = (this.#db as unknown as { pointer: number }).pointer;\n return this.#capi!.sqlite3_get_autocommit(pointer) === 0;\n }\n databaseSize(): number {\n const pc = this.exec(\"PRAGMA page_count\", []).rows[0][0];\n const ps = this.exec(\"PRAGMA page_size\", []).rows[0][0];\n return Number(pc) * Number(ps);\n }\n close(): void {\n this.#db.close();\n }\n}\n\nfunction toSqlite(v: unknown): unknown {\n if (v instanceof ArrayBuffer) return new Uint8Array(v);\n if (typeof v === \"boolean\") return v ? 1 : 0;\n return v === undefined ? null : v;\n}\nfunction fromSqlite(v: unknown): unknown {\n if (v instanceof Uint8Array) return v.buffer.slice(v.byteOffset, v.byteOffset + v.byteLength);\n return v;\n}\n\n/** In-memory WASM databases (tests, ephemeral cells). `sqlite3` = await sqlite3InitModule(). */\n/** Image hooks for an in-memory DB: `sqlite3_js_db_export` / `sqlite3_deserialize`. */\nexport function memoryImageHooks(sqlite3: any): WasmImageHooks {\n const { capi, wasm } = sqlite3;\n return {\n image: (db) => sqlite3.capi.sqlite3_js_db_export(db),\n restore(db, image) {\n const p = wasm.allocFromTypedArray(image);\n const rc = capi.sqlite3_deserialize(\n (db as any).pointer,\n \"main\",\n p,\n image.byteLength,\n image.byteLength,\n capi.SQLITE_DESERIALIZE_FREEONCLOSE | capi.SQLITE_DESERIALIZE_RESIZEABLE,\n );\n if (rc) throw new Error(`sqlite3_deserialize failed: ${capi.sqlite3_js_rc_str?.(rc) ?? rc}`);\n return db;\n },\n };\n}\n\n/**\n * Sets up a new SQLite WASM connection for a cell. One worker holds many small cells, and SQLite\n * WASM's heap is capped at 2 GiB and never shrinks, so each connection's fixed memory decides how\n * many cells can be open at once:\n * - no lookaside: SQLite's per-connection allocator of small blocks, about 45 KiB each;\n * - 4 KiB pages for a database that is still empty (celld's page size: SQLite's native default;\n * the WASM build's is 8 KiB). The page cache starts with a block of pages, so the page size\n * sets most of a connection's memory. A database that already holds data keeps its page size.\n * Together they bring a connection with one small table from about 258 KiB to about 120 KiB.\n */\nexport function tuneCellConnection(sqlite3: unknown, db: Oo1Db): void {\n const capi = (sqlite3 as { capi?: Record<string, any> }).capi;\n const pointer = (db as unknown as { pointer?: number }).pointer;\n // Before the connection runs any statement: SQLite refuses (SQLITE_BUSY) while lookaside is used.\n if (capi?.sqlite3_db_config && pointer) {\n capi.sqlite3_db_config(pointer, capi.SQLITE_DBCONFIG_LOOKASIDE, 0, 0, 0);\n }\n db.exec(\"PRAGMA page_size=4096\");\n}\n\nlet memdbCounter = 0;\nexport function wasmMemoryOpener(sqlite3: {\n oo1: { DB: new (path: string, mode?: string) => Oo1Db };\n}): OpenCellSql {\n return () => {\n // memdb (not \":memory:\"): an in-memory database that IS a VFS file, so the page hook works.\n const db = new sqlite3.oo1.DB(`file:/cells-mem-${++memdbCounter}?vfs=memdb`, \"c\");\n tuneCellConnection(sqlite3, db);\n return new WasmSqliteDriver(db, memoryImageHooks(sqlite3), sqlite3 as never);\n };\n}\n\n/**\n * Browser persistence: one OPFS \"SyncAccessHandle pool\" database per cell.\n * Must run in a Dedicated Worker; needs neither COOP/COEP nor SharedArrayBuffer.\n * Not runnable in Node (installOpfsSAHPoolVfs is browser-only) — covered by P04's Playwright spec.\n */\nexport async function sahpoolOpener(\n sqlite3: {\n installOpfsSAHPoolVfs(opts: { name?: string; initialCapacity?: number }): Promise<{\n OpfsSAHPoolDb: new (path: string) => Oo1Db;\n reserveMinimumCapacity(n: number): Promise<number>;\n addCapacity?(n: number): Promise<number>;\n getCapacity(): number;\n getFileCount(): number;\n getFileNames?(): string[];\n exportFile?(name: string): Uint8Array;\n // Not in older SQLite WASM builds (sqlite-vec's): there `release()` does nothing.\n pauseVfs?(): unknown;\n isPaused?(): boolean;\n unpauseVfs?(): Promise<unknown>;\n }>;\n },\n opts: { name?: string; initialCapacity?: number } = {},\n): Promise<\n OpenCellSql & {\n reserve(n: number): Promise<number>;\n release(): void;\n exportFiles?(): [string, Uint8Array][];\n }\n> {\n const pool = await sqlite3.installOpfsSAHPoolVfs({\n name: opts.name ?? \"cellb\",\n initialCapacity: opts.initialCapacity ?? 16,\n });\n // The same pool again in this worker (SQLite WASM keeps one per name), after a `release()`.\n if (pool.isPaused?.()) await pool.unpauseVfs?.();\n // A full pool fails the open (`SAH pool is full`), and opening is synchronous while growing\n // the pool is not. Each new slot is an OPFS file with a sync access handle, made one at a time,\n // and once the worker is busy each one takes seconds (about 5 s with 32 Flue conversations in\n // one worker), so the pool grows ahead of need, in small steps:\n // - a cell about to open reserves room first (`room`, awaited by the runtime before the cell's\n // first event): its database, its journal and a spare, and it waits until what was needed\n // when it asked fits, one step of 16 slots at a time (not a doubling, nor later reservations);\n // - an open cell counts its journal until it has one (SQLite makes it at the cell's first\n // write), so the pool grows while it still has room, not once the journals fill it;\n // - at each open (failed ones too: a cell can reopen without `room`), the pool grows in the\n // background until two thirds of it are free: an unused slot costs a small file, a missing\n // one a wait of seconds per slot, so it grows while the worker is still quiet.\n const SLOTS_PER_CELL = 3; // the database, its journal, and one spare\n const STEP = 16; // slots per growth step, made in parallel\n const AHEAD = 3; // the pool's size, in multiples of what it needs, kept by the background growth\n const reserved = new Set<string>();\n const opened = new Map<string, { path: string }>(); // the open cells' databases\n let growing: Promise<void> | undefined;\n /**\n * One growth step toward `target` (one at a time: a second caller joins it). SQLite makes a\n * pool's new slots one after another, two awaited OPFS calls each, and in a busy worker each\n * await waits seconds for the event loop: the step asks for its slots in parallel instead,\n * one `addCapacity(1)` each, so it costs about one slot's wait.\n */\n const step = (target: number): Promise<void> => {\n const n = Math.min(target, pool.getCapacity() + STEP) - pool.getCapacity();\n growing ??= (\n pool.addCapacity && n > 0\n ? Promise.all(Array.from({ length: n }, () => pool.addCapacity?.(1)))\n : pool.reserveMinimumCapacity(pool.getCapacity() + Math.max(n, 0))\n )\n .then(() => {})\n .finally(() => {\n growing = undefined;\n });\n return growing;\n };\n const needed = () => {\n // Journals not made yet. Without the pool's file names (older SQLite WASM builds) none\n // is counted, as before: the files that exist are.\n let journals = 0;\n if (pool.getFileNames) {\n const files = new Set(pool.getFileNames());\n for (const { path } of opened.values()) if (!files.has(`${path}-journal`)) journals++;\n }\n return pool.getFileCount() + journals + SLOTS_PER_CELL * reserved.size;\n };\n /** Grows until `target()` fits; stops when a step of its own adds nothing (the open says why). */\n const growTo = async (target: () => number): Promise<void> => {\n while (target() > pool.getCapacity()) {\n // A step already under way may have added its slots and not ended yet: joining it says\n // nothing about whether the pool can grow.\n const joined = growing !== undefined;\n const before = pool.getCapacity();\n await step(target());\n if (!joined && pool.getCapacity() <= before) return;\n }\n };\n const room = (cellKey: string): Promise<void> | undefined => {\n reserved.add(cellKey);\n const target = needed();\n if (target <= pool.getCapacity()) return undefined;\n return growTo(() => target);\n };\n let ahead: Promise<void> | undefined;\n const keepRoom = () => {\n if (ahead || pool.getCapacity() >= AHEAD * needed()) return;\n ahead = growTo(() => AHEAD * needed())\n .catch(() => {})\n .finally(() => {\n ahead = undefined;\n });\n };\n // The rollback journal stays in the pool between transactions (PERSIST): DELETE gives its pool\n // slot back and takes it again on every commit, which costs a header write each time. The\n // database file is the same in both modes (only WAL marks it).\n const openDb = (path: string) => {\n const db = new pool.OpfsSAHPoolDb(path);\n tuneCellConnection(sqlite3, db);\n db.exec(\"PRAGMA journal_mode=PERSIST\");\n return db;\n };\n const open: OpenCellSql = (cellKey) => {\n const path = `/${cellKey.replace(/[^\\w.-]/g, \"_\")}.sqlite`;\n reserved.delete(cellKey);\n // Counted from now on, with its journal until it has one; no longer once it is closed.\n const entry = { path };\n opened.set(cellKey, entry);\n keepRoom();\n let driver: WasmSqliteDriver;\n try {\n driver = new WasmSqliteDriver(\n openDb(path),\n {\n image: (db) => (sqlite3 as any).capi.sqlite3_js_db_export(db),\n // Replace the file inside the pool, then reopen it.\n restore(db, image) {\n db.close();\n (pool as any).importDb(path, image);\n return openDb(path);\n },\n },\n sqlite3 as never,\n );\n } catch (err) {\n if (opened.get(cellKey) === entry) opened.delete(cellKey);\n throw err;\n }\n const close = driver.close.bind(driver);\n driver.close = () => {\n // Only this driver's entry: the cell may have been opened again since.\n if (opened.get(cellKey) === entry) opened.delete(cellKey);\n close();\n };\n return driver;\n };\n return Object.assign(open, {\n room,\n reserve: (n: number) => pool.reserveMinimumCapacity(n),\n /**\n * Gives the pool's OPFS files back once every database is closed, so that another worker\n * (another tab's) can open the pool at once instead of when this worker is gone.\n */\n release: () => void pool.pauseVfs?.(),\n /**\n * Every cell database in the pool, as `[file name, bytes]` (`<cell key with [^\\w.-] as _>.sqlite`,\n * the name `nodeSqliteOpener(dir)` gives the same cell): what a deployment needs to start\n * from this browser's data. Journals are left out; a database with a transaction under way\n * is read as of its last commit only if the transaction is still in its journal (call it\n * between events).\n */\n exportFiles:\n pool.getFileNames && pool.exportFile\n ? () =>\n (pool.getFileNames?.() ?? [])\n .filter((name) => name.endsWith(\".sqlite\"))\n .map((name): [string, Uint8Array] => [\n name.replace(/^\\/+/, \"\"),\n pool.exportFile?.(name) as Uint8Array,\n ])\n : undefined,\n });\n}\n"]}
@@ -163,12 +163,19 @@ export function startCronTriggers(expressions, handler, clock, state) {
163
163
  const timers = new Set();
164
164
  let chain = Promise.resolve();
165
165
  let stopped = false;
166
+ // A timer waits at most 2^31 - 1 ms: setTimeout fires a longer delay after 1 ms, which ran
167
+ // a trigger whose occurrences are further apart (any monthly or yearly one) at once, and
168
+ // then each following occurrence about every millisecond.
166
169
  const at = (t, fn) => {
167
170
  const h = clock.setTimeout(() => {
168
171
  timers.delete(h);
169
- if (!stopped)
172
+ if (stopped)
173
+ return;
174
+ if (clock.now() < t)
175
+ at(t, fn);
176
+ else
170
177
  fn();
171
- }, Math.max(0, t - clock.now()));
178
+ }, Math.min(Math.max(0, t - clock.now()), 2 ** 31 - 1));
172
179
  timers.add(h);
173
180
  };
174
181
  const run = (s, scheduledTime, failures, nextOccurrence) => {
@@ -1 +1 @@
1
- {"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/bindings/cron.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Cron Triggers in celld's dialect (docs/services/cron-triggers.md, = Cloudflare's):\n * five fields — minute, hour, day of month, month, day of week — UTC, one-minute resolution.\n * `*`, values, `a-b`, `a,b`, `/n`; month and weekday names; weekdays 1–7 from SUNDAY;\n * day of month `L`, `L-<n>`, `LW`, `L-<n>W`, `<d>W`; day of week `<dow>L`, `<dow>#<n>`.\n * When both day fields are restricted they form a union. Refused like celld: descending\n * ranges, lists containing `*`, steps wider than the field.\n */\nconst MONTHS = [\"JAN\", \"FEB\", \"MAR\", \"APR\", \"MAY\", \"JUN\", \"JUL\", \"AUG\", \"SEP\", \"OCT\", \"NOV\", \"DEC\"];\nconst DAYS = [\"SUN\", \"MON\", \"TUE\", \"WED\", \"THU\", \"FRI\", \"SAT\"];\n\ninterface Field {\n any: boolean;\n values: Set<number>;\n}\n\nfunction parseSimple(\n text: string,\n min: number,\n max: number,\n names?: string[],\n nameBase = 1,\n): Field {\n if (text === \"*\") return { any: true, values: new Set(range(min, max)) };\n const parts = text.split(\",\");\n if (parts.length > 1 && parts.includes(\"*\"))\n throw new Error(`cron: a list cannot contain \"*\": ${text}`);\n const values = new Set<number>();\n const value = (v: string) => {\n const i = names?.indexOf(v.toUpperCase()) ?? -1;\n const n = i >= 0 ? i + nameBase : Number(v);\n if (!Number.isInteger(n) || n < min || n > max)\n throw new Error(`cron: value out of range: ${v}`);\n return n;\n };\n for (const part of parts) {\n const [base, stepText] = part.split(\"/\");\n const step = stepText === undefined ? 1 : Number(stepText);\n if (!Number.isInteger(step) || step < 1 || step > max - min)\n throw new Error(`cron: bad step: ${part}`);\n let lo: number;\n let hi: number;\n if (base === \"*\") [lo, hi] = [min, max];\n else if (base.includes(\"-\")) {\n const [a, b] = base.split(\"-\");\n [lo, hi] = [value(a), value(b)];\n if (lo > hi) throw new Error(`cron: descending range: ${base}`);\n } else {\n lo = value(base);\n hi = stepText === undefined ? lo : max;\n }\n for (let v = lo; v <= hi; v += step) values.add(v);\n }\n return { any: false, values };\n}\n\nconst range = (a: number, b: number) => Array.from({ length: b - a + 1 }, (_, i) => a + i);\nconst daysInMonth = (y: number, m: number) => new Date(Date.UTC(y, m + 1, 0)).getUTCDate();\n\ntype DayRule = (y: number, m: number, d: number) => boolean;\n\nfunction parseDom(text: string): { any: boolean; match: DayRule } {\n if (text === \"*\") return { any: true, match: () => true };\n const rules: DayRule[] = [];\n for (const part of text.split(\",\")) {\n const up = part.toUpperCase();\n const last = /^L(?:-(\\d+))?(W?)$/.exec(up);\n const weekdayOf = /^(\\d+)W$/.exec(up);\n if (last) {\n const m = last;\n const back = Number(m[1] ?? 0);\n const weekday = m[2] === \"W\";\n rules.push((y, mo, d) => {\n const target = daysInMonth(y, mo) - back;\n return d === (weekday ? nearestWeekday(y, mo, target) : target);\n });\n } else if (weekdayOf) {\n const day = Number(weekdayOf[1]);\n rules.push((y, mo, d) => d === nearestWeekday(y, mo, Math.min(day, daysInMonth(y, mo))));\n } else {\n const f = parseSimple(part, 1, 31);\n rules.push((_y, _m, d) => f.values.has(d));\n }\n }\n return { any: false, match: (y, mo, d) => rules.some((r) => r(y, mo, d)) };\n}\n\nfunction nearestWeekday(y: number, m: number, day: number): number {\n const dow = new Date(Date.UTC(y, m, day)).getUTCDay();\n if (dow === 6) return day > 1 ? day - 1 : day + 2;\n if (dow === 0) return day < daysInMonth(y, m) ? day + 1 : day - 2;\n return day;\n}\n\nfunction parseDow(text: string): { any: boolean; match: DayRule } {\n if (text === \"*\") return { any: true, match: () => true };\n const rules: DayRule[] = [];\n const dowOf = (v: string) => {\n const i = DAYS.indexOf(v.toUpperCase());\n const n = i >= 0 ? i + 1 : Number(v);\n if (!Number.isInteger(n) || n < 1 || n > 7) throw new Error(`cron: weekday out of range: ${v}`);\n return n - 1; // JS getUTCDay(): 0 = Sunday\n };\n for (const part of text.split(\",\")) {\n const lastOf = /^(\\w+)L$/i.exec(part);\n const nthOf = /^(\\w+)#(\\d)$/.exec(part);\n if (lastOf && !/^\\d+$/.test(part)) {\n const dow = dowOf(lastOf[1]);\n rules.push(\n (y, mo, d) =>\n new Date(Date.UTC(y, mo, d)).getUTCDay() === dow && d + 7 > daysInMonth(y, mo),\n );\n } else if (nthOf) {\n const dow = dowOf(nthOf[1]);\n const nth = Number(nthOf[2]);\n rules.push(\n (y, mo, d) => new Date(Date.UTC(y, mo, d)).getUTCDay() === dow && Math.ceil(d / 7) === nth,\n );\n } else {\n const f = parseSimple(part, 1, 7, DAYS, 1);\n rules.push((y, mo, d) => f.values.has(new Date(Date.UTC(y, mo, d)).getUTCDay() + 1));\n }\n }\n return { any: false, match: (y, mo, d) => rules.some((r) => r(y, mo, d)) };\n}\n\nexport interface CronSchedule {\n readonly text: string;\n matches(t: number): boolean;\n /** First occurrence strictly after `t` (ms), at a whole minute. */\n next(t: number): number;\n}\n\nexport function parseCron(text: string): CronSchedule {\n const fields = text.trim().split(/\\s+/);\n if (fields.length !== 5) throw new Error(`cron: expected 5 fields: ${text}`);\n const minute = parseSimple(fields[0], 0, 59);\n const hour = parseSimple(fields[1], 0, 23);\n const dom = parseDom(fields[2]);\n const month = parseSimple(fields[3], 1, 12, MONTHS, 1);\n const dow = parseDow(fields[4]);\n const dayOk = (y: number, m: number, d: number) =>\n dom.any && dow.any\n ? true\n : dom.any\n ? dow.match(y, m, d)\n : dow.any\n ? dom.match(y, m, d)\n : dom.match(y, m, d) || dow.match(y, m, d);\n const matches = (t: number) => {\n const x = new Date(t);\n return (\n minute.values.has(x.getUTCMinutes()) &&\n hour.values.has(x.getUTCHours()) &&\n month.values.has(x.getUTCMonth() + 1) &&\n dayOk(x.getUTCFullYear(), x.getUTCMonth(), x.getUTCDate())\n );\n };\n return {\n text,\n matches,\n next(t: number) {\n let c = Math.floor(t / 60_000) * 60_000 + 60_000;\n const limit = c + 5 * 366 * 86_400_000;\n while (c < limit) {\n const x = new Date(c);\n if (\n !month.values.has(x.getUTCMonth() + 1) ||\n !dayOk(x.getUTCFullYear(), x.getUTCMonth(), x.getUTCDate())\n ) {\n c = Date.UTC(x.getUTCFullYear(), x.getUTCMonth(), x.getUTCDate() + 1); // next day, 00:00\n continue;\n }\n if (matches(c)) return c;\n c += 60_000;\n }\n throw new Error(`cron: no occurrence within 5 years: ${text}`);\n },\n };\n}\n\nexport interface CronClock {\n now(): number;\n setTimeout(fn: () => void, ms: number): unknown;\n clearTimeout(h: unknown): void;\n}\n\n/**\n * Runs the Worker's `scheduled(controller, env, ctx)` for each expression, as celld does:\n * one invocation at a time with its `waitUntil()` work drained before the next; a throwing\n * handler retries after 4 s, doubling, until six failures, `controller.noRetry()` or the next\n * occurrence; `scheduledTime` names the occurrence, not the attempt.\n */\n/** Where the last fired occurrence of each expression is kept (for the downtime catch-up). */\nexport interface CronStateStore {\n get(expression: string): number | undefined;\n set(expression: string, scheduledTime: number): void;\n}\n\nexport function startCronTriggers(\n expressions: string[],\n handler: (\n controller: unknown,\n ctx: { waitUntil(p: Promise<unknown>): void; passThroughOnException(): void },\n ) => unknown,\n clock: CronClock,\n state?: CronStateStore,\n): () => void {\n const schedules = expressions.map(parseCron);\n const timers = new Set<unknown>();\n let chain: Promise<void> = Promise.resolve();\n let stopped = false;\n const at = (t: number, fn: () => void) => {\n const h = clock.setTimeout(\n () => {\n timers.delete(h);\n if (!stopped) fn();\n },\n Math.max(0, t - clock.now()),\n );\n timers.add(h);\n };\n const run = (\n s: CronSchedule,\n scheduledTime: number,\n failures: number,\n nextOccurrence: number,\n ) => {\n chain = chain.then(async () => {\n let retry = true;\n const pending: Promise<unknown>[] = [];\n const controller = {\n cron: s.text,\n scheduledTime,\n type: \"scheduled\",\n noRetry: () => {\n retry = false;\n },\n };\n try {\n await handler(controller, {\n waitUntil: (p) => pending.push(p),\n passThroughOnException() {},\n });\n await Promise.allSettled(pending);\n } catch {\n await Promise.allSettled(pending);\n const delay = 4_000 * 2 ** failures;\n if (retry && failures + 1 < 6 && clock.now() + delay < nextOccurrence)\n at(clock.now() + delay, () => run(s, scheduledTime, failures + 1, nextOccurrence));\n }\n });\n };\n const arm = (s: CronSchedule, from: number) => {\n const t = s.next(from);\n at(t, () => {\n state?.set(s.text, t);\n run(s, t, 0, s.next(t));\n arm(s, t);\n });\n };\n // After downtime: run ONE missed occurrence (the latest) and skip the rest, as celld does.\n for (const s of schedules) {\n const last = state?.get(s.text);\n if (last === undefined) continue;\n let missed: number | undefined;\n const now = clock.now();\n for (let t = s.next(last), n = 0; t <= now && n < 600_000; t = s.next(t), n++) missed = t;\n if (missed !== undefined) {\n state?.set(s.text, missed);\n run(s, missed, 0, s.next(missed));\n }\n }\n for (const s of schedules) arm(s, clock.now());\n return () => {\n stopped = true;\n for (const h of timers) clock.clearTimeout(h);\n timers.clear();\n };\n}\n"]}
1
+ {"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/bindings/cron.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Cron Triggers in celld's dialect (docs/services/cron-triggers.md, = Cloudflare's):\n * five fields — minute, hour, day of month, month, day of week — UTC, one-minute resolution.\n * `*`, values, `a-b`, `a,b`, `/n`; month and weekday names; weekdays 1–7 from SUNDAY;\n * day of month `L`, `L-<n>`, `LW`, `L-<n>W`, `<d>W`; day of week `<dow>L`, `<dow>#<n>`.\n * When both day fields are restricted they form a union. Refused like celld: descending\n * ranges, lists containing `*`, steps wider than the field.\n */\nconst MONTHS = [\"JAN\", \"FEB\", \"MAR\", \"APR\", \"MAY\", \"JUN\", \"JUL\", \"AUG\", \"SEP\", \"OCT\", \"NOV\", \"DEC\"];\nconst DAYS = [\"SUN\", \"MON\", \"TUE\", \"WED\", \"THU\", \"FRI\", \"SAT\"];\n\ninterface Field {\n any: boolean;\n values: Set<number>;\n}\n\nfunction parseSimple(\n text: string,\n min: number,\n max: number,\n names?: string[],\n nameBase = 1,\n): Field {\n if (text === \"*\") return { any: true, values: new Set(range(min, max)) };\n const parts = text.split(\",\");\n if (parts.length > 1 && parts.includes(\"*\"))\n throw new Error(`cron: a list cannot contain \"*\": ${text}`);\n const values = new Set<number>();\n const value = (v: string) => {\n const i = names?.indexOf(v.toUpperCase()) ?? -1;\n const n = i >= 0 ? i + nameBase : Number(v);\n if (!Number.isInteger(n) || n < min || n > max)\n throw new Error(`cron: value out of range: ${v}`);\n return n;\n };\n for (const part of parts) {\n const [base, stepText] = part.split(\"/\");\n const step = stepText === undefined ? 1 : Number(stepText);\n if (!Number.isInteger(step) || step < 1 || step > max - min)\n throw new Error(`cron: bad step: ${part}`);\n let lo: number;\n let hi: number;\n if (base === \"*\") [lo, hi] = [min, max];\n else if (base.includes(\"-\")) {\n const [a, b] = base.split(\"-\");\n [lo, hi] = [value(a), value(b)];\n if (lo > hi) throw new Error(`cron: descending range: ${base}`);\n } else {\n lo = value(base);\n hi = stepText === undefined ? lo : max;\n }\n for (let v = lo; v <= hi; v += step) values.add(v);\n }\n return { any: false, values };\n}\n\nconst range = (a: number, b: number) => Array.from({ length: b - a + 1 }, (_, i) => a + i);\nconst daysInMonth = (y: number, m: number) => new Date(Date.UTC(y, m + 1, 0)).getUTCDate();\n\ntype DayRule = (y: number, m: number, d: number) => boolean;\n\nfunction parseDom(text: string): { any: boolean; match: DayRule } {\n if (text === \"*\") return { any: true, match: () => true };\n const rules: DayRule[] = [];\n for (const part of text.split(\",\")) {\n const up = part.toUpperCase();\n const last = /^L(?:-(\\d+))?(W?)$/.exec(up);\n const weekdayOf = /^(\\d+)W$/.exec(up);\n if (last) {\n const m = last;\n const back = Number(m[1] ?? 0);\n const weekday = m[2] === \"W\";\n rules.push((y, mo, d) => {\n const target = daysInMonth(y, mo) - back;\n return d === (weekday ? nearestWeekday(y, mo, target) : target);\n });\n } else if (weekdayOf) {\n const day = Number(weekdayOf[1]);\n rules.push((y, mo, d) => d === nearestWeekday(y, mo, Math.min(day, daysInMonth(y, mo))));\n } else {\n const f = parseSimple(part, 1, 31);\n rules.push((_y, _m, d) => f.values.has(d));\n }\n }\n return { any: false, match: (y, mo, d) => rules.some((r) => r(y, mo, d)) };\n}\n\nfunction nearestWeekday(y: number, m: number, day: number): number {\n const dow = new Date(Date.UTC(y, m, day)).getUTCDay();\n if (dow === 6) return day > 1 ? day - 1 : day + 2;\n if (dow === 0) return day < daysInMonth(y, m) ? day + 1 : day - 2;\n return day;\n}\n\nfunction parseDow(text: string): { any: boolean; match: DayRule } {\n if (text === \"*\") return { any: true, match: () => true };\n const rules: DayRule[] = [];\n const dowOf = (v: string) => {\n const i = DAYS.indexOf(v.toUpperCase());\n const n = i >= 0 ? i + 1 : Number(v);\n if (!Number.isInteger(n) || n < 1 || n > 7) throw new Error(`cron: weekday out of range: ${v}`);\n return n - 1; // JS getUTCDay(): 0 = Sunday\n };\n for (const part of text.split(\",\")) {\n const lastOf = /^(\\w+)L$/i.exec(part);\n const nthOf = /^(\\w+)#(\\d)$/.exec(part);\n if (lastOf && !/^\\d+$/.test(part)) {\n const dow = dowOf(lastOf[1]);\n rules.push(\n (y, mo, d) =>\n new Date(Date.UTC(y, mo, d)).getUTCDay() === dow && d + 7 > daysInMonth(y, mo),\n );\n } else if (nthOf) {\n const dow = dowOf(nthOf[1]);\n const nth = Number(nthOf[2]);\n rules.push(\n (y, mo, d) => new Date(Date.UTC(y, mo, d)).getUTCDay() === dow && Math.ceil(d / 7) === nth,\n );\n } else {\n const f = parseSimple(part, 1, 7, DAYS, 1);\n rules.push((y, mo, d) => f.values.has(new Date(Date.UTC(y, mo, d)).getUTCDay() + 1));\n }\n }\n return { any: false, match: (y, mo, d) => rules.some((r) => r(y, mo, d)) };\n}\n\nexport interface CronSchedule {\n readonly text: string;\n matches(t: number): boolean;\n /** First occurrence strictly after `t` (ms), at a whole minute. */\n next(t: number): number;\n}\n\nexport function parseCron(text: string): CronSchedule {\n const fields = text.trim().split(/\\s+/);\n if (fields.length !== 5) throw new Error(`cron: expected 5 fields: ${text}`);\n const minute = parseSimple(fields[0], 0, 59);\n const hour = parseSimple(fields[1], 0, 23);\n const dom = parseDom(fields[2]);\n const month = parseSimple(fields[3], 1, 12, MONTHS, 1);\n const dow = parseDow(fields[4]);\n const dayOk = (y: number, m: number, d: number) =>\n dom.any && dow.any\n ? true\n : dom.any\n ? dow.match(y, m, d)\n : dow.any\n ? dom.match(y, m, d)\n : dom.match(y, m, d) || dow.match(y, m, d);\n const matches = (t: number) => {\n const x = new Date(t);\n return (\n minute.values.has(x.getUTCMinutes()) &&\n hour.values.has(x.getUTCHours()) &&\n month.values.has(x.getUTCMonth() + 1) &&\n dayOk(x.getUTCFullYear(), x.getUTCMonth(), x.getUTCDate())\n );\n };\n return {\n text,\n matches,\n next(t: number) {\n let c = Math.floor(t / 60_000) * 60_000 + 60_000;\n const limit = c + 5 * 366 * 86_400_000;\n while (c < limit) {\n const x = new Date(c);\n if (\n !month.values.has(x.getUTCMonth() + 1) ||\n !dayOk(x.getUTCFullYear(), x.getUTCMonth(), x.getUTCDate())\n ) {\n c = Date.UTC(x.getUTCFullYear(), x.getUTCMonth(), x.getUTCDate() + 1); // next day, 00:00\n continue;\n }\n if (matches(c)) return c;\n c += 60_000;\n }\n throw new Error(`cron: no occurrence within 5 years: ${text}`);\n },\n };\n}\n\nexport interface CronClock {\n now(): number;\n setTimeout(fn: () => void, ms: number): unknown;\n clearTimeout(h: unknown): void;\n}\n\n/**\n * Runs the Worker's `scheduled(controller, env, ctx)` for each expression, as celld does:\n * one invocation at a time with its `waitUntil()` work drained before the next; a throwing\n * handler retries after 4 s, doubling, until six failures, `controller.noRetry()` or the next\n * occurrence; `scheduledTime` names the occurrence, not the attempt.\n */\n/** Where the last fired occurrence of each expression is kept (for the downtime catch-up). */\nexport interface CronStateStore {\n get(expression: string): number | undefined;\n set(expression: string, scheduledTime: number): void;\n}\n\nexport function startCronTriggers(\n expressions: string[],\n handler: (\n controller: unknown,\n ctx: { waitUntil(p: Promise<unknown>): void; passThroughOnException(): void },\n ) => unknown,\n clock: CronClock,\n state?: CronStateStore,\n): () => void {\n const schedules = expressions.map(parseCron);\n const timers = new Set<unknown>();\n let chain: Promise<void> = Promise.resolve();\n let stopped = false;\n // A timer waits at most 2^31 - 1 ms: setTimeout fires a longer delay after 1 ms, which ran\n // a trigger whose occurrences are further apart (any monthly or yearly one) at once, and\n // then each following occurrence about every millisecond.\n const at = (t: number, fn: () => void) => {\n const h = clock.setTimeout(\n () => {\n timers.delete(h);\n if (stopped) return;\n if (clock.now() < t) at(t, fn);\n else fn();\n },\n Math.min(Math.max(0, t - clock.now()), 2 ** 31 - 1),\n );\n timers.add(h);\n };\n const run = (\n s: CronSchedule,\n scheduledTime: number,\n failures: number,\n nextOccurrence: number,\n ) => {\n chain = chain.then(async () => {\n let retry = true;\n const pending: Promise<unknown>[] = [];\n const controller = {\n cron: s.text,\n scheduledTime,\n type: \"scheduled\",\n noRetry: () => {\n retry = false;\n },\n };\n try {\n await handler(controller, {\n waitUntil: (p) => pending.push(p),\n passThroughOnException() {},\n });\n await Promise.allSettled(pending);\n } catch {\n await Promise.allSettled(pending);\n const delay = 4_000 * 2 ** failures;\n if (retry && failures + 1 < 6 && clock.now() + delay < nextOccurrence)\n at(clock.now() + delay, () => run(s, scheduledTime, failures + 1, nextOccurrence));\n }\n });\n };\n const arm = (s: CronSchedule, from: number) => {\n const t = s.next(from);\n at(t, () => {\n state?.set(s.text, t);\n run(s, t, 0, s.next(t));\n arm(s, t);\n });\n };\n // After downtime: run ONE missed occurrence (the latest) and skip the rest, as celld does.\n for (const s of schedules) {\n const last = state?.get(s.text);\n if (last === undefined) continue;\n let missed: number | undefined;\n const now = clock.now();\n for (let t = s.next(last), n = 0; t <= now && n < 600_000; t = s.next(t), n++) missed = t;\n if (missed !== undefined) {\n state?.set(s.text, missed);\n run(s, missed, 0, s.next(missed));\n }\n }\n for (const s of schedules) arm(s, clock.now());\n return () => {\n stopped = true;\n for (const h of timers) clock.clearTimeout(h);\n timers.clear();\n };\n}\n"]}
@@ -4,6 +4,20 @@ export declare function resolveModuleName(spec: string, importer: string, names:
4
4
  export declare const RESOLVE_MODULE_NAME_SOURCE = "(spec, importer, names) => {\n if (names.has(spec)) return spec;\n if (!/^\\.{0,2}\\//.test(spec)) return undefined;\n const name = new URL(spec, \"file:///\" + importer).pathname.slice(1);\n return names.has(name) ? name : undefined;\n}";
5
5
  /** The identifier rewritten calls use. */
6
6
  export declare const IMPORT_FROM = "__cellbImportFrom";
7
+ /** What an ES module exports by name, and the specifiers it re-exports everything from. */
8
+ export interface ModuleExports {
9
+ names: string[];
10
+ stars: string[];
11
+ }
12
+ /**
13
+ * One parse of ES module `source` (named `name`): its text with each `import(spec)` the bundler
14
+ * cannot link routed through `__cellbImportFrom` (`routed`, undefined when there is none), and
15
+ * its exports. `undefined` when it does not parse (the loader then reports its syntax error).
16
+ */
17
+ export declare function analyzeModule(source: string, name: string): {
18
+ routed: string | undefined;
19
+ exports: ModuleExports;
20
+ } | undefined;
7
21
  /**
8
22
  * `source` (an ES module named `name`) with each `import(spec)` that the bundler cannot link (a
9
23
  * computed specifier, or a literal that is not a relative path) calling `__cellbImportFrom(spec,
@@ -11,20 +25,16 @@ export declare const IMPORT_FROM = "__cellbImportFrom";
11
25
  * reports its syntax error).
12
26
  */
13
27
  export declare function routeDynamicImports(source: string, name: string): string | undefined;
14
- /** `prelude` put in front of `source` on its first line (after a hashbang), so lines keep their numbers. */
15
- export declare function prefixModule(source: string, prelude: string): string;
16
- /** What an ES module exports by name, and the specifiers it re-exports everything from. */
17
- export interface ModuleExports {
18
- names: string[];
19
- stars: string[];
20
- }
21
28
  /** The exports of ES module `source` (`undefined` if it does not parse). */
22
29
  export declare function moduleExports(source: string): ModuleExports | undefined;
30
+ /** `prelude` put in front of `source` on its first line (after a hashbang), so lines keep their numbers. */
31
+ export declare function prefixModule(source: string, prelude: string): string;
23
32
  /**
24
33
  * Each module's export names, `export *` followed within the modules (as far as they resolve).
25
- * A module that does not parse, or a star from outside them, adds nothing.
34
+ * A module that does not parse, or a star from outside them, adds nothing. `modules` are the
35
+ * modules' texts, or their exports already found (`analyzeModule`).
26
36
  */
27
- export declare function exportNamesByModule(modules: Record<string, string>): Record<string, string[]>;
37
+ export declare function exportNamesByModule(modules: Record<string, string> | Map<string, ModuleExports>): Record<string, string[]>;
28
38
  /**
29
39
  * An ES module that stands for loaded module `name` where code imports it by a specifier no
30
40
  * bundler saw (an `import()` in code built with `Function`): it takes the bundled module's