@statewalker/cellb 0.5.1 → 0.5.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.
- package/dist/adapters/node-sqlite-module.d.ts +9 -0
- package/dist/adapters/node-sqlite-module.js +28 -0
- package/dist/adapters/node-sqlite-module.js.map +1 -0
- package/dist/adapters/node-sqlite.js +2 -3
- package/dist/adapters/node-sqlite.js.map +1 -1
- package/dist/bucket/sqlite-object-store.js +2 -2
- package/dist/bucket/sqlite-object-store.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `node:sqlite`, loaded without Node's "SQLite is an experimental feature" warning. cellb is
|
|
3
|
+
* the one choosing the module, not its user, so the warning would only be noise on every start
|
|
4
|
+
* (`loadProject`, `nodeSqliteOpener`). Only that warning is held back; any other passes.
|
|
5
|
+
*
|
|
6
|
+
* Loaded with `require`: bundlers (vite/vitest) strip the "node:" prefix of the experimental
|
|
7
|
+
* builtin and then fail to resolve "sqlite".
|
|
8
|
+
*/
|
|
9
|
+
export declare function requireNodeSqlite(): typeof import("node:sqlite");
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
const require = createRequire(import.meta.url);
|
|
3
|
+
/**
|
|
4
|
+
* `node:sqlite`, loaded without Node's "SQLite is an experimental feature" warning. cellb is
|
|
5
|
+
* the one choosing the module, not its user, so the warning would only be noise on every start
|
|
6
|
+
* (`loadProject`, `nodeSqliteOpener`). Only that warning is held back; any other passes.
|
|
7
|
+
*
|
|
8
|
+
* Loaded with `require`: bundlers (vite/vitest) strip the "node:" prefix of the experimental
|
|
9
|
+
* builtin and then fail to resolve "sqlite".
|
|
10
|
+
*/
|
|
11
|
+
export function requireNodeSqlite() {
|
|
12
|
+
const emitWarning = process.emitWarning;
|
|
13
|
+
process.emitWarning = function (warning, ...rest) {
|
|
14
|
+
const type = typeof rest[0] === "string" ? rest[0] : rest[0]?.type;
|
|
15
|
+
const text = typeof warning === "string" ? warning : warning?.message;
|
|
16
|
+
const name = typeof warning === "string" ? type : (warning?.name ?? type);
|
|
17
|
+
if (name === "ExperimentalWarning" && /\bSQLite\b/.test(String(text)))
|
|
18
|
+
return;
|
|
19
|
+
return emitWarning.call(process, warning, ...rest);
|
|
20
|
+
};
|
|
21
|
+
try {
|
|
22
|
+
return require("node:sqlite");
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
process.emitWarning = emitWarning;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=node-sqlite-module.js.map
|
|
@@ -0,0 +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"]}
|
|
@@ -2,10 +2,9 @@ import { closeSync, fstatSync, mkdtempSync, openSync, readFileSync, readSync, rm
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
|
-
// Loaded via require: bundlers (vite/vitest) strip the "node:" prefix of the
|
|
6
|
-
// still-experimental node:sqlite builtin and fail to resolve "sqlite".
|
|
7
|
-
const { DatabaseSync } = createRequire(import.meta.url)("node:sqlite");
|
|
8
5
|
import { splitSqlStatements } from "../core/sql-split.js";
|
|
6
|
+
import { requireNodeSqlite } from "./node-sqlite-module.js";
|
|
7
|
+
const { DatabaseSync } = requireNodeSqlite();
|
|
9
8
|
const requireCjs = createRequire(import.meta.url);
|
|
10
9
|
const KNOWN_EXTENSIONS = {
|
|
11
10
|
sqlite_vec: () => requireCjs("sqlite-vec").getLoadablePath(),
|
|
@@ -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 fstatSync,\n mkdtempSync,\n openSync,\n readFileSync,\n readSync,\n rmSync,\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\n// Loaded via require: bundlers (vite/vitest) strip the \"node:\" prefix of the\n// still-experimental node:sqlite builtin and fail to resolve \"sqlite\".\nconst { DatabaseSync } = createRequire(import.meta.url)(\n \"node:sqlite\",\n) as typeof import(\"node:sqlite\");\n\nimport { splitSqlStatements } from \"../core/sql-split.js\";\nimport type { OpenCellSql, SqlResult, SyncSqlDriver } from \"../ports.js\";\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 constructor(path = \":memory:\", opts: { exclusive?: boolean; pageCapture?: boolean } = {}) {\n this.#path = path;\n this.#exclusive = !!opts.exclusive;\n this.#pageCapture = !!opts.pageCapture && path !== \":memory:\";\n // As celld and workerd: a double-quoted name that is no column is a string literal.\n this.#db = new DatabaseSync(path, {\n allowExtension: true,\n enableDoubleQuotedStringLiterals: true,\n });\n this.#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 (opts.exclusive) this.#db.exec(\"PRAGMA locking_mode = EXCLUSIVE; PRAGMA busy_timeout = 0;\");\n this.#walSetup();\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 #walSetup(): void {\n if (!this.#pageCapture) return;\n this.#db.exec(\"PRAGMA journal_mode = WAL; PRAGMA wal_autocheckpoint = 0;\");\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 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 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 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 }\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 const path = KNOWN_EXTENSIONS[name]?.();\n if (!path) throw new Error(`Unknown SQLite extension \"${name}\"`);\n this.#db.enableLoadExtension(true);\n try {\n this.#db.loadExtension(path);\n } finally {\n this.#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 this.#path = join(mkdtempSync(join(tmpdir(), \"cell-mem-\")), \"db.sqlite\");\n for (const suffix of [\"-wal\", \"-shm\", \"-journal\"]) rmSync(this.#path + suffix, { force: true });\n writeFileSync(this.#path, image);\n this.#db = new DatabaseSync(this.#path, { enableDoubleQuotedStringLiterals: true });\n if (this.#exclusive) this.#db.exec(\"PRAGMA locking_mode = EXCLUSIVE; PRAGMA busy_timeout = 0;\");\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/** One file per cell in `dir`, or in-memory when `dir` is omitted. */\n/**\n * `pageCapture` (file-backed only): WAL mode, and each commit's changed pages read from the WAL\n * (takeDirtyPages) — LTX logs then cost O(changed pages) on Node as with SQLite WASM.\n */\nexport function nodeSqliteOpener(\n dir?: string,\n opts: { exclusive?: boolean; pageCapture?: boolean } = {},\n): OpenCellSql {\n return (cellKey) =>\n new NodeSqliteDriver(\n dir ? `${dir}/${cellKey.replace(/[^\\w.-]/g, \"_\")}.sqlite` : \":memory:\",\n opts,\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 fstatSync,\n mkdtempSync,\n openSync,\n readFileSync,\n readSync,\n rmSync,\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 constructor(path = \":memory:\", opts: { exclusive?: boolean; pageCapture?: boolean } = {}) {\n this.#path = path;\n this.#exclusive = !!opts.exclusive;\n this.#pageCapture = !!opts.pageCapture && path !== \":memory:\";\n // As celld and workerd: a double-quoted name that is no column is a string literal.\n this.#db = new DatabaseSync(path, {\n allowExtension: true,\n enableDoubleQuotedStringLiterals: true,\n });\n this.#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 (opts.exclusive) this.#db.exec(\"PRAGMA locking_mode = EXCLUSIVE; PRAGMA busy_timeout = 0;\");\n this.#walSetup();\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 #walSetup(): void {\n if (!this.#pageCapture) return;\n this.#db.exec(\"PRAGMA journal_mode = WAL; PRAGMA wal_autocheckpoint = 0;\");\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 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 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 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 }\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 const path = KNOWN_EXTENSIONS[name]?.();\n if (!path) throw new Error(`Unknown SQLite extension \"${name}\"`);\n this.#db.enableLoadExtension(true);\n try {\n this.#db.loadExtension(path);\n } finally {\n this.#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 this.#path = join(mkdtempSync(join(tmpdir(), \"cell-mem-\")), \"db.sqlite\");\n for (const suffix of [\"-wal\", \"-shm\", \"-journal\"]) rmSync(this.#path + suffix, { force: true });\n writeFileSync(this.#path, image);\n this.#db = new DatabaseSync(this.#path, { enableDoubleQuotedStringLiterals: true });\n if (this.#exclusive) this.#db.exec(\"PRAGMA locking_mode = EXCLUSIVE; PRAGMA busy_timeout = 0;\");\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/** One file per cell in `dir`, or in-memory when `dir` is omitted. */\n/**\n * `pageCapture` (file-backed only): WAL mode, and each commit's changed pages read from the WAL\n * (takeDirtyPages) — LTX logs then cost O(changed pages) on Node as with SQLite WASM.\n */\nexport function nodeSqliteOpener(\n dir?: string,\n opts: { exclusive?: boolean; pageCapture?: boolean } = {},\n): OpenCellSql {\n return (cellKey) =>\n new NodeSqliteDriver(\n dir ? `${dir}/${cellKey.replace(/[^\\w.-]/g, \"_\")}.sqlite` : \":memory:\",\n opts,\n );\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { requireNodeSqlite } from "../adapters/node-sqlite-module.js";
|
|
2
2
|
import { PreconditionFailedError } from "./object-store.js";
|
|
3
|
-
const { DatabaseSync } =
|
|
3
|
+
const { DatabaseSync } = requireNodeSqlite();
|
|
4
4
|
/**
|
|
5
5
|
* celld dev's local bucket: `<project>/.celld/dev/objects.sqlite3` (objects(key, body, etag
|
|
6
6
|
* INTEGER, modified_ms, attributes) + store_sequence). Reading and writing it lets a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-object-store.js","sourceRoot":"","sources":["../../src/bucket/sqlite-object-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"sqlite-object-store.js","sourceRoot":"","sources":["../../src/bucket/sqlite-object-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { requireNodeSqlite } from \"../adapters/node-sqlite-module.js\";\nimport type { ObjectAttributes, ObjectStore } from \"./object-store.js\";\nimport { PreconditionFailedError } from \"./object-store.js\";\n\nconst { DatabaseSync } = requireNodeSqlite();\n\n/**\n * celld dev's local bucket: `<project>/.celld/dev/objects.sqlite3` (objects(key, body, etag\n * INTEGER, modified_ms, attributes) + store_sequence). Reading and writing it lets a\n * cellb node and `celld dev` share one bucket, so cells move between them.\n * Conditional writes are real (one SQLite transaction).\n */\nexport function sqliteObjectStore(file: string): ObjectStore & { close(): void } {\n const db = new DatabaseSync(file);\n db.exec(`CREATE TABLE IF NOT EXISTS objects (\n key TEXT PRIMARY KEY, body BLOB NOT NULL, etag INTEGER NOT NULL,\n modified_ms INTEGER NOT NULL, attributes TEXT NOT NULL)`);\n db.exec(`CREATE TABLE IF NOT EXISTS store_sequence (\n singleton INTEGER PRIMARY KEY CHECK (singleton = 1), next_etag INTEGER NOT NULL)`);\n db.exec(\"INSERT OR IGNORE INTO store_sequence (singleton, next_etag) VALUES (1, 1)\");\n db.exec(\"PRAGMA busy_timeout = 5000\");\n return {\n async get(key) {\n const r = db\n .prepare(\"SELECT body, etag, modified_ms, attributes FROM objects WHERE key = ?\")\n .get(key) as\n | { body: Uint8Array; etag: number; modified_ms: number; attributes: string }\n | undefined;\n return r\n ? {\n body: new Uint8Array(r.body),\n etag: String(r.etag),\n modifiedMs: Number(r.modified_ms),\n attrs: fromAttributes(r.attributes),\n }\n : undefined;\n },\n async put(key, body, cond, attrs) {\n db.exec(\"BEGIN IMMEDIATE\");\n try {\n const cur = db.prepare(\"SELECT etag FROM objects WHERE key = ?\").get(key) as\n | { etag: number }\n | undefined;\n if (cond?.ifNoneMatch === \"*\" && cur) throw new PreconditionFailedError(key);\n if (cond?.ifMatch !== undefined && String(cur?.etag) !== cond.ifMatch)\n throw new PreconditionFailedError(key);\n const { next_etag } = db\n .prepare(\"SELECT next_etag FROM store_sequence WHERE singleton = 1\")\n .get() as {\n next_etag: number;\n };\n db.prepare(\"UPDATE store_sequence SET next_etag = ? WHERE singleton = 1\").run(\n next_etag + 1,\n );\n db.prepare(\n \"INSERT OR REPLACE INTO objects (key, body, etag, modified_ms, attributes) VALUES (?, ?, ?, ?, ?)\",\n ).run(key, body, next_etag, Date.now(), toAttributes(attrs));\n db.exec(\"COMMIT\");\n return String(next_etag);\n } catch (e) {\n db.exec(\"ROLLBACK\");\n throw e;\n }\n },\n async list(prefix) {\n return (\n db\n .prepare(\"SELECT key FROM objects WHERE key >= ? AND key < ? ORDER BY key\")\n .all(prefix, `${prefix}\\uffff`) as {\n key: string;\n }[]\n ).map((r) => r.key);\n },\n async delete(key) {\n db.prepare(\"DELETE FROM objects WHERE key = ?\").run(key);\n },\n close() {\n db.close();\n },\n };\n}\n\n// celld dev's `attributes` column: a JSON array of {kind, name, value} — \"metadata\" entries\n// (user metadata, name = key) and one entry per content header (\"content-type\", …).\ntype HeaderField =\n | \"contentType\"\n | \"contentLanguage\"\n | \"contentDisposition\"\n | \"contentEncoding\"\n | \"cacheControl\";\nconst HEADERS: [HeaderField, string][] = [\n [\"contentType\", \"content-type\"],\n [\"contentLanguage\", \"content-language\"],\n [\"contentDisposition\", \"content-disposition\"],\n [\"contentEncoding\", \"content-encoding\"],\n [\"cacheControl\", \"cache-control\"],\n];\nfunction toAttributes(attrs?: ObjectAttributes): string {\n const out: { kind: string; name: string | null; value: string }[] = [];\n for (const [name, value] of Object.entries(attrs?.metadata ?? {}))\n out.push({ kind: \"metadata\", name, value });\n for (const [field, kind] of HEADERS) {\n const v = attrs?.[field];\n if (typeof v === \"string\") out.push({ kind, name: null, value: v });\n }\n return JSON.stringify(out);\n}\nfunction fromAttributes(raw: string): ObjectAttributes | undefined {\n let list: { kind: string; name: string | null; value: string }[];\n try {\n list = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (!Array.isArray(list) || !list.length) return undefined;\n const attrs: ObjectAttributes = {};\n for (const e of list) {\n if (e.kind === \"metadata\" && e.name) {\n attrs.metadata = attrs.metadata ?? {};\n attrs.metadata[e.name] = e.value;\n }\n const h = HEADERS.find(([, kind]) => kind === e.kind);\n if (h) (attrs as Record<string, unknown>)[h[0]] = e.value;\n }\n return attrs;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statewalker/cellb",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "cellb: isomorphic Durable Objects runtime (celld/Cloudflare-compatible surface) for browsers and servers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@statewalker/webrun-files-browser": "^0.10.0",
|
|
60
60
|
"@statewalker/webrun-files-mem": "^0.10.0",
|
|
61
61
|
"@statewalker/webrun-files-node": "^0.10.3",
|
|
62
|
-
"@statewalker/webrun-http-browser": "^0.12.
|
|
62
|
+
"@statewalker/webrun-http-browser": "^0.12.2",
|
|
63
63
|
"@statewalker/webrun-http-streams": "^0.4.0",
|
|
64
64
|
"@statewalker/webrun-rpc": "^0.10.0",
|
|
65
65
|
"@statewalker/webrun-streams": "^0.2.3",
|