@statewalker/cellb 0.8.3 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/adapters/node-sqlite.d.ts +9 -3
- package/dist/adapters/node-sqlite.js +82 -5
- package/dist/adapters/node-sqlite.js.map +1 -1
- package/dist/core/storage.d.ts +0 -4
- package/dist/core/storage.js +41 -2
- package/dist/core/storage.js.map +1 -1
- package/dist/isolate/node-entry.js +3 -2
- package/dist/isolate/node-entry.js.map +1 -1
- package/dist/project/node-load.js +5 -1
- package/dist/project/node-load.js.map +1 -1
- package/dist/project/wrangler.d.ts +5 -1
- package/dist/project/wrangler.js +6 -2
- package/dist/project/wrangler.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -171,7 +171,10 @@ import { MemFilesApi } from "@statewalker/webrun-files-mem";
|
|
|
171
171
|
|
|
172
172
|
const dir = "./counter"; // wrangler.jsonc and its `main`
|
|
173
173
|
const { runtime, unsupported } = await loadNodeProject(dir, {
|
|
174
|
-
|
|
174
|
+
// Every cell starts empty and is restored from the bucket on first use. pageCapture logs each
|
|
175
|
+
// commit's pages from the WAL (O(changed pages)) instead of imaging the whole database per
|
|
176
|
+
// commit; without a directory, cells live in temporary files removed when they close.
|
|
177
|
+
openSql: nodeSqliteOpener(undefined, { pageCapture: true }),
|
|
175
178
|
files: new MemFilesApi(), // blob store for large KV values
|
|
176
179
|
storage: celldBucket(sqliteObjectStore(`${dir}/.celld/dev/objects.sqlite3`), { node: "cellb-1" }),
|
|
177
180
|
});
|
|
@@ -5,6 +5,7 @@ export declare class NodeSqliteDriver implements SyncSqlDriver {
|
|
|
5
5
|
constructor(path?: string, opts?: {
|
|
6
6
|
exclusive?: boolean;
|
|
7
7
|
pageCapture?: boolean;
|
|
8
|
+
temporary?: boolean;
|
|
8
9
|
});
|
|
9
10
|
/** The pages of the transactions committed since the previous call (WAL frames). */
|
|
10
11
|
takeDirtyPages(): {
|
|
@@ -34,10 +35,15 @@ export declare class NodeSqliteDriver implements SyncSqlDriver {
|
|
|
34
35
|
/** Replaces the database file with `image` and reopens it (an in-memory DB becomes file-backed). */
|
|
35
36
|
restore(image: Uint8Array): void;
|
|
36
37
|
}
|
|
37
|
-
/** One file per cell in `dir`, or in-memory when `dir` is omitted. */
|
|
38
38
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
39
|
+
* One file per cell in `dir`; without `dir`, each cell in memory.
|
|
40
|
+
*
|
|
41
|
+
* `pageCapture`: WAL mode, and each commit's changed pages read from the WAL (takeDirtyPages),
|
|
42
|
+
* so LTX logs (a celld bucket) cost O(changed pages) on Node as with SQLite WASM, instead of an
|
|
43
|
+
* image of the whole database (VACUUM INTO) and a page-by-page diff per commit. A WAL needs a
|
|
44
|
+
* file: without `dir`, each cell opened gets a temporary file (in a `cellb-cells-…` directory
|
|
45
|
+
* under the OS temp directory), removed when the cell closes, so it still starts empty each
|
|
46
|
+
* time as in memory (a bucket restores it).
|
|
41
47
|
*/
|
|
42
48
|
export declare function nodeSqliteOpener(dir?: string, opts?: {
|
|
43
49
|
exclusive?: boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { closeSync, fstatSync, mkdtempSync, openSync, readFileSync, readSync, rmSync, writeFileSync, } from "node:fs";
|
|
1
|
+
import { closeSync, existsSync, fstatSync, mkdtempSync, openSync, readFileSync, readSync, rmdirSync, rmSync, statSync, writeFileSync, } from "node:fs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
@@ -15,8 +15,11 @@ export class NodeSqliteDriver {
|
|
|
15
15
|
#path;
|
|
16
16
|
#exclusive;
|
|
17
17
|
#pageCapture;
|
|
18
|
+
/** A file of its own that close() removes (a cell "in memory" that needs a WAL). */
|
|
19
|
+
#temporary;
|
|
18
20
|
constructor(path = ":memory:", opts = {}) {
|
|
19
21
|
this.#path = path;
|
|
22
|
+
this.#temporary = !!opts.temporary && path !== ":memory:";
|
|
20
23
|
this.#exclusive = !!opts.exclusive;
|
|
21
24
|
this.#pageCapture = !!opts.pageCapture && path !== ":memory:";
|
|
22
25
|
// As celld and workerd: a double-quoted name that is no column is a string literal.
|
|
@@ -39,10 +42,16 @@ export class NodeSqliteDriver {
|
|
|
39
42
|
// instead of reading the whole file. Automatic checkpoints are off; take() checkpoints
|
|
40
43
|
// (TRUNCATE) itself once the WAL grows, and restarts from its start.
|
|
41
44
|
#walOffset = 0;
|
|
45
|
+
/** Whether anyone reads the captured pages; until then exec() keeps the WAL bounded itself. */
|
|
46
|
+
#taken = false;
|
|
47
|
+
#writes = 0;
|
|
42
48
|
#walSetup() {
|
|
43
49
|
if (!this.#pageCapture)
|
|
44
50
|
return;
|
|
45
51
|
this.#db.exec("PRAGMA journal_mode = WAL; PRAGMA wal_autocheckpoint = 0;");
|
|
52
|
+
// A temporary file is only the WAL's carrier (the bucket keeps the cell): no fsync per commit.
|
|
53
|
+
if (this.#temporary)
|
|
54
|
+
this.#db.exec("PRAGMA synchronous = OFF");
|
|
46
55
|
this.#db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
47
56
|
this.#walOffset = 0;
|
|
48
57
|
}
|
|
@@ -50,6 +59,7 @@ export class NodeSqliteDriver {
|
|
|
50
59
|
takeDirtyPages() {
|
|
51
60
|
if (!this.#pageCapture)
|
|
52
61
|
return undefined;
|
|
62
|
+
this.#taken = true;
|
|
53
63
|
const walPath = `${this.#path}-wal`;
|
|
54
64
|
let fd;
|
|
55
65
|
try {
|
|
@@ -118,6 +128,8 @@ export class NodeSqliteDriver {
|
|
|
118
128
|
last = this.#one(text, params);
|
|
119
129
|
written += last.rowsWritten;
|
|
120
130
|
}
|
|
131
|
+
if (this.#pageCapture && !this.#taken && ++this.#writes % 64 === 0)
|
|
132
|
+
this.#boundWal();
|
|
121
133
|
return { ...last, rowsWritten: written };
|
|
122
134
|
}
|
|
123
135
|
#one(sql, params) {
|
|
@@ -132,6 +144,23 @@ export class NodeSqliteDriver {
|
|
|
132
144
|
const rows = stmt.all(...args).map((row) => row.map(fromSqlite));
|
|
133
145
|
return { columnNames, rows, rowsWritten: 0 };
|
|
134
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* A database whose pages nobody takes (the runtime's own tables, a storage that logs no pages)
|
|
149
|
+
* has no one to checkpoint its WAL (automatic checkpoints are off): past 4 MiB, fold it in.
|
|
150
|
+
*/
|
|
151
|
+
#boundWal() {
|
|
152
|
+
if (this.inTransaction())
|
|
153
|
+
return;
|
|
154
|
+
try {
|
|
155
|
+
if (statSync(`${this.#path}-wal`).size <= 4 * 1024 * 1024)
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
this.#db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
162
|
+
this.#walOffset = 0;
|
|
163
|
+
}
|
|
135
164
|
inTransaction() {
|
|
136
165
|
return this.#db.isTransaction;
|
|
137
166
|
}
|
|
@@ -142,6 +171,15 @@ export class NodeSqliteDriver {
|
|
|
142
171
|
}
|
|
143
172
|
close() {
|
|
144
173
|
this.#db.close();
|
|
174
|
+
if (!this.#temporary)
|
|
175
|
+
return;
|
|
176
|
+
for (const suffix of ["", "-wal", "-shm", "-journal"])
|
|
177
|
+
rmSync(this.#path + suffix, { force: true });
|
|
178
|
+
try {
|
|
179
|
+
rmdirSync(dirname(this.#path)); // the opener's directory, once its last cell is closed
|
|
180
|
+
temporaryDirs.delete(dirname(this.#path));
|
|
181
|
+
}
|
|
182
|
+
catch { }
|
|
145
183
|
}
|
|
146
184
|
// ---- change capture (session extension) for transaction logs -------------------------
|
|
147
185
|
#session;
|
|
@@ -242,12 +280,51 @@ function fromSqlite(v) {
|
|
|
242
280
|
return v.buffer.slice(v.byteOffset, v.byteOffset + v.byteLength);
|
|
243
281
|
return v;
|
|
244
282
|
}
|
|
245
|
-
/**
|
|
283
|
+
/** Temporary cell directories still present: removed if the process exits without closing them. */
|
|
284
|
+
const temporaryDirs = new Set();
|
|
285
|
+
let exitHook = false;
|
|
286
|
+
function removeAtExit(dir) {
|
|
287
|
+
temporaryDirs.add(dir);
|
|
288
|
+
if (exitHook)
|
|
289
|
+
return;
|
|
290
|
+
exitHook = true;
|
|
291
|
+
process.once("exit", () => {
|
|
292
|
+
for (const d of temporaryDirs)
|
|
293
|
+
rmSync(d, { recursive: true, force: true });
|
|
294
|
+
});
|
|
295
|
+
}
|
|
246
296
|
/**
|
|
247
|
-
*
|
|
248
|
-
*
|
|
297
|
+
* One file per cell in `dir`; without `dir`, each cell in memory.
|
|
298
|
+
*
|
|
299
|
+
* `pageCapture`: WAL mode, and each commit's changed pages read from the WAL (takeDirtyPages),
|
|
300
|
+
* so LTX logs (a celld bucket) cost O(changed pages) on Node as with SQLite WASM, instead of an
|
|
301
|
+
* image of the whole database (VACUUM INTO) and a page-by-page diff per commit. A WAL needs a
|
|
302
|
+
* file: without `dir`, each cell opened gets a temporary file (in a `cellb-cells-…` directory
|
|
303
|
+
* under the OS temp directory), removed when the cell closes, so it still starts empty each
|
|
304
|
+
* time as in memory (a bucket restores it).
|
|
249
305
|
*/
|
|
250
306
|
export function nodeSqliteOpener(dir, opts = {}) {
|
|
251
|
-
|
|
307
|
+
let temp;
|
|
308
|
+
let opened = 0;
|
|
309
|
+
return (cellKey) => {
|
|
310
|
+
const name = cellKey.replace(/[^\w.-]/g, "_");
|
|
311
|
+
// The runtime's own databases (alarms index, cron state) log no pages: never captured.
|
|
312
|
+
const capture = !!opts.pageCapture && !cellKey.startsWith("__cellb/");
|
|
313
|
+
const o = { ...opts, pageCapture: capture };
|
|
314
|
+
if (dir)
|
|
315
|
+
return new NodeSqliteDriver(`${dir}/${name}.sqlite`, o);
|
|
316
|
+
if (!capture)
|
|
317
|
+
return new NodeSqliteDriver(":memory:", o);
|
|
318
|
+
if (!temp || !existsSync(temp)) {
|
|
319
|
+
temp = mkdtempSync(join(tmpdir(), "cellb-cells-"));
|
|
320
|
+
removeAtExit(temp);
|
|
321
|
+
}
|
|
322
|
+
// A file per opening: a cell reopened while its previous database is still closing gets
|
|
323
|
+
// a fresh one, as in memory.
|
|
324
|
+
return new NodeSqliteDriver(join(temp, `${name}-${++opened}.sqlite`), {
|
|
325
|
+
...o,
|
|
326
|
+
temporary: true,
|
|
327
|
+
});
|
|
328
|
+
};
|
|
252
329
|
}
|
|
253
330
|
//# sourceMappingURL=node-sqlite.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-sqlite.js","sourceRoot":"","sources":["../../src/adapters/node-sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,SAAS,EACT,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,MAAM,EAAE,YAAY,EAAE,GAAG,iBAAiB,EAAE,CAAC;AAE7C,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,gBAAgB,GAAiC;IACrD,UAAU,EAAE,GAAG,EAAE,CAAE,UAAU,CAAC,YAAY,CAAmC,CAAC,eAAe,EAAE;CAChG,CAAC;AAEF,kEAAkE;AAClE,MAAM,OAAO,gBAAgB;IAC3B,GAAG,CAAgB;IACnB,KAAK,CAAS;IACL,UAAU,CAAU;IACpB,YAAY,CAAU;IAC/B,YAAY,IAAI,GAAG,UAAU,EAAE,IAAI,GAAmD,EAAE;QACtF,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,KAAK,UAAU,CAAC;QAC9D,oFAAoF;QACpF,IAAI,CAAC,GAAG,GAAG,IAAI,YAAY,CAAC,IAAI,EAAE;YAChC,cAAc,EAAE,IAAI;YACpB,gCAAgC,EAAE,IAAI;SACvC,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,+CAA+C;QACpF,0EAA0E;QAC1E,0EAA0E;QAC1E,0EAA0E;QAC1E,IAAI,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;QAC/F,IAAI,CAAC,SAAS,EAAE,CAAC;IACnB,CAAC;IAED,0FAA0F;IAC1F,4FAA4F;IAC5F,wFAAwF;IACxF,4FAA4F;IAC5F,uFAAuF;IACvF,qEAAqE;IACrE,UAAU,GAAG,CAAC,CAAC;IACf,SAAS;QACP,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,OAAO;QAC/B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;QAC3E,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QACjD,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;IACtB,CAAC;IACD,oFAAoF;IACpF,cAAc;QAGZ,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,OAAO,SAAS,CAAC;QACzC,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,KAAK,MAAM,CAAC;QACpC,IAAI,EAAU,CAAC;QACf,IAAI,CAAC;YACH,EAAE,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC;YAChC,IAAI,IAAI,GAAG,EAAE;gBAAE,OAAO,SAAS,CAAC;YAChC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YAC/B,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC/E,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1E,MAAM,SAAS,GAAG,EAAE,GAAG,QAAQ,CAAC;YAChC,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;YAC3C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAC;YAC9C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;YAC5C,IAAI,SAAS,GAAG,CAAC,CAAC;YAClB,IAAI,WAAW,GAAG,MAAM,CAAC;YACzB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACtC,OAAO,MAAM,GAAG,SAAS,IAAI,IAAI,EAAE,CAAC;gBAClC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;gBAC1C,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,KAAK;oBAAE,MAAM,CAAC,eAAe;gBAC/F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACvE,MAAM,IAAI,SAAS,CAAC;gBACpB,MAAM,MAAM,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;gBACrC,IAAI,MAAM,EAAE,CAAC;oBACX,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO;wBAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;oBAC9C,OAAO,CAAC,KAAK,EAAE,CAAC;oBAChB,SAAS,GAAG,MAAM,CAAC;oBACnB,WAAW,GAAG,MAAM,CAAC;gBACvB,CAAC;YACH,CAAC;YACD,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC;YAC9B,IAAI,CAAC,SAAS;gBACZ,OAAO;oBACL,QAAQ;oBACR,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAChE,KAAK;iBACN,CAAC;YACJ,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;gBAAE,IAAI,CAAC,GAAG,SAAS;oBAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACtE,iEAAiE;YACjE,IAAI,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;gBAClC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;gBACjD,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;YACtB,CAAC;YACD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QACxC,CAAC;gBAAS,CAAC;YACT,SAAS,CAAC,EAAE,CAAC,CAAC;QAChB,CAAC;IACH,CAAC;IACD,IAAI,CAAC,GAAW,EAAE,MAAiB;QACjC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACzE,wFAAwF;QACxF,IAAI,IAAI,GAAc,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;QACpE,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC9B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC/B,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC;QAC9B,CAAC;QACD,OAAO,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;IAC3C,CAAC;IACD,IAAI,CAAC,GAAW,EAAE,MAAiB;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACnC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAU,CAAC;QAC3C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;YAC5B,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QACnE,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAI,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAA4B,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;QAC7F,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IAC/C,CAAC;IACD,aAAa;QACX,OAAQ,IAAI,CAAC,GAA6C,CAAC,aAAa,CAAC;IAC3E,CAAC;IACD,YAAY;QACV,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAa,CAAC;QACpE,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAa,CAAC;QACnE,OAAO,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IACD,KAAK;QACH,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;IAED,yFAAyF;IACzF,QAAQ,CAAyD;IACjE,4FAA4F;IACnF,wBAAwB,GAAG,KAAK,CAAC;IAC1C,YAAY;QACV,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,QAAQ,GACX,IAAI,CAAC,GACN,CAAC,aAAa,EAAE,CAAC;IACpB,CAAC;IACD,WAAW;QACT,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;QACxB,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC1B,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,UAAU,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC;QACvB,CAAC;gBAAS,CAAC;YACT,CAAC,CAAC,KAAK,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IACD,cAAc;QACZ,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;IAC5B,CAAC;IACD,cAAc,CAAC,SAAqB;QAClC,IAAI,CAAC,SAAS,CAAC,UAAU;YAAE,OAAO;QAClC,MAAM,wBAAwB,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,GAAyE,CAAC,cAAc,CAC5F,SAAS,EACT;YACE,UAAU,EAAE,GAAG,EAAE,CAAC,wBAAwB;SAC3C,CACF,CAAC;IACJ,CAAC;IAED,2FAA2F;IAC3F,aAAa,CAAC,IAAY;QACxB,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACxC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,GAAG,CAAC,CAAC;QACjE,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,SAAS;QACP,IAAI,IAAI,CAAC,KAAK,KAAK,UAAU;YAAE,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;QACnD,wFAAwF;QACxF,iFAAiF;QACjF,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,GAAG,EAAE,EAAE,YAAY,IAAI,EAAE,CAAC,CAAC;QACvF,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,KAAK,EAAE,CAAC;YACjC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;YACjD,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,sBAAsB;QAC7C,CAAC;QACD,OAAO,IAAI,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,4FAA4F;IAC5F,KAAK;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QACzE,IAAI,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YAC1D,OAAO,IAAI,UAAU,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,oGAAoG;IACpG,OAAO,CAAC,KAAiB;QACvB,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QACjB,IAAI,IAAI,CAAC,KAAK,KAAK,UAAU;YAC3B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QAC3E,KAAK,MAAM,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChG,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,GAAG,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,gCAAgC,EAAE,IAAI,EAAE,CAAC,CAAC;QACpF,IAAI,IAAI,CAAC,UAAU;YAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;QAChG,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,wBAAwB;IAC5C,CAAC;CACF;AAED,SAAS,QAAQ,CAAC,CAAU;IAC1B,IAAI,CAAC,YAAY,WAAW;QAAE,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IACvD,IAAI,OAAO,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC;AACD,2CAA2C;AAC3C,SAAS,UAAU,CAAC,CAAU;IAC5B,IAAI,CAAC,YAAY,UAAU;QAAE,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IAC9F,OAAO,CAAC,CAAC;AACX,CAAC;AAED,sEAAsE;AACtE;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAAY,EACZ,IAAI,GAAmD,EAAE;IAEzD,OAAO,CAAC,OAAO,EAAE,EAAE,CACjB,IAAI,gBAAgB,CAClB,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EACtE,IAAI,CACL,CAAC;AACN,CAAC","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
|
+
{"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 // 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 /** 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.#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 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/** 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"]}
|
package/dist/core/storage.d.ts
CHANGED
|
@@ -56,10 +56,6 @@ export declare class DurableObjectStorage extends AsyncKvApi {
|
|
|
56
56
|
constructor(sql: SqlStorage, kv: SyncKvStorage, gate: InputGate, sync: () => Promise<void>);
|
|
57
57
|
deleteAll(): Promise<void>;
|
|
58
58
|
transactionSync<T>(fn: () => T): T;
|
|
59
|
-
/**
|
|
60
|
-
* Async transaction spanning awaits: the input gate stays closed (no other
|
|
61
|
-
* event can interleave writes into the savepoint) and auto-commit is held.
|
|
62
|
-
*/
|
|
63
59
|
transaction<T>(closure: (txn: DurableObjectTransaction) => Promise<T>): Promise<T>;
|
|
64
60
|
/** Resolves once all writes so far are durable (the output gate barrier). */
|
|
65
61
|
sync(): Promise<void>;
|
package/dist/core/storage.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { serialize } from "../v8/serialize.js";
|
|
2
|
+
import { nativeAsyncContext } from "./async-context.js";
|
|
2
3
|
import { CELLD_SCHEMA } from "./celld-schema.js";
|
|
3
4
|
/** `EXPORT` of core/handles.ts, by its registered name: importing handles.ts here is a cycle. */
|
|
4
5
|
const EXPORT = Symbol.for("cellb.export");
|
|
@@ -210,18 +211,41 @@ export class DurableObjectStorage extends AsyncKvApi {
|
|
|
210
211
|
transactionSync(fn) {
|
|
211
212
|
return this.sql.transactionSync(fn);
|
|
212
213
|
}
|
|
214
|
+
/** The last async transaction() queued: each one starts once the one before has settled. */
|
|
215
|
+
#transactions = Promise.resolve();
|
|
213
216
|
/**
|
|
214
217
|
* Async transaction spanning awaits: the input gate stays closed (no other
|
|
215
218
|
* event can interleave writes into the savepoint) and auto-commit is held.
|
|
219
|
+
*
|
|
220
|
+
* Transactions of one object run one after another, as on workerd. The gate alone does not
|
|
221
|
+
* order them: events already past it (Miniflare's D1 object awaits each request's body
|
|
222
|
+
* first) opened their savepoints into each other, and one's rollback undid the other's
|
|
223
|
+
* writes.
|
|
224
|
+
*
|
|
225
|
+
* A transaction() awaited inside another's closure nests, as on workerd, and runs at once on
|
|
226
|
+
* a savepoint of its own. Telling it apart from another event's call needs async context
|
|
227
|
+
* (AsyncLocalStorage on Node, or the engine's AsyncContext); without it, such a call waits
|
|
228
|
+
* for its parent forever: use the `txn` argument there.
|
|
216
229
|
*/
|
|
230
|
+
#txnScope = txnScope();
|
|
231
|
+
#txnDepth = 0;
|
|
217
232
|
transaction(closure) {
|
|
233
|
+
if (this.#txnScope?.get() === this)
|
|
234
|
+
return this.#transaction(closure);
|
|
235
|
+
const run = () => this.#transaction(closure);
|
|
236
|
+
const result = this.#transactions.then(run, run);
|
|
237
|
+
this.#transactions = result.catch(() => { });
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
240
|
+
#transaction(closure) {
|
|
218
241
|
return this.gate.runClosed(async () => {
|
|
219
242
|
const release = this.sql.hold();
|
|
220
|
-
const sp =
|
|
243
|
+
const sp = `_cf_atx${++this.#txnDepth}`;
|
|
221
244
|
this.sql.internalExec(`SAVEPOINT ${sp}`);
|
|
222
245
|
const txn = new DurableObjectTransaction(this.kv, this.gate);
|
|
223
246
|
try {
|
|
224
|
-
const
|
|
247
|
+
const scope = this.#txnScope;
|
|
248
|
+
const r = await (scope ? scope.run(this, () => closure(txn)) : closure(txn));
|
|
225
249
|
if (txn.rolledBack)
|
|
226
250
|
this.#rollbackTo(sp);
|
|
227
251
|
else
|
|
@@ -233,6 +257,7 @@ export class DurableObjectStorage extends AsyncKvApi {
|
|
|
233
257
|
throw e;
|
|
234
258
|
}
|
|
235
259
|
finally {
|
|
260
|
+
this.#txnDepth--;
|
|
236
261
|
release();
|
|
237
262
|
}
|
|
238
263
|
});
|
|
@@ -348,4 +373,18 @@ export class DurableObjectStorage extends AsyncKvApi {
|
|
|
348
373
|
this.onAlarmChange(null);
|
|
349
374
|
}
|
|
350
375
|
}
|
|
376
|
+
/** An async-context slot marking "inside this storage's transaction", where the platform has one. */
|
|
377
|
+
function txnScope() {
|
|
378
|
+
const hooks = globalThis.process?.getBuiltinModule?.("node:async_hooks");
|
|
379
|
+
if (hooks?.AsyncLocalStorage) {
|
|
380
|
+
const als = new hooks.AsyncLocalStorage();
|
|
381
|
+
return { get: () => als.getStore(), run: (v, fn) => als.run(v, fn) };
|
|
382
|
+
}
|
|
383
|
+
const native = nativeAsyncContext();
|
|
384
|
+
if (native) {
|
|
385
|
+
const v = new native.Variable({ name: "cellb.storage.transaction" });
|
|
386
|
+
return { get: () => v.get(), run: (value, fn) => v.run(value, fn) };
|
|
387
|
+
}
|
|
388
|
+
return undefined;
|
|
389
|
+
}
|
|
351
390
|
//# sourceMappingURL=storage.js.map
|
package/dist/core/storage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/core/storage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAajD,iGAAiG;AACjG,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAC1C,MAAM,kBAAkB,GAAG,CAAC,CAAU,EAAW,EAAE,CACjD,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAK,CAA6B,CAAC,MAAM,CAAC;IAClE,CAAC,CAAC,IAAI;IACN,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC;QAC3B,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,SAAS;YAClD,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACnF,CAAC,CAAC,CAAC,CAAC;AAEZ;;;GAGG;AACH,MAAM,OAAO,aAAa;IACxB,IAAI,CAAa;IACjB,MAAM,CAAa;IACnB,MAAM,GAAG,KAAK,CAAC;IACN,KAAK,CAAS;IACvB,yFAAyF;IACzF,SAAS,CAAqB;IAE9B,YAAY,GAAe,EAAE,KAAiB,EAAE,KAAK,GAAG,EAAE;QACxD,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE;YACtB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,qEAAqE;QAC5F,CAAC,CAAC,CAAC;IACL,CAAC;IACD,KAAK;QACH,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACxB,KAAK,MAAM,GAAG,IAAI,YAAY;YAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAC5D,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS;YAC9B,IAAI,CAAC,IAAI,CAAC,YAAY,CACpB,sEAAsE,EACtE,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAC7B,CAAC;QACJ,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IACD,GAAG,CAAc,GAAW;QAC1B,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,gDAAgD,EAAE;YACjF,IAAI,CAAC,KAAK;YACV,GAAG;SACJ,CAAC,CAAC;QACH,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,SAAS,CAAC;QACrC,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAgB,CAAC,CAAM,CAAC;IAC9E,CAAC;IACD,GAAG,CAAC,GAAW,EAAE,KAAc;QAC7B,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,2FAA2F;QAC3F,qFAAqF;QACrF,IAAI,CAAC;YACH,eAAe,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,sFAAsF;YACtF,kFAAkF;YAClF,IAAI,CAAC;gBACH,SAAS,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;YACvC,CAAC;YAAC,OAAO,EAAE,EAAE,CAAC;gBACZ,MAAM,IAAI,SAAS,CAAE,EAAY,CAAC,OAAO,CAAC,CAAC;YAC7C,CAAC;YACD,qFAAqF;YACrF,MAAM,IAAI,SAAS,CAChB,CAAW,CAAC,OAAO,CAAC,OAAO,CAAC,yCAAyC,EAAE,EAAE,CAAC,CAC5E,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,8DAA8D,EAAE;YACrF,IAAI,CAAC,KAAK;YACV,GAAG;YACH,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;SAC1B,CAAC,CAAC;IACL,CAAC;IACD,MAAM,CAAC,GAAW;QAChB,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,OAAO,CACL,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,8CAA8C,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;aACtF,WAAW,GAAG,CAAC,CACnB,CAAC;IACJ,CAAC;IACD;;;OAGG;IACH,IAAI,CAAc,IAAI,GAAgB,EAAE;QACtC,MAAM,UAAU,GAAG,EAAE,IAAI,CAAC,eAAe,CAAC;QAC1C,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,IAAI,UAAU,KAAK,IAAI,CAAC,eAAe;gBACrC,MAAM,IAAI,KAAK,CACb,kFAAkF;oBAChF,kDAAkD,CACrD,CAAC;QACN,CAAC,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAI,IAAI,CAAC,CAAC;QACjC,OAAO,CAAC,QAAQ,CAAC;YACf,IAAI,EAAE,CAAC;YACP,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,GAAG,CAAC;gBACV,IAAI,EAAE,CAAC;YACT,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;IACP,CAAC;IACD,eAAe,GAAG,CAAC,CAAC;IACpB,CAAC,KAAK,CAAI,IAAiB;QACzB,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,MAAM,KAAK,GAAa,CAAC,WAAW,CAAC,CAAC;QACtC,MAAM,MAAM,GAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5E,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACrF,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvE,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;YAC3B,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAClF,IAAI,CAAC,GAAG,yBAAyB,CAAC;QAClC,CAAC,IAAI,UAAU,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,IAAI,eAAe,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;QACpD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,CAAC,CAAC,IAAI,UAAU,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzE,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI;YACzD,MAAM,CAAC,CAAW,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,CAAgB,CAAC,CAAM,CAAC,CAAC;IACnF,CAAC;IACD,SAAS;QACP,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,oCAAoC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7E,CAAC;CACF;AAED,+EAA+E;AAC/E,MAAM,OAAO,UAAU;IACX,EAAE,CAAgB;IAClB,IAAI,CAAY;IAC1B,YAAY,EAAiB,EAAE,IAAe;QAC5C,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IACD,8FAA8F;IACpF,EAAE,CAAI,EAAW;QACzB,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;YACpC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;YACxB,OAAO,EAAE,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC;IAGD,GAAG,CAAC,SAA4B;QAC9B,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE;YAClB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;gBAAE,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC7D,SAAS,CAAC,SAAS,CAAC,CAAC;YACrB,MAAM,CAAC,GAAG,IAAI,GAAG,EAAmB,CAAC;YACrC,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;gBACtC,MAAM,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBACzB,IAAI,CAAC,KAAK,SAAS;oBAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACnC,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,CAAC;IACL,CAAC;IAGD,GAAG,CAAC,YAA8C,EAAE,KAAe;QACjE,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE;YAClB,IAAI,OAAO,YAAY,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;YAC9E,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAC7C,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACnC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO;gBAAE,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC;IAGD,MAAM,CAAC,SAA4B;QACjC,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE;YAClB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;gBAAE,OAAO,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAChE,SAAS,CAAC,SAAS,CAAC,CAAC;YACrB,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAc,IAAkB;QAClC,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAI,IAAI,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC;CACF;AAED,qFAAqF;AACrF,SAAS,SAAS,CAAC,KAAe,IAAS,CAAC;AAE5C,MAAM,OAAO,wBAAyB,SAAQ,UAAU;IACtD,UAAU,GAAG,KAAK,CAAC;IACnB,QAAQ;QACN,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;CACF;AAED,uDAAuD;AACvD,MAAM,OAAO,oBAAqB,SAAQ,UAAU;IACzC,GAAG,CAAa;IAChB,EAAE,CAAgB;IAC3B,KAAK,CAAsB;IAE3B,YAAY,GAAe,EAAE,EAAiB,EAAE,IAAe,EAAE,IAAyB;QACxF,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAChB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE;YACtB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QAC1B,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IACD,SAAS;QACP,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE;YAClB,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC;YACpB,6FAA6F;YAC7F,IAAI,CAAC,IAAI,CAAC,uBAAuB;gBAAE,IAAI,CAAC,cAAc,EAAE,CAAC;YACzD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAClC,wIAAwI,CACzI,CAAC,IAAI,CAAC;YACP,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM;gBACzB,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,yBAAyB,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACxF,CAAC,CAAC,CAAC;IACL,CAAC;IACD,eAAe,CAAI,EAAW;QAC5B,OAAO,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IACtC,CAAC;IACD;;;OAGG;IACH,WAAW,CAAI,OAAsD;QACnE,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;YACpC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YAChC,MAAM,EAAE,GAAG,SAAS,CAAC;YACrB,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;YACzC,MAAM,GAAG,GAAG,IAAI,wBAAwB,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7D,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;gBAC7B,IAAI,GAAG,CAAC,UAAU;oBAAE,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;;oBACpC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;gBAC5C,OAAO,CAAC,CAAC;YACX,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;gBACrB,MAAM,CAAC,CAAC;YACV,CAAC;oBAAS,CAAC;gBACT,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IACD,WAAW,CAAC,EAAU;QACpB,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACvC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU;YAAE,CAAC,EAAE,CAAC,CAAC,oCAAoC;IAChF,CAAC;IACD,6EAA6E;IAC7E,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IACD,2EAA2E;IAC3E,uBAAuB,GAAG,KAAK,CAAC;IAChC,8FAA8F;IAC9F,IAAI,MAAM;QACR,OAAO,IAAI,CAAC;IACd,CAAC;IACD,2EAA2E;IAC3E,aAAa,GAAgC,GAAG,EAAE,GAAE,CAAC,CAAC;IAEtD,UAAU,GAAG,KAAK,CAAC;IACnB,KAAK;QACH,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO;QAC5B,KAAK,MAAM,GAAG,IAAI,YAAY;YAAE,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAC3D,IAAI,IAAI,CAAC,EAAE,CAAC,SAAS,KAAK,SAAS;YACjC,IAAI,CAAC,GAAG,CAAC,YAAY,CACnB,sEAAsE,EACtE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,CACnC,CAAC;QACJ,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;IACD;;;OAGG;IACH,YAAY;QACV,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY;QAC7B,4EAA4E;QAC5E,6FAA6F,EAC7F,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAChB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACV,OAAO,CAAC;YACN,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;YAC5F,CAAC,CAAC,IAAI,CAAC;IACX,CAAC;IACD,0FAA0F;IAC1F,OAAO,CAAqC;IAC5C,UAAU,CAAC,GAA2B;QACpC,IAAI,CAAC,OAAO,GAAG,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC;IAChD,CAAC;IACD;;;;OAIG;IACH,WAAW,CACT,KAAyC,EACzC,SAAkB,EAClB,GAAW;QAEX,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAChC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU;YAAE,OAAO,GAAG,EAAE,EAAE,IAAI,IAAI,CAAC;QACxE,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,qDAAqD,EAAE;gBAC3E,IAAI,CAAC,EAAE,CAAC,KAAK;gBACb,KAAK,CAAC,EAAE;aACT,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,uCAAuC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;QAClF,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,GAAG,GAAG,GAAG,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAClE,IAAI,CAAC,GAAG,CAAC,YAAY,CACnB,sGAAsG,EACtG,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CACpB,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,EAAE,EAAE,IAAI,IAAI,CAAC;QAC9C,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,gGAAgG;IAChG,SAAS;QACP,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAChC,IAAI,GAAG,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,KAAK,GAAG,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QACnF,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7B,CAAC;IACD,6FAA6F;IAC7F,QAAQ,CAAC,KAAe;QACtB,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,QAAQ,CAAC,aAA4B,EAAE,KAAe;QACpD,sFAAsF;QACtF,MAAM,CAAC,GAAG,aAAa,YAAY,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAC1F,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE;YAClB,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,YAAY;YACnB,6DAA6D;YAC7D,iMAAiM,EACjM,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CACpB,CAAC;YACF,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IACD,yEAAyE;IACzE,YAAY,CAAC,EAAU;QACrB,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,CAAC,YAAY,CACnB,iMAAiM,EACjM,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CACpB,CAAC;QACF,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC;IACD,WAAW,CAAC,KAAe;QACzB,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,cAAc;QACZ,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,uCAAuC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;QAChF,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;CACF","sourcesContent":["import type { ValueCodec } from \"../ports.js\";\nimport { serialize } from \"../v8/serialize.js\";\nimport { CELLD_SCHEMA } from \"./celld-schema.js\";\nimport type { InputGate } from \"./gates.js\";\nimport type { SqlStorage } from \"./sql-storage.js\";\n\nexport interface ListOptions {\n start?: string;\n startAfter?: string;\n end?: string;\n prefix?: string;\n reverse?: boolean;\n limit?: number;\n}\n\n/** `EXPORT` of core/handles.ts, by its registered name: importing handles.ts here is a cycle. */\nconst EXPORT = Symbol.for(\"cellb.export\");\nconst withoutStoredStubs = (v: unknown): unknown =>\n v && typeof v === \"object\" && (v as Record<symbol, unknown>)[EXPORT]\n ? null\n : Array.isArray(v)\n ? v.map(withoutStoredStubs)\n : v && Object.getPrototypeOf(v) === Object.prototype\n ? Object.fromEntries(Object.entries(v).map(([k, x]) => [k, withoutStoredStubs(x)]))\n : v;\n\n/**\n * Synchronous KV API of SQLite-backed objects (`ctx.storage.kv`), stored as celld stores it:\n * `_cf_KV(scope, k, v)` with the cell's scope and V8-serialized values (celld-schema.ts).\n */\nexport class SyncKvStorage {\n #sql: SqlStorage;\n #codec: ValueCodec;\n #ready = false;\n readonly scope: string;\n /** The name the object was addressed by: recorded as celld's _cf_METADATA.actor_name. */\n actorName: string | undefined;\n\n constructor(sql: SqlStorage, codec: ValueCodec, scope = \"\") {\n this.#sql = sql;\n this.#codec = codec;\n this.scope = scope;\n sql.rolledBack.add(() => {\n this.#ready = false; // the table may have been created inside the rolled-back transaction\n });\n }\n #init(): void {\n if (this.#ready) return;\n for (const ddl of CELLD_SCHEMA) this.#sql.internalExec(ddl);\n if (this.actorName !== undefined)\n this.#sql.internalExec(\n \"INSERT OR IGNORE INTO _cf_METADATA (scope, actor_name) VALUES (?, ?)\",\n [this.scope, this.actorName],\n );\n this.#ready = true;\n }\n get<T = unknown>(key: string): T | undefined {\n this.#init();\n const r = this.#sql.internalExec(\"SELECT v FROM _cf_KV WHERE scope = ? AND k = ?\", [\n this.scope,\n key,\n ]);\n if (!r.rows.length) return undefined;\n return this.#codec.decode(new Uint8Array(r.rows[0][0] as ArrayBuffer)) as T;\n }\n put(key: string, value: unknown): void {\n this.#init();\n // As celld: `undefined` is a storable value; what structured clone refuses is a TypeError.\n // ctx.exports.X({ props }) stubs are left to the codec, which stores them (workerd).\n try {\n structuredClone(withoutStoredStubs(value));\n } catch (e) {\n // Worded as V8 (workerd, celld) words it, by cellb's V8 serializer: SpiderMonkey says\n // \"Function object could not be cloned.\" for V8's \"() => 1 could not be cloned.\".\n try {\n serialize(withoutStoredStubs(value));\n } catch (v8) {\n throw new TypeError((v8 as Error).message);\n }\n // Browsers prefix the engine message (\"Failed to execute 'structuredClone' on …: \").\n throw new TypeError(\n (e as Error).message.replace(/^Failed to execute '[^']+' on '[^']+': /, \"\"),\n );\n }\n this.#sql.internalExec(\"INSERT OR REPLACE INTO _cf_KV (scope, k, v) VALUES (?, ?, ?)\", [\n this.scope,\n key,\n this.#codec.encode(value),\n ]);\n }\n delete(key: string): boolean {\n this.#init();\n return (\n this.#sql.internalExec(\"DELETE FROM _cf_KV WHERE scope = ? AND k = ?\", [this.scope, key])\n .rowsWritten > 0\n );\n }\n /**\n * Only one list() iterator is live at a time, as in workerd: a new call invalidates the\n * previous one, which throws on its next step.\n */\n list<T = unknown>(opts: ListOptions = {}): IterableIterator<[string, T]> {\n const generation = ++this.#listGeneration;\n const live = () => {\n if (generation !== this.#listGeneration)\n throw new Error(\n \"kv.list() iterator was invalidated because a new call to kv.list() was started. \" +\n \"Only one kv.list() iterator can exist at a time.\",\n );\n };\n const rows = this.#rows<T>(opts);\n return (function* () {\n live();\n for (const row of rows) {\n yield row;\n live();\n }\n })();\n }\n #listGeneration = 0;\n *#rows<T>(opts: ListOptions): IterableIterator<[string, T]> {\n this.#init();\n const where: string[] = [\"scope = ?\"];\n const params: unknown[] = [this.scope];\n if (opts.start !== undefined) where.push(\"k >= ?\"), params.push(opts.start);\n if (opts.startAfter !== undefined) where.push(\"k > ?\"), params.push(opts.startAfter);\n if (opts.end !== undefined) where.push(\"k < ?\"), params.push(opts.end);\n if (opts.prefix !== undefined)\n where.push(\"substr(k, 1, ?) = ?\"), params.push(opts.prefix.length, opts.prefix);\n let q = \"SELECT k, v FROM _cf_KV\";\n q += ` WHERE ${where.join(\" AND \")}`;\n q += ` ORDER BY k ${opts.reverse ? \"DESC\" : \"ASC\"}`;\n if (opts.limit !== undefined) (q += \" LIMIT ?\"), params.push(opts.limit);\n for (const [k, v] of this.#sql.internalExec(q, params).rows)\n yield [k as string, this.#codec.decode(new Uint8Array(v as ArrayBuffer)) as T];\n }\n deleteAll(): void {\n this.#init();\n this.#sql.internalExec(\"DELETE FROM _cf_KV WHERE scope = ?\", [this.scope]);\n }\n}\n\n/** Methods shared by `ctx.storage` and the `txn` object of `transaction()`. */\nexport class AsyncKvApi {\n protected kv: SyncKvStorage;\n protected gate: InputGate;\n constructor(kv: SyncKvStorage, gate: InputGate) {\n this.kv = kv;\n this.gate = gate;\n }\n /** Every async storage op closes the input gate until it (and its continuation) completes. */\n protected op<T>(fn: () => T): Promise<T> {\n return this.gate.runClosed(async () => {\n await Promise.resolve();\n return fn();\n });\n }\n get<T = unknown>(key: string): Promise<T | undefined>;\n get<T = unknown>(keys: string[]): Promise<Map<string, T>>;\n get(keyOrKeys: string | string[]): Promise<unknown> {\n return this.op(() => {\n if (!Array.isArray(keyOrKeys)) return this.kv.get(keyOrKeys);\n checkKeys(keyOrKeys);\n const m = new Map<string, unknown>();\n for (const k of [...keyOrKeys].sort()) {\n const v = this.kv.get(k);\n if (v !== undefined) m.set(k, v);\n }\n return m;\n });\n }\n put(key: string, value: unknown): Promise<void>;\n put(entries: Record<string, unknown>): Promise<void>;\n put(keyOrEntries: string | Record<string, unknown>, value?: unknown): Promise<void> {\n return this.op(() => {\n if (typeof keyOrEntries === \"string\") return this.kv.put(keyOrEntries, value);\n const entries = Object.entries(keyOrEntries);\n checkKeys(entries.map(([k]) => k));\n for (const [k, v] of entries) this.kv.put(k, v);\n });\n }\n delete(key: string): Promise<boolean>;\n delete(keys: string[]): Promise<number>;\n delete(keyOrKeys: string | string[]): Promise<boolean | number> {\n return this.op(() => {\n if (!Array.isArray(keyOrKeys)) return this.kv.delete(keyOrKeys);\n checkKeys(keyOrKeys);\n return keyOrKeys.filter((k) => this.kv.delete(k)).length;\n });\n }\n list<T = unknown>(opts?: ListOptions): Promise<Map<string, T>> {\n return this.op(() => new Map(this.kv.list<T>(opts)));\n }\n}\n\n// celld sets no limit on the number of keys of one get/put/delete (storage-details).\nfunction checkKeys(_keys: string[]): void {}\n\nexport class DurableObjectTransaction extends AsyncKvApi {\n rolledBack = false;\n rollback(): void {\n this.rolledBack = true;\n }\n}\n\n/** `ctx.storage` of a SQLite-backed Durable Object. */\nexport class DurableObjectStorage extends AsyncKvApi {\n readonly sql: SqlStorage;\n readonly kv: SyncKvStorage;\n #sync: () => Promise<void>;\n\n constructor(sql: SqlStorage, kv: SyncKvStorage, gate: InputGate, sync: () => Promise<void>) {\n super(kv, gate);\n this.sql = sql;\n sql.rolledBack.add(() => {\n this.#metaReady = false;\n });\n this.kv = kv;\n this.#sync = sync;\n }\n deleteAll(): Promise<void> {\n return this.op(() => {\n this.kv.deleteAll();\n // deleteAll() also deletes the alarm, as on Cloudflare, unless `delete_all_preserves_alarm`.\n if (!this.deleteAllPreservesAlarm) this.clearAlarmSync();\n const tables = this.sql.internalExec(\n \"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE '\\\\_cf\\\\_%' ESCAPE '\\\\' AND name NOT LIKE 'sqlite\\\\_%' ESCAPE '\\\\'\",\n ).rows;\n for (const [name] of tables)\n this.sql.internalExec(`DROP TABLE IF EXISTS \"${String(name).replace(/\"/g, '\"\"')}\"`);\n });\n }\n transactionSync<T>(fn: () => T): T {\n return this.sql.transactionSync(fn);\n }\n /**\n * Async transaction spanning awaits: the input gate stays closed (no other\n * event can interleave writes into the savepoint) and auto-commit is held.\n */\n transaction<T>(closure: (txn: DurableObjectTransaction) => Promise<T>): Promise<T> {\n return this.gate.runClosed(async () => {\n const release = this.sql.hold();\n const sp = \"_cf_atx\";\n this.sql.internalExec(`SAVEPOINT ${sp}`);\n const txn = new DurableObjectTransaction(this.kv, this.gate);\n try {\n const r = await closure(txn);\n if (txn.rolledBack) this.#rollbackTo(sp);\n else this.sql.internalExec(`RELEASE ${sp}`);\n return r;\n } catch (e) {\n this.#rollbackTo(sp);\n throw e;\n } finally {\n release();\n }\n });\n }\n #rollbackTo(sp: string): void {\n this.sql.internalExec(`ROLLBACK TO ${sp}`);\n this.sql.internalExec(`RELEASE ${sp}`);\n for (const f of this.sql.rolledBack) f(); // tables created inside may be gone\n }\n /** Resolves once all writes so far are durable (the output gate barrier). */\n sync(): Promise<void> {\n return this.#sync();\n }\n /** `delete_all_preserves_alarm`: deleteAll() leaves the alarm in place. */\n deleteAllPreservesAlarm = false;\n /** celld's harness hands its storage \"scope\" to engine ops; here it is the storage itself. */\n get _scope(): this {\n return this;\n }\n /** Called whenever the stored alarm changes (the runtime schedules it). */\n onAlarmChange: (at: number | null) => void = () => {};\n\n #metaReady = false;\n #meta(): void {\n if (this.#metaReady) return;\n for (const ddl of CELLD_SCHEMA) this.sql.internalExec(ddl);\n if (this.kv.actorName !== undefined)\n this.sql.internalExec(\n \"INSERT OR IGNORE INTO _cf_METADATA (scope, actor_name) VALUES (?, ?)\",\n [this.kv.scope, this.kv.actorName],\n );\n this.#metaReady = true;\n }\n /**\n * The alarm row as celld keeps it (storage.rs): due time, failure counters, and a random\n * generation that changes with every setAlarm() — so a handler's own change is detected.\n */\n alarmRowSync(): { at: number; retry: number; counted: number; generation: string } | null {\n this.#meta();\n const r = this.sql.internalExec(\n // generation is a 64-bit random(): read as text (beyond JS's safe integers)\n \"SELECT at_ms, retry, counted_retry, CAST(generation AS TEXT) FROM _cf_ALARM WHERE scope = ?\",\n [this.kv.scope],\n ).rows[0];\n return r\n ? { at: Number(r[0]), retry: Number(r[1]), counted: Number(r[2]), generation: String(r[3]) }\n : null;\n }\n /** The alarm being handled: getAlarm() reads null until the handler changes the alarm. */\n #active: { generation: string } | undefined;\n beginAlarm(row: { generation: string }): void {\n this.#active = { generation: row.generation };\n }\n /**\n * After the handler (celld's finish_alarm_handler): unless the handler changed the alarm,\n * success deletes it and failure reschedules it with backoff (2 s << min(retry, 6)) —\n * abandoned after 6 counted failures. Returns the alarm now stored.\n */\n finishAlarm(\n fired: { at: number; generation: string },\n succeeded: boolean,\n now: number,\n ): number | null {\n this.#active = undefined;\n const cur = this.alarmRowSync();\n if (!cur || cur.generation !== fired.generation) return cur?.at ?? null;\n if (succeeded) {\n this.sql.internalExec(\"DELETE FROM _cf_ALARM WHERE scope = ? AND at_ms = ?\", [\n this.kv.scope,\n fired.at,\n ]);\n } else if (cur.counted >= 6) {\n this.sql.internalExec(\"DELETE FROM _cf_ALARM WHERE scope = ?\", [this.kv.scope]);\n } else {\n const at = now + 2_000 * 2 ** Math.min(Math.max(cur.retry, 0), 6);\n this.sql.internalExec(\n \"UPDATE _cf_ALARM SET at_ms = ?, retry = retry + 1, counted_retry = counted_retry + 1 WHERE scope = ?\",\n [at, this.kv.scope],\n );\n }\n const after = this.alarmRowSync()?.at ?? null;\n this.onAlarmChange(after);\n return after;\n }\n /** Synchronous read of the stored alarm (ms since epoch) or null (null while it is handled). */\n alarmSync(): number | null {\n const row = this.alarmRowSync();\n if (row && this.#active && this.#active.generation === row.generation) return null;\n return row ? row.at : null;\n }\n /** One alarm per object, in celld's `_cf_ALARM` (same transaction as the event's writes). */\n getAlarm(_opts?: unknown): Promise<number | null> {\n return this.op(() => this.alarmSync());\n }\n setAlarm(scheduledTime: number | Date, _opts?: unknown): Promise<void> {\n // As celld: the time is coerced to a number and a non-number becomes 0 (due at once).\n const n = scheduledTime instanceof Date ? scheduledTime.getTime() : Number(scheduledTime);\n const at = Number.isNaN(n) ? 0 : n;\n return this.op(() => {\n this.#meta();\n this.sql.internalExec(\n // celld's statement: counters reset, a new random generation\n \"INSERT INTO _cf_ALARM(scope,at_ms,retry,counted_retry,generation) VALUES(?,?,0,0,random()) ON CONFLICT(scope) DO UPDATE SET at_ms=excluded.at_ms, retry=0, counted_retry=0, generation=random()\",\n [this.kv.scope, at],\n );\n this.onAlarmChange(at);\n });\n }\n /** setAlarm() inside a synchronous transaction (celld's harness ops). */\n setAlarmSync(at: number): void {\n this.#meta();\n this.sql.internalExec(\n \"INSERT INTO _cf_ALARM(scope,at_ms,retry,counted_retry,generation) VALUES(?,?,0,0,random()) ON CONFLICT(scope) DO UPDATE SET at_ms=excluded.at_ms, retry=0, counted_retry=0, generation=random()\",\n [this.kv.scope, at],\n );\n this.onAlarmChange(at);\n }\n deleteAlarm(_opts?: unknown): Promise<void> {\n return this.op(() => this.clearAlarmSync());\n }\n clearAlarmSync(): void {\n this.#meta();\n this.sql.internalExec(\"DELETE FROM _cf_ALARM WHERE scope = ?\", [this.kv.scope]);\n this.onAlarmChange(null);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/core/storage.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ValueCodec } from \"../ports.js\";\nimport { serialize } from \"../v8/serialize.js\";\nimport { nativeAsyncContext } from \"./async-context.js\";\nimport { CELLD_SCHEMA } from \"./celld-schema.js\";\nimport type { InputGate } from \"./gates.js\";\nimport type { SqlStorage } from \"./sql-storage.js\";\n\nexport interface ListOptions {\n start?: string;\n startAfter?: string;\n end?: string;\n prefix?: string;\n reverse?: boolean;\n limit?: number;\n}\n\n/** `EXPORT` of core/handles.ts, by its registered name: importing handles.ts here is a cycle. */\nconst EXPORT = Symbol.for(\"cellb.export\");\nconst withoutStoredStubs = (v: unknown): unknown =>\n v && typeof v === \"object\" && (v as Record<symbol, unknown>)[EXPORT]\n ? null\n : Array.isArray(v)\n ? v.map(withoutStoredStubs)\n : v && Object.getPrototypeOf(v) === Object.prototype\n ? Object.fromEntries(Object.entries(v).map(([k, x]) => [k, withoutStoredStubs(x)]))\n : v;\n\n/**\n * Synchronous KV API of SQLite-backed objects (`ctx.storage.kv`), stored as celld stores it:\n * `_cf_KV(scope, k, v)` with the cell's scope and V8-serialized values (celld-schema.ts).\n */\nexport class SyncKvStorage {\n #sql: SqlStorage;\n #codec: ValueCodec;\n #ready = false;\n readonly scope: string;\n /** The name the object was addressed by: recorded as celld's _cf_METADATA.actor_name. */\n actorName: string | undefined;\n\n constructor(sql: SqlStorage, codec: ValueCodec, scope = \"\") {\n this.#sql = sql;\n this.#codec = codec;\n this.scope = scope;\n sql.rolledBack.add(() => {\n this.#ready = false; // the table may have been created inside the rolled-back transaction\n });\n }\n #init(): void {\n if (this.#ready) return;\n for (const ddl of CELLD_SCHEMA) this.#sql.internalExec(ddl);\n if (this.actorName !== undefined)\n this.#sql.internalExec(\n \"INSERT OR IGNORE INTO _cf_METADATA (scope, actor_name) VALUES (?, ?)\",\n [this.scope, this.actorName],\n );\n this.#ready = true;\n }\n get<T = unknown>(key: string): T | undefined {\n this.#init();\n const r = this.#sql.internalExec(\"SELECT v FROM _cf_KV WHERE scope = ? AND k = ?\", [\n this.scope,\n key,\n ]);\n if (!r.rows.length) return undefined;\n return this.#codec.decode(new Uint8Array(r.rows[0][0] as ArrayBuffer)) as T;\n }\n put(key: string, value: unknown): void {\n this.#init();\n // As celld: `undefined` is a storable value; what structured clone refuses is a TypeError.\n // ctx.exports.X({ props }) stubs are left to the codec, which stores them (workerd).\n try {\n structuredClone(withoutStoredStubs(value));\n } catch (e) {\n // Worded as V8 (workerd, celld) words it, by cellb's V8 serializer: SpiderMonkey says\n // \"Function object could not be cloned.\" for V8's \"() => 1 could not be cloned.\".\n try {\n serialize(withoutStoredStubs(value));\n } catch (v8) {\n throw new TypeError((v8 as Error).message);\n }\n // Browsers prefix the engine message (\"Failed to execute 'structuredClone' on …: \").\n throw new TypeError(\n (e as Error).message.replace(/^Failed to execute '[^']+' on '[^']+': /, \"\"),\n );\n }\n this.#sql.internalExec(\"INSERT OR REPLACE INTO _cf_KV (scope, k, v) VALUES (?, ?, ?)\", [\n this.scope,\n key,\n this.#codec.encode(value),\n ]);\n }\n delete(key: string): boolean {\n this.#init();\n return (\n this.#sql.internalExec(\"DELETE FROM _cf_KV WHERE scope = ? AND k = ?\", [this.scope, key])\n .rowsWritten > 0\n );\n }\n /**\n * Only one list() iterator is live at a time, as in workerd: a new call invalidates the\n * previous one, which throws on its next step.\n */\n list<T = unknown>(opts: ListOptions = {}): IterableIterator<[string, T]> {\n const generation = ++this.#listGeneration;\n const live = () => {\n if (generation !== this.#listGeneration)\n throw new Error(\n \"kv.list() iterator was invalidated because a new call to kv.list() was started. \" +\n \"Only one kv.list() iterator can exist at a time.\",\n );\n };\n const rows = this.#rows<T>(opts);\n return (function* () {\n live();\n for (const row of rows) {\n yield row;\n live();\n }\n })();\n }\n #listGeneration = 0;\n *#rows<T>(opts: ListOptions): IterableIterator<[string, T]> {\n this.#init();\n const where: string[] = [\"scope = ?\"];\n const params: unknown[] = [this.scope];\n if (opts.start !== undefined) where.push(\"k >= ?\"), params.push(opts.start);\n if (opts.startAfter !== undefined) where.push(\"k > ?\"), params.push(opts.startAfter);\n if (opts.end !== undefined) where.push(\"k < ?\"), params.push(opts.end);\n if (opts.prefix !== undefined)\n where.push(\"substr(k, 1, ?) = ?\"), params.push(opts.prefix.length, opts.prefix);\n let q = \"SELECT k, v FROM _cf_KV\";\n q += ` WHERE ${where.join(\" AND \")}`;\n q += ` ORDER BY k ${opts.reverse ? \"DESC\" : \"ASC\"}`;\n if (opts.limit !== undefined) (q += \" LIMIT ?\"), params.push(opts.limit);\n for (const [k, v] of this.#sql.internalExec(q, params).rows)\n yield [k as string, this.#codec.decode(new Uint8Array(v as ArrayBuffer)) as T];\n }\n deleteAll(): void {\n this.#init();\n this.#sql.internalExec(\"DELETE FROM _cf_KV WHERE scope = ?\", [this.scope]);\n }\n}\n\n/** Methods shared by `ctx.storage` and the `txn` object of `transaction()`. */\nexport class AsyncKvApi {\n protected kv: SyncKvStorage;\n protected gate: InputGate;\n constructor(kv: SyncKvStorage, gate: InputGate) {\n this.kv = kv;\n this.gate = gate;\n }\n /** Every async storage op closes the input gate until it (and its continuation) completes. */\n protected op<T>(fn: () => T): Promise<T> {\n return this.gate.runClosed(async () => {\n await Promise.resolve();\n return fn();\n });\n }\n get<T = unknown>(key: string): Promise<T | undefined>;\n get<T = unknown>(keys: string[]): Promise<Map<string, T>>;\n get(keyOrKeys: string | string[]): Promise<unknown> {\n return this.op(() => {\n if (!Array.isArray(keyOrKeys)) return this.kv.get(keyOrKeys);\n checkKeys(keyOrKeys);\n const m = new Map<string, unknown>();\n for (const k of [...keyOrKeys].sort()) {\n const v = this.kv.get(k);\n if (v !== undefined) m.set(k, v);\n }\n return m;\n });\n }\n put(key: string, value: unknown): Promise<void>;\n put(entries: Record<string, unknown>): Promise<void>;\n put(keyOrEntries: string | Record<string, unknown>, value?: unknown): Promise<void> {\n return this.op(() => {\n if (typeof keyOrEntries === \"string\") return this.kv.put(keyOrEntries, value);\n const entries = Object.entries(keyOrEntries);\n checkKeys(entries.map(([k]) => k));\n for (const [k, v] of entries) this.kv.put(k, v);\n });\n }\n delete(key: string): Promise<boolean>;\n delete(keys: string[]): Promise<number>;\n delete(keyOrKeys: string | string[]): Promise<boolean | number> {\n return this.op(() => {\n if (!Array.isArray(keyOrKeys)) return this.kv.delete(keyOrKeys);\n checkKeys(keyOrKeys);\n return keyOrKeys.filter((k) => this.kv.delete(k)).length;\n });\n }\n list<T = unknown>(opts?: ListOptions): Promise<Map<string, T>> {\n return this.op(() => new Map(this.kv.list<T>(opts)));\n }\n}\n\n// celld sets no limit on the number of keys of one get/put/delete (storage-details).\nfunction checkKeys(_keys: string[]): void {}\n\nexport class DurableObjectTransaction extends AsyncKvApi {\n rolledBack = false;\n rollback(): void {\n this.rolledBack = true;\n }\n}\n\n/** `ctx.storage` of a SQLite-backed Durable Object. */\nexport class DurableObjectStorage extends AsyncKvApi {\n readonly sql: SqlStorage;\n readonly kv: SyncKvStorage;\n #sync: () => Promise<void>;\n\n constructor(sql: SqlStorage, kv: SyncKvStorage, gate: InputGate, sync: () => Promise<void>) {\n super(kv, gate);\n this.sql = sql;\n sql.rolledBack.add(() => {\n this.#metaReady = false;\n });\n this.kv = kv;\n this.#sync = sync;\n }\n deleteAll(): Promise<void> {\n return this.op(() => {\n this.kv.deleteAll();\n // deleteAll() also deletes the alarm, as on Cloudflare, unless `delete_all_preserves_alarm`.\n if (!this.deleteAllPreservesAlarm) this.clearAlarmSync();\n const tables = this.sql.internalExec(\n \"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE '\\\\_cf\\\\_%' ESCAPE '\\\\' AND name NOT LIKE 'sqlite\\\\_%' ESCAPE '\\\\'\",\n ).rows;\n for (const [name] of tables)\n this.sql.internalExec(`DROP TABLE IF EXISTS \"${String(name).replace(/\"/g, '\"\"')}\"`);\n });\n }\n transactionSync<T>(fn: () => T): T {\n return this.sql.transactionSync(fn);\n }\n /** The last async transaction() queued: each one starts once the one before has settled. */\n #transactions: Promise<unknown> = Promise.resolve();\n /**\n * Async transaction spanning awaits: the input gate stays closed (no other\n * event can interleave writes into the savepoint) and auto-commit is held.\n *\n * Transactions of one object run one after another, as on workerd. The gate alone does not\n * order them: events already past it (Miniflare's D1 object awaits each request's body\n * first) opened their savepoints into each other, and one's rollback undid the other's\n * writes.\n *\n * A transaction() awaited inside another's closure nests, as on workerd, and runs at once on\n * a savepoint of its own. Telling it apart from another event's call needs async context\n * (AsyncLocalStorage on Node, or the engine's AsyncContext); without it, such a call waits\n * for its parent forever: use the `txn` argument there.\n */\n #txnScope = txnScope();\n #txnDepth = 0;\n transaction<T>(closure: (txn: DurableObjectTransaction) => Promise<T>): Promise<T> {\n if (this.#txnScope?.get() === this) return this.#transaction(closure);\n const run = () => this.#transaction(closure);\n const result = this.#transactions.then(run, run);\n this.#transactions = result.catch(() => {});\n return result;\n }\n #transaction<T>(closure: (txn: DurableObjectTransaction) => Promise<T>): Promise<T> {\n return this.gate.runClosed(async () => {\n const release = this.sql.hold();\n const sp = `_cf_atx${++this.#txnDepth}`;\n this.sql.internalExec(`SAVEPOINT ${sp}`);\n const txn = new DurableObjectTransaction(this.kv, this.gate);\n try {\n const scope = this.#txnScope;\n const r = await (scope ? scope.run(this, () => closure(txn)) : closure(txn));\n if (txn.rolledBack) this.#rollbackTo(sp);\n else this.sql.internalExec(`RELEASE ${sp}`);\n return r;\n } catch (e) {\n this.#rollbackTo(sp);\n throw e;\n } finally {\n this.#txnDepth--;\n release();\n }\n });\n }\n #rollbackTo(sp: string): void {\n this.sql.internalExec(`ROLLBACK TO ${sp}`);\n this.sql.internalExec(`RELEASE ${sp}`);\n for (const f of this.sql.rolledBack) f(); // tables created inside may be gone\n }\n /** Resolves once all writes so far are durable (the output gate barrier). */\n sync(): Promise<void> {\n return this.#sync();\n }\n /** `delete_all_preserves_alarm`: deleteAll() leaves the alarm in place. */\n deleteAllPreservesAlarm = false;\n /** celld's harness hands its storage \"scope\" to engine ops; here it is the storage itself. */\n get _scope(): this {\n return this;\n }\n /** Called whenever the stored alarm changes (the runtime schedules it). */\n onAlarmChange: (at: number | null) => void = () => {};\n\n #metaReady = false;\n #meta(): void {\n if (this.#metaReady) return;\n for (const ddl of CELLD_SCHEMA) this.sql.internalExec(ddl);\n if (this.kv.actorName !== undefined)\n this.sql.internalExec(\n \"INSERT OR IGNORE INTO _cf_METADATA (scope, actor_name) VALUES (?, ?)\",\n [this.kv.scope, this.kv.actorName],\n );\n this.#metaReady = true;\n }\n /**\n * The alarm row as celld keeps it (storage.rs): due time, failure counters, and a random\n * generation that changes with every setAlarm() — so a handler's own change is detected.\n */\n alarmRowSync(): { at: number; retry: number; counted: number; generation: string } | null {\n this.#meta();\n const r = this.sql.internalExec(\n // generation is a 64-bit random(): read as text (beyond JS's safe integers)\n \"SELECT at_ms, retry, counted_retry, CAST(generation AS TEXT) FROM _cf_ALARM WHERE scope = ?\",\n [this.kv.scope],\n ).rows[0];\n return r\n ? { at: Number(r[0]), retry: Number(r[1]), counted: Number(r[2]), generation: String(r[3]) }\n : null;\n }\n /** The alarm being handled: getAlarm() reads null until the handler changes the alarm. */\n #active: { generation: string } | undefined;\n beginAlarm(row: { generation: string }): void {\n this.#active = { generation: row.generation };\n }\n /**\n * After the handler (celld's finish_alarm_handler): unless the handler changed the alarm,\n * success deletes it and failure reschedules it with backoff (2 s << min(retry, 6)) —\n * abandoned after 6 counted failures. Returns the alarm now stored.\n */\n finishAlarm(\n fired: { at: number; generation: string },\n succeeded: boolean,\n now: number,\n ): number | null {\n this.#active = undefined;\n const cur = this.alarmRowSync();\n if (!cur || cur.generation !== fired.generation) return cur?.at ?? null;\n if (succeeded) {\n this.sql.internalExec(\"DELETE FROM _cf_ALARM WHERE scope = ? AND at_ms = ?\", [\n this.kv.scope,\n fired.at,\n ]);\n } else if (cur.counted >= 6) {\n this.sql.internalExec(\"DELETE FROM _cf_ALARM WHERE scope = ?\", [this.kv.scope]);\n } else {\n const at = now + 2_000 * 2 ** Math.min(Math.max(cur.retry, 0), 6);\n this.sql.internalExec(\n \"UPDATE _cf_ALARM SET at_ms = ?, retry = retry + 1, counted_retry = counted_retry + 1 WHERE scope = ?\",\n [at, this.kv.scope],\n );\n }\n const after = this.alarmRowSync()?.at ?? null;\n this.onAlarmChange(after);\n return after;\n }\n /** Synchronous read of the stored alarm (ms since epoch) or null (null while it is handled). */\n alarmSync(): number | null {\n const row = this.alarmRowSync();\n if (row && this.#active && this.#active.generation === row.generation) return null;\n return row ? row.at : null;\n }\n /** One alarm per object, in celld's `_cf_ALARM` (same transaction as the event's writes). */\n getAlarm(_opts?: unknown): Promise<number | null> {\n return this.op(() => this.alarmSync());\n }\n setAlarm(scheduledTime: number | Date, _opts?: unknown): Promise<void> {\n // As celld: the time is coerced to a number and a non-number becomes 0 (due at once).\n const n = scheduledTime instanceof Date ? scheduledTime.getTime() : Number(scheduledTime);\n const at = Number.isNaN(n) ? 0 : n;\n return this.op(() => {\n this.#meta();\n this.sql.internalExec(\n // celld's statement: counters reset, a new random generation\n \"INSERT INTO _cf_ALARM(scope,at_ms,retry,counted_retry,generation) VALUES(?,?,0,0,random()) ON CONFLICT(scope) DO UPDATE SET at_ms=excluded.at_ms, retry=0, counted_retry=0, generation=random()\",\n [this.kv.scope, at],\n );\n this.onAlarmChange(at);\n });\n }\n /** setAlarm() inside a synchronous transaction (celld's harness ops). */\n setAlarmSync(at: number): void {\n this.#meta();\n this.sql.internalExec(\n \"INSERT INTO _cf_ALARM(scope,at_ms,retry,counted_retry,generation) VALUES(?,?,0,0,random()) ON CONFLICT(scope) DO UPDATE SET at_ms=excluded.at_ms, retry=0, counted_retry=0, generation=random()\",\n [this.kv.scope, at],\n );\n this.onAlarmChange(at);\n }\n deleteAlarm(_opts?: unknown): Promise<void> {\n return this.op(() => this.clearAlarmSync());\n }\n clearAlarmSync(): void {\n this.#meta();\n this.sql.internalExec(\"DELETE FROM _cf_ALARM WHERE scope = ?\", [this.kv.scope]);\n this.onAlarmChange(null);\n }\n}\n\ninterface TxnScope {\n get(): unknown;\n run<R>(value: unknown, fn: () => R): R;\n}\n\n/** An async-context slot marking \"inside this storage's transaction\", where the platform has one. */\nfunction txnScope(): TxnScope | undefined {\n const hooks = (\n globalThis as { process?: { getBuiltinModule?(id: string): unknown } }\n ).process?.getBuiltinModule?.(\"node:async_hooks\") as\n | {\n AsyncLocalStorage?: new () => {\n getStore(): unknown;\n run<R>(store: unknown, fn: () => R): R;\n };\n }\n | undefined;\n if (hooks?.AsyncLocalStorage) {\n const als = new hooks.AsyncLocalStorage();\n return { get: () => als.getStore(), run: (v, fn) => als.run(v, fn) };\n }\n const native = nativeAsyncContext();\n if (native) {\n const v = new native.Variable<unknown>({ name: \"cellb.storage.transaction\" });\n return { get: () => v.get(), run: (value, fn) => v.run(value, fn) };\n }\n return undefined;\n}\n"]}
|
|
@@ -18,6 +18,7 @@ Object.assign(globalThis, {
|
|
|
18
18
|
});
|
|
19
19
|
serveIsolate(parentPort, async ({ source }) => import(`data:text/javascript;base64,${Buffer.from(source ?? "").toString("base64")}`),
|
|
20
20
|
// Facets of the loaded code keep their SQLite here: files under `dataDir` when the host
|
|
21
|
-
// gives one, else
|
|
22
|
-
|
|
21
|
+
// gives one, else temporary files (lost with the isolate, as in memory). The isolate logs
|
|
22
|
+
// every commit's pages to its host, so they are read from the WAL, not from an image.
|
|
23
|
+
{ openSql: (load) => nodeSqliteOpener(load?.dataDir, { pageCapture: true }) });
|
|
23
24
|
//# sourceMappingURL=node-entry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-entry.js","sourceRoot":"","sources":["../../src/isolate/node-entry.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EACL,YAAY,EACZ,aAAa,EACb,SAAS,EACT,aAAa,EACb,4BAA4B,GAC7B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG5C,8FAA8F;AAC9F,qFAAqF;AACrF,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AAErE,8FAA8F;AAC9F,gGAAgG;AAChG,yEAAyE;AACzE,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE;IACxB,OAAO,EAAE,YAAY;IACrB,QAAQ,EAAE,aAAa;IACvB,SAAS;IACT,aAAa;IACb,4BAA4B;CAC7B,CAAC,CAAC;AAEH,YAAY,CACV,UAAiC,EACjC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CACnB,MAAM,CAAC,+BAA+B,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;AACvF,wFAAwF;AACxF,
|
|
1
|
+
{"version":3,"file":"node-entry.js","sourceRoot":"","sources":["../../src/isolate/node-entry.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EACL,YAAY,EACZ,aAAa,EACb,SAAS,EACT,aAAa,EACb,4BAA4B,GAC7B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG5C,8FAA8F;AAC9F,qFAAqF;AACrF,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AAErE,8FAA8F;AAC9F,gGAAgG;AAChG,yEAAyE;AACzE,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE;IACxB,OAAO,EAAE,YAAY;IACrB,QAAQ,EAAE,aAAa;IACvB,SAAS;IACT,aAAa;IACb,4BAA4B;CAC7B,CAAC,CAAC;AAEH,YAAY,CACV,UAAiC,EACjC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CACnB,MAAM,CAAC,+BAA+B,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;AACvF,wFAAwF;AACxF,0FAA0F;AAC1F,sFAAsF;AACtF,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,EAAE,CAC9E,CAAC","sourcesContent":["// A worker thread hosting ONE loaded Worker (an isolate); see src/isolate/protocol.ts.\nimport { parentPort } from \"node:worker_threads\";\nimport { nodeSqliteOpener } from \"../adapters/node-sqlite.js\";\nimport {\n CellsRequest,\n CellsResponse,\n WebSocket,\n WebSocketPair,\n WebSocketRequestResponsePair,\n} from \"../project/workers-globals-module.js\";\nimport { serveIsolate } from \"./isolate.js\";\nimport type { PortLike } from \"./protocol.js\";\n\n// An exception no request awaits (a timer, ctx.abort() from one) is reported, and the isolate\n// lives on, as in a browser Dedicated Worker and workerd; Node would end the thread.\nprocess.on(\"uncaughtException\", (e) => console.error(\"Uncaught\", e));\n\n// This thread is the loaded Worker's realm: its globals are the Workers ones, as in a browser\n// isolate (src/isolate/isolate-worker.ts). A `Response` that takes `{ status: 101, webSocket }`\n// and a `WebSocketPair` are what a Worker that accepts WebSockets needs.\nObject.assign(globalThis, {\n Request: CellsRequest,\n Response: CellsResponse,\n WebSocket,\n WebSocketPair,\n WebSocketRequestResponsePair,\n});\n\nserveIsolate(\n parentPort as unknown as PortLike,\n async ({ source }) =>\n import(`data:text/javascript;base64,${Buffer.from(source ?? \"\").toString(\"base64\")}`),\n // Facets of the loaded code keep their SQLite here: files under `dataDir` when the host\n // gives one, else temporary files (lost with the isolate, as in memory). The isolate logs\n // every commit's pages to its host, so they are read from the WAL, not from an image.\n { openSql: (load) => nodeSqliteOpener(load?.dataDir, { pageCapture: true }) },\n);\n"]}
|
|
@@ -88,7 +88,11 @@ function nodeHost(options) {
|
|
|
88
88
|
else
|
|
89
89
|
files = new MemFilesApi();
|
|
90
90
|
return {
|
|
91
|
-
|
|
91
|
+
// A storage that logs pages (a celld bucket: every commit as LTX) gets them from the WAL
|
|
92
|
+
// (O(changed pages)) instead of an image of the whole database diffed per commit.
|
|
93
|
+
openSql: nodeSqliteOpener(options.data ? resolve(options.data) : undefined, {
|
|
94
|
+
pageCapture: !!options.bucket?.durability?.capturePages,
|
|
95
|
+
}),
|
|
92
96
|
files,
|
|
93
97
|
storage: options.bucket,
|
|
94
98
|
ai: options.ai,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-load.js","sourceRoot":"","sources":["../../src/project/node-load.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `loadProject` on Node (`@statewalker/cellb/node`): one call that reads a project, built or\n * not, and runs it.\n */\nimport { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport type { FilesApi } from \"@statewalker/webrun-files\";\nimport { MemFilesApi } from \"@statewalker/webrun-files-mem\";\nimport { NodeFilesApi } from \"@statewalker/webrun-files-node\";\nimport { nodeSqliteOpener } from \"../adapters/node-sqlite.js\";\nimport type { WorkerModule } from \"../core/runtime.js\";\nimport type { CellStorage } from \"../ports.js\";\nimport {\n BUILD_MANIFEST,\n BUILT_WORKER,\n type BuiltProject,\n filesApiReader,\n isFilesApi,\n type LoadedProject,\n type LoadProjectOptions,\n type ProjectReader,\n type ProjectSource,\n readBuildManifest,\n readBuiltProject,\n urlReader,\n} from \"./built-project.js\";\nimport * as workersClasses from \"./cloudflare-workers.js\";\nimport { loadNodeProject, nodeIsolatedLoader, nodeModuleLoader } from \"./node-project.js\";\nimport { workerScope } from \"./worker-scope.js\";\nimport * as workersGlobals from \"./workers-globals-module.js\";\nimport {\n createProjectRuntime,\n loadProjectBindings,\n loadTimeEnv,\n type ProjectHost,\n populatesProcessEnv,\n processEnvOf,\n} from \"./wrangler.js\";\n\nexport type NodeLoadProjectOptions = LoadProjectOptions<CellStorage>;\n\n/**\n * Loads a project and runs it in this process.\n *\n * `source`: a folder with `wrangler.json(c)` (its `main` bundled with esbuild, as\n * `loadNodeProject` does), a folder written by `cellb build` (its `worker.js` imported as built),\n * an `http(s):` URL of a built folder, or a FilesApi holding either kind of folder.\n *\n * `options.data`: a directory for the cells' SQLite files and the project's files\n * (`<data>/files`); without it, both are in memory.\n */\nexport async function loadProject(\n source: ProjectSource,\n options: NodeLoadProjectOptions = {},\n): Promise<LoadedProject> {\n const host = nodeHost(options);\n const close = async (runtime: { close(): Promise<void> }, cleanup?: () => void) => {\n await runtime.close();\n cleanup?.();\n };\n // A folder on disk: read where it lies.\n const dir = localDir(source);\n if (dir !== undefined) {\n const reader = fsReader(dir);\n const manifest = await readBuildManifest(reader);\n if (manifest) return runBuilt(await readBuiltProject(reader, manifest), host);\n const { runtime, unsupported, config } = await loadNodeProject(dir, host);\n return {\n config,\n runtime,\n unsupported,\n fetch: (req) => runtime.fetch(req),\n close: () => close(runtime),\n };\n }\n // A FilesApi: a built folder is read from it; a source folder is copied out for esbuild.\n if (isFilesApi(source)) {\n const reader = filesApiReader(source);\n const manifest = await readBuildManifest(reader);\n if (manifest) return runBuilt(await readBuiltProject(reader, manifest), host);\n const tmp = await copyOut(source);\n try {\n const { runtime, unsupported, config } = await loadNodeProject(tmp, host);\n return {\n config,\n runtime,\n unsupported,\n fetch: (req) => runtime.fetch(req),\n close: () => close(runtime, () => rmSync(tmp, { recursive: true, force: true })),\n };\n } catch (err) {\n rmSync(tmp, { recursive: true, force: true });\n throw err;\n }\n }\n // A URL of a built folder.\n const url = folderUrl(source);\n const reader = urlReader(url);\n const manifest = await readBuildManifest(reader);\n if (!manifest)\n throw new Error(`${url} has no ${BUILD_MANIFEST}: load a folder written by \\`cellb build\\``);\n return runBuilt(await readBuiltProject(reader, manifest), host);\n}\n\n/** What `options` become on Node: SQLite files and a FilesApi under `data`, or memory. */\nfunction nodeHost(options: NodeLoadProjectOptions): Omit<ProjectHost, \"loadModules\"> {\n let files: FilesApi;\n if (options.data) {\n const data = resolve(options.data);\n mkdirSync(join(data, \"files\"), { recursive: true });\n files = new NodeFilesApi({ rootDir: join(data, \"files\") });\n } else files = new MemFilesApi();\n return {\n openSql: nodeSqliteOpener(options.data ? resolve(options.data) : undefined),\n files,\n storage: options.bucket,\n ai: options.ai,\n };\n}\n\n/**\n * Runs a built project on Node: `worker.js` was bundled for a browser realm, so it reads the\n * Workers globals and `cloudflare:workers` from the globals this sets, as in a browser worker.\n * (One such project per process: the globals are the process's.)\n */\nasync function runBuilt(\n built: BuiltProject,\n host: Omit<ProjectHost, \"loadModules\">,\n): Promise<LoadedProject> {\n const { config } = built;\n const flags = config.compatibility_flags ?? [];\n const scope = workerScope(loadTimeEnv(config, host.ai));\n const g = globalThis as Record<string, unknown>;\n g.__cellsWorkersModule = workersClasses;\n g.__cellsProjectScope = scope;\n g.__cellsGlobals = {\n ...workersGlobals,\n Request: workersGlobals.CellsRequest,\n Response: workersGlobals.CellsResponse,\n WebSocketPair: flags.includes(\"websocket_standard_binary_type\")\n ? workersGlobals.StandardWebSocketPair\n : workersGlobals.WebSocketPair,\n };\n if (populatesProcessEnv(config)) {\n const env = processEnvOf(config);\n g.__cellsProcessEnv = env;\n for (const [k, v] of Object.entries(env)) process.env[k] ??= v;\n }\n let module: WorkerModule = { default: {} } as WorkerModule;\n if (built.code !== null) {\n const tmp = mkdtempSync(join(tmpdir(), \"cellb-built-\"));\n const file = join(tmp, BUILT_WORKER.replace(/\\.js$/, \".mjs\"));\n writeFileSync(file, built.code);\n try {\n module = (await import(/* @vite-ignore */ pathToFileURL(file).href)) as WorkerModule;\n } finally {\n rmSync(tmp, { recursive: true, force: true });\n }\n }\n const project = createProjectRuntime(config, module, {\n bindings: await loadProjectBindings(config),\n loadModules: nodeModuleLoader,\n isolatedModules: nodeIsolatedLoader(() => host.storage),\n assetFiles: built.assets,\n ...host,\n });\n scope.bind(project.runtime);\n const { runtime, unsupported } = project;\n return {\n config,\n runtime,\n unsupported,\n fetch: (req) => runtime.fetch(req),\n close: () => runtime.close(),\n };\n}\n\n/** The folder a source names on this machine: a path or a `file:` URL. */\nfunction localDir(source: ProjectSource): string | undefined {\n if (typeof source === \"string\") {\n if (/^https?:\\/\\//i.test(source)) return undefined;\n return resolve(source.startsWith(\"file:\") ? fileURLToPath(source) : source);\n }\n if (source instanceof URL && source.protocol === \"file:\") return fileURLToPath(source);\n return undefined;\n}\n\nfunction folderUrl(source: ProjectSource): URL {\n const url = new URL(String(source));\n if (!url.pathname.endsWith(\"/\")) url.pathname += \"/\";\n return url;\n}\n\nfunction fsReader(dir: string): ProjectReader {\n return {\n async bytes(path) {\n const full = join(dir, path);\n return existsSync(full) ? new Uint8Array(readFileSync(full)) : undefined;\n },\n };\n}\n\n/** Copies a FilesApi's files into a temporary folder (esbuild bundles from disk). */\nasync function copyOut(files: FilesApi): Promise<string> {\n const tmp = mkdtempSync(join(tmpdir(), \"cellb-project-\"));\n const reader = filesApiReader(files);\n for (const path of (await reader.list?.(\"/\")) ?? []) {\n const out = join(tmp, path);\n mkdirSync(dirname(out), { recursive: true });\n writeFileSync(out, (await reader.bytes(path)) as Uint8Array);\n }\n return tmp;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"node-load.js","sourceRoot":"","sources":["../../src/project/node-load.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `loadProject` on Node (`@statewalker/cellb/node`): one call that reads a project, built or\n * not, and runs it.\n */\nimport { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport type { FilesApi } from \"@statewalker/webrun-files\";\nimport { MemFilesApi } from \"@statewalker/webrun-files-mem\";\nimport { NodeFilesApi } from \"@statewalker/webrun-files-node\";\nimport { nodeSqliteOpener } from \"../adapters/node-sqlite.js\";\nimport type { WorkerModule } from \"../core/runtime.js\";\nimport type { CellStorage } from \"../ports.js\";\nimport {\n BUILD_MANIFEST,\n BUILT_WORKER,\n type BuiltProject,\n filesApiReader,\n isFilesApi,\n type LoadedProject,\n type LoadProjectOptions,\n type ProjectReader,\n type ProjectSource,\n readBuildManifest,\n readBuiltProject,\n urlReader,\n} from \"./built-project.js\";\nimport * as workersClasses from \"./cloudflare-workers.js\";\nimport { loadNodeProject, nodeIsolatedLoader, nodeModuleLoader } from \"./node-project.js\";\nimport { workerScope } from \"./worker-scope.js\";\nimport * as workersGlobals from \"./workers-globals-module.js\";\nimport {\n createProjectRuntime,\n loadProjectBindings,\n loadTimeEnv,\n type ProjectHost,\n populatesProcessEnv,\n processEnvOf,\n} from \"./wrangler.js\";\n\nexport type NodeLoadProjectOptions = LoadProjectOptions<CellStorage>;\n\n/**\n * Loads a project and runs it in this process.\n *\n * `source`: a folder with `wrangler.json(c)` (its `main` bundled with esbuild, as\n * `loadNodeProject` does), a folder written by `cellb build` (its `worker.js` imported as built),\n * an `http(s):` URL of a built folder, or a FilesApi holding either kind of folder.\n *\n * `options.data`: a directory for the cells' SQLite files and the project's files\n * (`<data>/files`); without it, both are in memory.\n */\nexport async function loadProject(\n source: ProjectSource,\n options: NodeLoadProjectOptions = {},\n): Promise<LoadedProject> {\n const host = nodeHost(options);\n const close = async (runtime: { close(): Promise<void> }, cleanup?: () => void) => {\n await runtime.close();\n cleanup?.();\n };\n // A folder on disk: read where it lies.\n const dir = localDir(source);\n if (dir !== undefined) {\n const reader = fsReader(dir);\n const manifest = await readBuildManifest(reader);\n if (manifest) return runBuilt(await readBuiltProject(reader, manifest), host);\n const { runtime, unsupported, config } = await loadNodeProject(dir, host);\n return {\n config,\n runtime,\n unsupported,\n fetch: (req) => runtime.fetch(req),\n close: () => close(runtime),\n };\n }\n // A FilesApi: a built folder is read from it; a source folder is copied out for esbuild.\n if (isFilesApi(source)) {\n const reader = filesApiReader(source);\n const manifest = await readBuildManifest(reader);\n if (manifest) return runBuilt(await readBuiltProject(reader, manifest), host);\n const tmp = await copyOut(source);\n try {\n const { runtime, unsupported, config } = await loadNodeProject(tmp, host);\n return {\n config,\n runtime,\n unsupported,\n fetch: (req) => runtime.fetch(req),\n close: () => close(runtime, () => rmSync(tmp, { recursive: true, force: true })),\n };\n } catch (err) {\n rmSync(tmp, { recursive: true, force: true });\n throw err;\n }\n }\n // A URL of a built folder.\n const url = folderUrl(source);\n const reader = urlReader(url);\n const manifest = await readBuildManifest(reader);\n if (!manifest)\n throw new Error(`${url} has no ${BUILD_MANIFEST}: load a folder written by \\`cellb build\\``);\n return runBuilt(await readBuiltProject(reader, manifest), host);\n}\n\n/** What `options` become on Node: SQLite files and a FilesApi under `data`, or memory. */\nfunction nodeHost(options: NodeLoadProjectOptions): Omit<ProjectHost, \"loadModules\"> {\n let files: FilesApi;\n if (options.data) {\n const data = resolve(options.data);\n mkdirSync(join(data, \"files\"), { recursive: true });\n files = new NodeFilesApi({ rootDir: join(data, \"files\") });\n } else files = new MemFilesApi();\n return {\n // A storage that logs pages (a celld bucket: every commit as LTX) gets them from the WAL\n // (O(changed pages)) instead of an image of the whole database diffed per commit.\n openSql: nodeSqliteOpener(options.data ? resolve(options.data) : undefined, {\n pageCapture: !!options.bucket?.durability?.capturePages,\n }),\n files,\n storage: options.bucket,\n ai: options.ai,\n };\n}\n\n/**\n * Runs a built project on Node: `worker.js` was bundled for a browser realm, so it reads the\n * Workers globals and `cloudflare:workers` from the globals this sets, as in a browser worker.\n * (One such project per process: the globals are the process's.)\n */\nasync function runBuilt(\n built: BuiltProject,\n host: Omit<ProjectHost, \"loadModules\">,\n): Promise<LoadedProject> {\n const { config } = built;\n const flags = config.compatibility_flags ?? [];\n const scope = workerScope(loadTimeEnv(config, host.ai));\n const g = globalThis as Record<string, unknown>;\n g.__cellsWorkersModule = workersClasses;\n g.__cellsProjectScope = scope;\n g.__cellsGlobals = {\n ...workersGlobals,\n Request: workersGlobals.CellsRequest,\n Response: workersGlobals.CellsResponse,\n WebSocketPair: flags.includes(\"websocket_standard_binary_type\")\n ? workersGlobals.StandardWebSocketPair\n : workersGlobals.WebSocketPair,\n };\n if (populatesProcessEnv(config)) {\n const env = processEnvOf(config);\n g.__cellsProcessEnv = env;\n for (const [k, v] of Object.entries(env)) process.env[k] ??= v;\n }\n let module: WorkerModule = { default: {} } as WorkerModule;\n if (built.code !== null) {\n const tmp = mkdtempSync(join(tmpdir(), \"cellb-built-\"));\n const file = join(tmp, BUILT_WORKER.replace(/\\.js$/, \".mjs\"));\n writeFileSync(file, built.code);\n try {\n module = (await import(/* @vite-ignore */ pathToFileURL(file).href)) as WorkerModule;\n } finally {\n rmSync(tmp, { recursive: true, force: true });\n }\n }\n const project = createProjectRuntime(config, module, {\n bindings: await loadProjectBindings(config),\n loadModules: nodeModuleLoader,\n isolatedModules: nodeIsolatedLoader(() => host.storage),\n assetFiles: built.assets,\n ...host,\n });\n scope.bind(project.runtime);\n const { runtime, unsupported } = project;\n return {\n config,\n runtime,\n unsupported,\n fetch: (req) => runtime.fetch(req),\n close: () => runtime.close(),\n };\n}\n\n/** The folder a source names on this machine: a path or a `file:` URL. */\nfunction localDir(source: ProjectSource): string | undefined {\n if (typeof source === \"string\") {\n if (/^https?:\\/\\//i.test(source)) return undefined;\n return resolve(source.startsWith(\"file:\") ? fileURLToPath(source) : source);\n }\n if (source instanceof URL && source.protocol === \"file:\") return fileURLToPath(source);\n return undefined;\n}\n\nfunction folderUrl(source: ProjectSource): URL {\n const url = new URL(String(source));\n if (!url.pathname.endsWith(\"/\")) url.pathname += \"/\";\n return url;\n}\n\nfunction fsReader(dir: string): ProjectReader {\n return {\n async bytes(path) {\n const full = join(dir, path);\n return existsSync(full) ? new Uint8Array(readFileSync(full)) : undefined;\n },\n };\n}\n\n/** Copies a FilesApi's files into a temporary folder (esbuild bundles from disk). */\nasync function copyOut(files: FilesApi): Promise<string> {\n const tmp = mkdtempSync(join(tmpdir(), \"cellb-project-\"));\n const reader = filesApiReader(files);\n for (const path of (await reader.list?.(\"/\")) ?? []) {\n const out = join(tmp, path);\n mkdirSync(dirname(out), { recursive: true });\n writeFileSync(out, (await reader.bytes(path)) as Uint8Array);\n }\n return tmp;\n}\n"]}
|
|
@@ -138,7 +138,11 @@ export declare function createProjectRuntime(config: WranglerConfig, module: Wor
|
|
|
138
138
|
* Entries with ids are kept as they are, so storage shared with celld keeps its names.
|
|
139
139
|
*/
|
|
140
140
|
export declare function withResourceIds(config: WranglerConfig): WranglerConfig;
|
|
141
|
-
/**
|
|
141
|
+
/**
|
|
142
|
+
* Whether `config` asks for nodejs_compat: the `nodejs_compat` or `nodejs_compat_v2` flag, as in
|
|
143
|
+
* workerd and Wrangler. Other `nodejs_compat_*` flags (the process.env ones) tune nodejs_compat
|
|
144
|
+
* and do nothing without it.
|
|
145
|
+
*/
|
|
142
146
|
export declare function hasNodeCompat(config: WranglerConfig): boolean;
|
|
143
147
|
/** The configuration files of a project folder, in the order celld reads them. */
|
|
144
148
|
export declare const WRANGLER_FILES: string[];
|
package/dist/project/wrangler.js
CHANGED
|
@@ -375,9 +375,13 @@ export function withResourceIds(config) {
|
|
|
375
375
|
d1_databases: d1?.map((d) => d.database_id ? d : { ...d, database_id: d.database_name ?? d.binding }),
|
|
376
376
|
};
|
|
377
377
|
}
|
|
378
|
-
/**
|
|
378
|
+
/**
|
|
379
|
+
* Whether `config` asks for nodejs_compat: the `nodejs_compat` or `nodejs_compat_v2` flag, as in
|
|
380
|
+
* workerd and Wrangler. Other `nodejs_compat_*` flags (the process.env ones) tune nodejs_compat
|
|
381
|
+
* and do nothing without it.
|
|
382
|
+
*/
|
|
379
383
|
export function hasNodeCompat(config) {
|
|
380
|
-
return (config.compatibility_flags ?? []).some((f) => f
|
|
384
|
+
return (config.compatibility_flags ?? []).some((f) => f === "nodejs_compat" || f === "nodejs_compat_v2");
|
|
381
385
|
}
|
|
382
386
|
/** The configuration files of a project folder, in the order celld reads them. */
|
|
383
387
|
export const WRANGLER_FILES = ["wrangler.jsonc", "wrangler.json"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrangler.js","sourceRoot":"","sources":["../../src/project/wrangler.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FilesApi } from \"@statewalker/webrun-files\";\nimport type { AssetFiles, AssetsConfig } from \"../bindings/assets.js\";\nimport type { QueueConsumerConfig } from \"../bindings/celld-queues.js\";\nimport type { ModuleLoader } from \"../bindings/worker-loader.js\";\nimport { type WorkersAiOptions, workersAi } from \"../bindings/workers-ai.js\";\nimport { entrypointStub } from \"../core/handles.js\";\nimport type { DurableObjectNamespace } from \"../core/namespace.js\";\nimport {\n type CellRuntime,\n type CellRuntimeOptions,\n createCellRuntime,\n type WorkerModule,\n} from \"../core/runtime.js\";\nimport { splitSqlStatements } from \"../core/sql-split.js\";\nimport { filesApiBlobService } from \"../miniflare-compat/blob-service.js\";\nimport { simulatorFetcher } from \"../miniflare-compat/simulator-fetcher.js\";\nimport { systemClock } from \"../ports.js\";\nimport type { ModuleRule } from \"./module-rules.js\";\n\n/** The subset of wrangler.json(c) that celld deploys (and cellb reads). */\nexport interface WranglerConfig {\n name?: string;\n main?: string;\n compatibility_date?: string;\n compatibility_flags?: string[];\n vars?: Record<string, unknown>;\n durable_objects?: { bindings?: { name: string; class_name: string; script_name?: string }[] };\n migrations?: {\n tag: string;\n new_sqlite_classes?: string[];\n new_classes?: string[];\n renamed_classes?: { from: string; to: string }[];\n deleted_classes?: string[];\n }[];\n kv_namespaces?: { binding: string; id?: string }[];\n d1_databases?: { binding: string; database_name?: string; database_id?: string }[];\n r2_buckets?: { binding: string; bucket_name: string }[];\n queues?: {\n producers?: { binding: string; queue: string; delivery_delay?: number }[];\n consumers?: QueueConsumerConfig[];\n };\n workflows?: WorkflowConfig[];\n triggers?: { crons?: string[] };\n assets?: AssetsConfig;\n services?: { binding: string; service: string; entrypoint?: string; props?: unknown }[];\n worker_loaders?: { binding: string }[];\n /** Workers AI: served by the host's OpenAI-compatible endpoint (`ProjectHost.ai`), if any. */\n ai?: { binding: string };\n /** Module rules: how imports of non-JS files load (`CompiledWasm`, `Data`, `Text`). */\n rules?: ModuleRule[];\n /** Containers (celld runs them with Docker or Podman): not supported, reported. */\n containers?: { class_name: string; image?: string }[];\n}\n\n/** wrangler `workflows` entries. */\nexport interface WorkflowConfig {\n binding: string;\n name: string;\n class_name: string;\n}\n\n/** Runs the Worker's `queue(batch, env, ctx)` handler for a batch celld's queue cell leased. */\ninterface QueueDispatcher {\n deliver(batch: unknown): Promise<void>;\n}\n\nexport interface ProjectHost\n extends Pick<CellRuntimeOptions, \"openSql\" | \"storage\" | \"clock\" | \"peers\" | \"route\"> {\n /** Files of `assets.directory` (path \"/a/b.html\" → bytes), loaded by the host. */\n assetFiles?: AssetFiles;\n /** Runs each loaded Worker in its own realm (celld isolates); classes still use `loadModules`. */\n isolatedModules?: ModuleLoader;\n /** Compiles code given to a Worker Loader binding (esbuild on Node, webrun-modules in browsers). */\n loadModules?: ModuleLoader;\n /** Blob store of the KV simulator (large values): OPFS in a browser, a directory or S3 on a server. */\n files: FilesApi;\n /** The OpenAI-compatible endpoint behind the `ai` binding; without it the binding is unsupported. */\n ai?: WorkersAiOptions;\n /** The binding implementations the config needs: `await loadProjectBindings(config)`. */\n bindings?: ProjectBindings;\n}\n\n/**\n * The implementations of the bindings a project declares, loaded on demand: a project with\n * Durable Objects only loads none of them (Miniflare's D1 simulator, celld's KV, queue and\n * workflow code, R2, assets, cron and Worker Loaders), and a browser bundle keeps them in chunks\n * of their own.\n */\nexport interface ProjectBindings {\n kv?: typeof import(\"../bindings/celld-kv.js\");\n d1?: typeof import(\"../miniflare-compat/vendored.js\");\n queues?: typeof import(\"../bindings/celld-queues.js\");\n workflows?: typeof import(\"../bindings/celld-workflows.js\");\n r2?: typeof import(\"../bindings/r2.js\");\n r2Celld?: typeof import(\"../bindings/r2-celld.js\");\n cron?: typeof import(\"../bindings/cron.js\");\n assets?: typeof import(\"../bindings/assets.js\");\n workerLoader?: typeof import(\"../bindings/worker-loader.js\");\n}\n\n/** Loads the binding implementations `config` declares, for `createProjectRuntime`'s host. */\nexport async function loadProjectBindings(config: WranglerConfig): Promise<ProjectBindings> {\n const when = <T>(cond: unknown, load: () => Promise<T>) =>\n cond ? load() : Promise.resolve(undefined);\n const [kv, d1, queues, workflows, r2, r2Celld, cron, assets, workerLoader] = await Promise.all([\n when(config.kv_namespaces?.length, () => import(\"../bindings/celld-kv.js\")),\n when(config.d1_databases?.length, () => import(\"../miniflare-compat/vendored.js\")),\n when(\n config.queues?.producers?.length || config.queues?.consumers?.length,\n () => import(\"../bindings/celld-queues.js\"),\n ),\n when(config.workflows?.length, () => import(\"../bindings/celld-workflows.js\")),\n when(config.r2_buckets?.length, () => import(\"../bindings/r2.js\")),\n when(config.r2_buckets?.length, () => import(\"../bindings/r2-celld.js\")),\n when(config.triggers?.crons?.length, () => import(\"../bindings/cron.js\")),\n when(config.assets, () => import(\"../bindings/assets.js\")),\n when(config.worker_loaders?.length, () => import(\"../bindings/worker-loader.js\")),\n ]);\n return { kv, d1, queues, workflows, r2, r2Celld, cron, assets, workerLoader };\n}\n\n/** The loaded implementation of a binding the config declares, or an error saying how to load it. */\nfunction binding<K extends keyof ProjectBindings>(\n host: ProjectHost,\n key: K,\n what: string,\n): NonNullable<ProjectBindings[K]> {\n const m = host.bindings?.[key];\n if (!m)\n throw new Error(\n `${what}: the host has no implementation loaded; pass \\`bindings: await loadProjectBindings(config)\\``,\n );\n return m as NonNullable<ProjectBindings[K]>;\n}\n\nexport interface ProjectRuntime {\n runtime: CellRuntime;\n /** Configuration entries cellb does not support yet (reported, not silently ignored). */\n unsupported: string[];\n}\n\n/**\n * What `env` of `cloudflare:workers` holds while the Worker's module is evaluated, before the\n * runtime exists: the vars, and the bindings that need no runtime (`ai`; Flue's entry reads\n * `env.AI` at load).\n */\nexport function loadTimeEnv(\n config: WranglerConfig,\n ai?: WorkersAiOptions,\n): Record<string, unknown> {\n const env: Record<string, unknown> = { ...config.vars };\n if (config.ai && ai) env[config.ai.binding] = workersAi(ai);\n return env;\n}\n\n// Internal bindings carrying the runtime-supplied objects behind KV and D1.\nconst KV_OBJECTS = \"__CELLS_KV_OBJECTS\";\nconst D1_OBJECTS = \"__CELLS_D1_OBJECTS\";\nconst QUEUE_OBJECTS = \"__CELLS_QUEUE_OBJECTS\";\nconst WORKFLOW_OBJECTS = \"__CELLS_WORKFLOW_OBJECTS\";\n\n/**\n * Builds a runtime from a wrangler config and the Worker's module namespace — the same\n * inputs celld deploys. Hosts differ only in `host` (storage) and in how they load `main`.\n */\nexport function createProjectRuntime(\n config: WranglerConfig,\n module: WorkerModule,\n host: ProjectHost,\n): ProjectRuntime {\n config = withResourceIds(config);\n const unsupported: string[] = [];\n const durableObjects: NonNullable<CellRuntimeOptions[\"durableObjects\"]> = {};\n const sqliteClasses = new Set<string>();\n for (const m of config.migrations ?? []) {\n for (const c of m.new_sqlite_classes ?? []) sqliteClasses.add(c);\n for (const c of m.new_classes ?? []) sqliteClasses.add(c); // KV-backed on Cloudflare; SQLite here (superset)\n for (const r of m.renamed_classes ?? [])\n unsupported.push(`migrations.renamed_classes (${r.from} → ${r.to})`);\n }\n // wrangler's module rule types: the bundles apply CompiledWasm, Data and Text (module-rules.ts)\n for (const [i, r] of (config.rules ?? []).entries())\n if (![\"ESModule\", \"CommonJS\", \"CompiledWasm\", \"Data\", \"Text\"].includes(r.type))\n unsupported.push(`rules[${i}].type \"${r.type}\"`);\n for (const c of config.containers ?? [])\n unsupported.push(`containers[${c.class_name}] (cellb runs no containers)`);\n for (const b of config.durable_objects?.bindings ?? []) {\n if (b.script_name) unsupported.push(`durable_objects.bindings[${b.name}].script_name`);\n durableObjects[b.name] = { className: b.class_name };\n }\n const worker: WorkerModule = { ...module };\n let kv: ReturnType<NonNullable<ProjectBindings[\"kv\"]>[\"celldKv\"]> | undefined;\n if (config.kv_namespaces?.length) {\n kv = binding(host, \"kv\", \"kv_namespaces\").celldKv(host.files);\n worker.__KvNamespace = kv.KvNamespaceCell as never;\n durableObjects[KV_OBJECTS] = { className: \"__KvNamespace\" };\n }\n if (config.d1_databases?.length) {\n worker.__D1Database = binding(host, \"d1\", \"d1_databases\").D1DatabaseObject;\n durableObjects[D1_OBJECTS] = { className: \"__D1Database\" };\n }\n // Queues: every queue is a cell of a runtime-supplied class (as on celld).\n const consumers = new Map((config.queues?.consumers ?? []).map((c) => [c.queue, c]));\n // celld's own queue code (vendor/celld/queues.js): its queue cell, producer and consumer\n // batch, so a queue's cell (and pending messages) is celld's format.\n let queueDispatcher: QueueDispatcher | undefined;\n let queues: ReturnType<NonNullable<ProjectBindings[\"queues\"]>[\"celldQueues\"]> | undefined;\n if (config.queues?.producers?.length || consumers.size) {\n queues = binding(host, \"queues\", \"queues\").celldQueues({\n namespace: () => runtime.env[QUEUE_OBJECTS] as never,\n consumers: [...consumers.values()],\n compatibilityDate: config.compatibility_date,\n runConsumer: (batch) => queueDispatcher!.deliver(batch as never),\n });\n worker.__Queue = queues.QueueCell as never;\n durableObjects[QUEUE_OBJECTS] = { className: \"__Queue\" };\n }\n // Workflows: every instance is a cell of a runtime-supplied class (as on celld).\n // celld's own workflow code (vendor/celld/workflows.js): its instance cell and binding.\n let workflows:\n | ReturnType<NonNullable<ProjectBindings[\"workflows\"]>[\"celldWorkflows\"]>\n | undefined;\n if (config.workflows?.length) {\n workflows = binding(host, \"workflows\", \"workflows\").celldWorkflows({\n script: config.name ?? \"worker\",\n workflows: Object.fromEntries(config.workflows.map((w) => [w.name, w.class_name])),\n exports: () => module as Record<string, unknown>,\n env: () => runtime.env,\n namespace: () => runtime.env[WORKFLOW_OBJECTS],\n });\n worker[workflows.className] = workflows.WorkflowCell as never;\n durableObjects[WORKFLOW_OBJECTS] = { className: workflows.className };\n }\n if (config.ai && !host.ai)\n unsupported.push(\n `ai[${config.ai.binding}] (Workers AI: give the host an OpenAI-compatible \\`ai\\`)`,\n );\n for (const s of config.services ?? [])\n if (s.service !== config.name)\n unsupported.push(\n `services[${s.binding}] → \"${s.service}\" (only this script's own entrypoints)`,\n );\n const sqlExtensions: string[] = [];\n let deleteAllPreservesAlarm = false;\n for (const f of config.compatibility_flags ?? []) {\n if (f === \"delete_all_preserves_alarm\") deleteAllPreservesAlarm = true;\n else if (f === \"delete_all_deletes_alarm\")\n continue; // the default\n else if (f === \"sqlite_vec\")\n sqlExtensions.push(\"sqlite_vec\"); // vec0 virtual tables, as on celld\n else if (f === \"nodejs_compat\" || f === \"nodejs_compat_v2\")\n continue; // the host's bundler maps node:*\n else if (f === \"websocket_standard_binary_type\")\n continue; // the host picks the project's WebSocketPair\n else if (\n f === \"nodejs_compat_populate_process_env\" ||\n f === \"nodejs_compat_do_not_populate_process_env\"\n )\n continue; // the host fills process.env or not (populatesProcessEnv)\n else unsupported.push(`compatibility_flags: ${f}`);\n }\n\n const runtime = createCellRuntime({\n worker,\n durableObjects,\n vars: { ...config.vars, MINIFLARE_BLOBS: filesApiBlobService(host.files) },\n openSql: host.openSql,\n sqlExtensions,\n deleteAllPreservesAlarm,\n scriptName: config.name ?? \"worker\",\n // celld's fleet-wide namespaces for the resources several scripts can share.\n namespaceKeys: {\n __KvNamespace: \"cells:v1:kv:__KvNamespace\",\n __D1Database: \"cells:v1:d1:__D1Database\",\n __Queue: \"cells:v1:queue:__Queue\",\n },\n storage: host.storage,\n clock: host.clock,\n peers: host.peers,\n route: host.route,\n });\n const env = runtime.env as Record<string, unknown>;\n if (config.ai && host.ai) env[config.ai.binding] = workersAi(host.ai);\n // KV: celld's own client against celld's own namespace cell (cell name \"<id>/<shard>\").\n for (const ns of config.kv_namespaces ?? [])\n env[ns.binding] = new kv!.KvNamespace(() => env[KV_OBJECTS], `${ns.id}/0`);\n for (const p of config.queues?.producers ?? [])\n env[p.binding] = queues!.producer(p.queue, p.delivery_delay ?? 0);\n if (consumers.size) {\n const handler = (module.default as { queue?: (b: unknown, e: unknown, c: unknown) => unknown })\n .queue;\n if (typeof handler !== \"function\")\n unsupported.push(\"queues.consumers without a queue() handler\");\n queueDispatcher = {\n deliver: async (batch) => {\n const pending: Promise<unknown>[] = [];\n await handler?.call(module.default, batch, env, {\n waitUntil: (p: Promise<unknown>) => pending.push(p),\n passThroughOnException() {},\n });\n await Promise.allSettled(pending);\n },\n };\n }\n // The isolates of loaded Workers end with the runtime (on Node, a worker thread's port would\n // keep the process alive; in a browser, a Dedicated Worker would outlive the runtime).\n const isolated = host.isolatedModules as\n | (ModuleLoader & { close?(): void | Promise<void> })\n | undefined;\n if (config.worker_loaders?.length && isolated?.close) {\n const close = runtime.close.bind(runtime);\n runtime.close = async () => {\n await close();\n await isolated.close?.();\n };\n }\n for (const l of config.worker_loaders ?? []) {\n if (!host.loadModules) {\n unsupported.push(`worker_loaders[${l.binding}] (the host provides no module loader)`);\n continue;\n }\n const { workerLoader } = binding(host, \"workerLoader\", \"worker_loaders\");\n env[l.binding] = host.isolatedModules\n ? workerLoader(host.isolatedModules) // facets of loaded code run in the isolate as well\n : workerLoader(host.loadModules);\n }\n // Cron Triggers (validated at load time like `celld deploy` does).\n const crons = config.triggers?.crons ?? [];\n if (crons.length) {\n const scheduled = (\n module.default as { scheduled?: (c: unknown, e: unknown, x: unknown) => unknown }\n ).scheduled;\n if (typeof scheduled !== \"function\")\n unsupported.push(\"triggers.crons without a scheduled() handler\");\n else {\n const db = host.openSql(\"__cellb/cron\");\n const stop = binding(host, \"cron\", \"triggers.crons\").startCronTriggers(\n crons,\n (c, x) => runtime.runEvent(() => scheduled.call(module.default, c, env, x)),\n host.clock ?? systemClock,\n cronState(db),\n );\n const close = runtime.close.bind(runtime);\n runtime.close = async () => {\n stop();\n db.close();\n await close();\n };\n }\n }\n // Static assets: routed before the Worker; `assets.binding` exposes env.ASSETS.\n if (config.assets) {\n const hasWorker = typeof (module.default as { fetch?: unknown })?.fetch === \"function\";\n if (host.assetFiles?.has(\"/.assetsignore\"))\n throw new Error(\n `${config.assets.directory ?? \"assets\"}/.assetsignore is not supported by celld; remove it`,\n );\n const assets = binding(host, \"assets\", \"assets\").createAssets(\n host.assetFiles ?? new Map(),\n config.assets,\n hasWorker,\n );\n if (config.assets.binding) env[config.assets.binding] = assets.binding;\n const workerFetch = runtime.fetch.bind(runtime);\n runtime.fetch = async (req) =>\n assets.route(req) ??\n (hasWorker ? workerFetch(req) : new Response(\"Not found\", { status: 404 }));\n }\n for (const w of config.workflows ?? []) env[w.binding] = workflows!.binding(w.name);\n // Service bindings to this script's own entrypoints (a celld fleet runs one application):\n // default export or a named WorkerEntrypoint, with fetch() and JS RPC.\n for (const s of config.services ?? []) {\n if (s.service !== config.name) continue;\n const target = s.entrypoint ? module[s.entrypoint] : module.default;\n if (!target)\n unsupported.push(`services[${s.binding}].entrypoint \"${s.entrypoint}\" is not exported`);\n else env[s.binding] = entrypointStub(target, env, s.props);\n }\n // R2 objects live directly in the host's store, as celld keeps them in the fleet bucket.\n // With a celld fleet bucket, R2 objects live in it as celld keeps them; else in the FilesApi.\n for (const r2 of config.r2_buckets ?? []) {\n const { r2Bucket, r2BucketOn } = binding(host, \"r2\", \"r2_buckets\");\n const { celldR2Backend } = binding(host, \"r2Celld\", \"r2_buckets\");\n env[r2.binding] = host.storage?.objects\n ? r2BucketOn(celldR2Backend(host.storage.objects, r2.bucket_name), r2.binding)\n : r2Bucket(host.files, `/r2/${r2.bucket_name}`, r2.binding);\n }\n for (const d1 of config.d1_databases ?? [])\n env[d1.binding] = celldExec(\n binding(host, \"d1\", \"d1_databases\").makeD1Binding({\n fetcher: simulatorFetcher(\n env[D1_OBJECTS] as DurableObjectNamespace,\n d1.database_id as string, // set by withResourceIds\n ) as never,\n }) as D1Like,\n );\n for (const name of [...sqliteClasses])\n if (!Object.values(durableObjects).some((d) => d.className === name)) {\n // A migrated class without a binding is fine (reachable through other code paths only).\n }\n return { runtime, unsupported };\n}\n\ninterface D1Like {\n exec(sql: string): Promise<{ count: number; duration: number }>;\n prepare(sql: string): { run(): Promise<unknown> };\n}\n\n/**\n * `D1Database#exec` as celld implements it: statements are split by SQL syntax.\n * workerd's d1-api.ts splits on NEWLINES (Cloudflare's documented behaviour), so a\n * multi-line `CREATE TABLE` fails there but works on celld — and celld is the\n * reference here (verified on celld 0.6.2 by the d1 example in conformance/).\n */\nfunction celldExec<T extends D1Like>(db: T): T {\n const exec = async (sql: string) => {\n const t0 = Date.now();\n const statements = splitSqlStatements(sql).filter((s) => s.trim());\n for (const statement of statements) {\n if (/^\\s*BEGIN\\b/i.test(statement))\n throw new Error(\n \"D1_EXEC_ERROR: the SQL ends in an incomplete statement, which did not run: terminate the last statement with a semicolon\",\n );\n guard(statement);\n await db.prepare(statement).run();\n }\n return { count: statements.length, duration: Date.now() - t0 };\n };\n return celldD1(db, exec) as T;\n}\n\n/**\n * celld's D1 rules on top of workerd's client (celld docs/services/d1.md, checked by the\n * d1-details project): ATTACH/DETACH and TEMP objects are \"not authorized\", VACUUM is\n * \"authorization denied\"; there is one primary and no replica, so sessions return the\n * bookmark \"celld:primary\" and every result reports served_by_primary/served_by_region\n * \"local\"; a read-only statement reports last_row_id and changes as 0.\n */\nfunction guard(sql: string): void {\n if (/^\\s*(ATTACH|DETACH)\\b/i.test(sql) || /^\\s*CREATE\\s+(TEMP|TEMPORARY)\\b/i.test(sql))\n throw new Error(\"D1_ERROR: not authorized\");\n if (/^\\s*VACUUM\\b/i.test(sql)) throw new Error(\"D1_ERROR: authorization denied\");\n}\n\nfunction celldMeta(r: any): any {\n if (!r?.meta) return r;\n r.meta.served_by_primary = true;\n r.meta.served_by_region = \"local\";\n if (r.meta.changed_db === false) {\n r.meta.last_row_id = 0;\n r.meta.changes = 0;\n }\n return r;\n}\n\nfunction celldStatement(stmt: any): any {\n return new Proxy(stmt, {\n get(t, p, r) {\n const v = Reflect.get(t, p, r);\n if (p === \"bind\") return (...a: unknown[]) => celldStatement(v.apply(t, a));\n if (p === \"run\" || p === \"all\")\n return async (...a: unknown[]) => celldMeta(await v.apply(t, a));\n return typeof v === \"function\" ? v.bind(t) : v;\n },\n });\n}\n\nfunction celldD1(db: any, exec?: (sql: string) => Promise<unknown>): any {\n return new Proxy(db, {\n get(t, p, r) {\n if (p === \"exec\" && exec) return exec;\n const v = Reflect.get(t, p, r);\n if (p === \"prepare\")\n return (sql: string) => {\n guard(sql);\n return celldStatement(v.call(t, sql));\n };\n if (p === \"batch\")\n return async (stmts: unknown[], ...a: unknown[]) =>\n ((await v.call(t, stmts, ...a)) as unknown[]).map(celldMeta);\n if (p === \"withSession\")\n return () => {\n const session = celldD1(t);\n return new Proxy(session, {\n get: (s, q, rr) =>\n q === \"getBookmark\" ? () => \"celld:primary\" : Reflect.get(s, q, rr),\n });\n };\n if (p === \"getBookmark\") return () => \"celld:primary\";\n return typeof v === \"function\" ? v.bind(t) : v;\n },\n });\n}\n\n/** Last fired occurrence per cron expression, in a small SQLite database of the host. */\nfunction cronState(db: ReturnType<ProjectHost[\"openSql\"]>) {\n db.exec(\n \"CREATE TABLE IF NOT EXISTS cron_state (expression TEXT PRIMARY KEY, scheduled_time INTEGER)\",\n [],\n );\n return {\n get: (e: string) => {\n const row = db.exec(\"SELECT scheduled_time FROM cron_state WHERE expression = ?\", [e])\n .rows[0];\n return row ? Number(row[0]) : undefined;\n },\n set: (e: string, t: number) =>\n void db.exec(\"INSERT OR REPLACE INTO cron_state (expression, scheduled_time) VALUES (?, ?)\", [\n e,\n t,\n ]),\n };\n}\n\n/**\n * KV namespaces and D1 databases may omit their ids: wrangler provisions them on deploy, and\n * framework builds (Astro's Cloudflare adapter, for one) emit such entries. A KV namespace\n * then takes its binding name as id; a D1 database its `database_name`, else its binding name.\n * Entries with ids are kept as they are, so storage shared with celld keeps its names.\n */\nexport function withResourceIds(config: WranglerConfig): WranglerConfig {\n const kv = config.kv_namespaces;\n const d1 = config.d1_databases;\n if (!kv?.some((n) => !n.id) && !d1?.some((d) => !d.database_id)) return config;\n return {\n ...config,\n kv_namespaces: kv?.map((n) => (n.id ? n : { ...n, id: n.binding })),\n d1_databases: d1?.map((d) =>\n d.database_id ? d : { ...d, database_id: d.database_name ?? d.binding },\n ),\n };\n}\n\n/** Whether `config` asks for nodejs_compat (the flag, or a `nodejs_compat_*` one). */\nexport function hasNodeCompat(config: WranglerConfig): boolean {\n return (config.compatibility_flags ?? []).some((f) => f.startsWith(\"nodejs_compat\"));\n}\n\n/** The configuration files of a project folder, in the order celld reads them. */\nexport const WRANGLER_FILES = [\"wrangler.jsonc\", \"wrangler.json\"];\n\n/**\n * workerd fills `process.env` with the project's text `vars` under nodejs_compat from\n * compatibility date 2025-04-01 (`nodejs_compat_populate_process_env`), unless\n * `nodejs_compat_do_not_populate_process_env` is set. Frameworks read their settings there\n * (EmDash's `EMDASH_SITE_URL`, for one).\n */\nexport function populatesProcessEnv(config: WranglerConfig): boolean {\n const flags = config.compatibility_flags ?? [];\n if (!hasNodeCompat(config)) return false;\n if (flags.includes(\"nodejs_compat_do_not_populate_process_env\")) return false;\n if (flags.includes(\"nodejs_compat_populate_process_env\")) return true;\n return (config.compatibility_date ?? \"\") >= \"2025-04-01\";\n}\n\n/** The text `vars` of a project, as `process.env` holds them. */\nexport function processEnvOf(config: WranglerConfig): Record<string, string> {\n const env: Record<string, string> = {};\n for (const [k, v] of Object.entries(config.vars ?? {})) if (typeof v === \"string\") env[k] = v;\n return env;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"wrangler.js","sourceRoot":"","sources":["../../src/project/wrangler.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FilesApi } from \"@statewalker/webrun-files\";\nimport type { AssetFiles, AssetsConfig } from \"../bindings/assets.js\";\nimport type { QueueConsumerConfig } from \"../bindings/celld-queues.js\";\nimport type { ModuleLoader } from \"../bindings/worker-loader.js\";\nimport { type WorkersAiOptions, workersAi } from \"../bindings/workers-ai.js\";\nimport { entrypointStub } from \"../core/handles.js\";\nimport type { DurableObjectNamespace } from \"../core/namespace.js\";\nimport {\n type CellRuntime,\n type CellRuntimeOptions,\n createCellRuntime,\n type WorkerModule,\n} from \"../core/runtime.js\";\nimport { splitSqlStatements } from \"../core/sql-split.js\";\nimport { filesApiBlobService } from \"../miniflare-compat/blob-service.js\";\nimport { simulatorFetcher } from \"../miniflare-compat/simulator-fetcher.js\";\nimport { systemClock } from \"../ports.js\";\nimport type { ModuleRule } from \"./module-rules.js\";\n\n/** The subset of wrangler.json(c) that celld deploys (and cellb reads). */\nexport interface WranglerConfig {\n name?: string;\n main?: string;\n compatibility_date?: string;\n compatibility_flags?: string[];\n vars?: Record<string, unknown>;\n durable_objects?: { bindings?: { name: string; class_name: string; script_name?: string }[] };\n migrations?: {\n tag: string;\n new_sqlite_classes?: string[];\n new_classes?: string[];\n renamed_classes?: { from: string; to: string }[];\n deleted_classes?: string[];\n }[];\n kv_namespaces?: { binding: string; id?: string }[];\n d1_databases?: { binding: string; database_name?: string; database_id?: string }[];\n r2_buckets?: { binding: string; bucket_name: string }[];\n queues?: {\n producers?: { binding: string; queue: string; delivery_delay?: number }[];\n consumers?: QueueConsumerConfig[];\n };\n workflows?: WorkflowConfig[];\n triggers?: { crons?: string[] };\n assets?: AssetsConfig;\n services?: { binding: string; service: string; entrypoint?: string; props?: unknown }[];\n worker_loaders?: { binding: string }[];\n /** Workers AI: served by the host's OpenAI-compatible endpoint (`ProjectHost.ai`), if any. */\n ai?: { binding: string };\n /** Module rules: how imports of non-JS files load (`CompiledWasm`, `Data`, `Text`). */\n rules?: ModuleRule[];\n /** Containers (celld runs them with Docker or Podman): not supported, reported. */\n containers?: { class_name: string; image?: string }[];\n}\n\n/** wrangler `workflows` entries. */\nexport interface WorkflowConfig {\n binding: string;\n name: string;\n class_name: string;\n}\n\n/** Runs the Worker's `queue(batch, env, ctx)` handler for a batch celld's queue cell leased. */\ninterface QueueDispatcher {\n deliver(batch: unknown): Promise<void>;\n}\n\nexport interface ProjectHost\n extends Pick<CellRuntimeOptions, \"openSql\" | \"storage\" | \"clock\" | \"peers\" | \"route\"> {\n /** Files of `assets.directory` (path \"/a/b.html\" → bytes), loaded by the host. */\n assetFiles?: AssetFiles;\n /** Runs each loaded Worker in its own realm (celld isolates); classes still use `loadModules`. */\n isolatedModules?: ModuleLoader;\n /** Compiles code given to a Worker Loader binding (esbuild on Node, webrun-modules in browsers). */\n loadModules?: ModuleLoader;\n /** Blob store of the KV simulator (large values): OPFS in a browser, a directory or S3 on a server. */\n files: FilesApi;\n /** The OpenAI-compatible endpoint behind the `ai` binding; without it the binding is unsupported. */\n ai?: WorkersAiOptions;\n /** The binding implementations the config needs: `await loadProjectBindings(config)`. */\n bindings?: ProjectBindings;\n}\n\n/**\n * The implementations of the bindings a project declares, loaded on demand: a project with\n * Durable Objects only loads none of them (Miniflare's D1 simulator, celld's KV, queue and\n * workflow code, R2, assets, cron and Worker Loaders), and a browser bundle keeps them in chunks\n * of their own.\n */\nexport interface ProjectBindings {\n kv?: typeof import(\"../bindings/celld-kv.js\");\n d1?: typeof import(\"../miniflare-compat/vendored.js\");\n queues?: typeof import(\"../bindings/celld-queues.js\");\n workflows?: typeof import(\"../bindings/celld-workflows.js\");\n r2?: typeof import(\"../bindings/r2.js\");\n r2Celld?: typeof import(\"../bindings/r2-celld.js\");\n cron?: typeof import(\"../bindings/cron.js\");\n assets?: typeof import(\"../bindings/assets.js\");\n workerLoader?: typeof import(\"../bindings/worker-loader.js\");\n}\n\n/** Loads the binding implementations `config` declares, for `createProjectRuntime`'s host. */\nexport async function loadProjectBindings(config: WranglerConfig): Promise<ProjectBindings> {\n const when = <T>(cond: unknown, load: () => Promise<T>) =>\n cond ? load() : Promise.resolve(undefined);\n const [kv, d1, queues, workflows, r2, r2Celld, cron, assets, workerLoader] = await Promise.all([\n when(config.kv_namespaces?.length, () => import(\"../bindings/celld-kv.js\")),\n when(config.d1_databases?.length, () => import(\"../miniflare-compat/vendored.js\")),\n when(\n config.queues?.producers?.length || config.queues?.consumers?.length,\n () => import(\"../bindings/celld-queues.js\"),\n ),\n when(config.workflows?.length, () => import(\"../bindings/celld-workflows.js\")),\n when(config.r2_buckets?.length, () => import(\"../bindings/r2.js\")),\n when(config.r2_buckets?.length, () => import(\"../bindings/r2-celld.js\")),\n when(config.triggers?.crons?.length, () => import(\"../bindings/cron.js\")),\n when(config.assets, () => import(\"../bindings/assets.js\")),\n when(config.worker_loaders?.length, () => import(\"../bindings/worker-loader.js\")),\n ]);\n return { kv, d1, queues, workflows, r2, r2Celld, cron, assets, workerLoader };\n}\n\n/** The loaded implementation of a binding the config declares, or an error saying how to load it. */\nfunction binding<K extends keyof ProjectBindings>(\n host: ProjectHost,\n key: K,\n what: string,\n): NonNullable<ProjectBindings[K]> {\n const m = host.bindings?.[key];\n if (!m)\n throw new Error(\n `${what}: the host has no implementation loaded; pass \\`bindings: await loadProjectBindings(config)\\``,\n );\n return m as NonNullable<ProjectBindings[K]>;\n}\n\nexport interface ProjectRuntime {\n runtime: CellRuntime;\n /** Configuration entries cellb does not support yet (reported, not silently ignored). */\n unsupported: string[];\n}\n\n/**\n * What `env` of `cloudflare:workers` holds while the Worker's module is evaluated, before the\n * runtime exists: the vars, and the bindings that need no runtime (`ai`; Flue's entry reads\n * `env.AI` at load).\n */\nexport function loadTimeEnv(\n config: WranglerConfig,\n ai?: WorkersAiOptions,\n): Record<string, unknown> {\n const env: Record<string, unknown> = { ...config.vars };\n if (config.ai && ai) env[config.ai.binding] = workersAi(ai);\n return env;\n}\n\n// Internal bindings carrying the runtime-supplied objects behind KV and D1.\nconst KV_OBJECTS = \"__CELLS_KV_OBJECTS\";\nconst D1_OBJECTS = \"__CELLS_D1_OBJECTS\";\nconst QUEUE_OBJECTS = \"__CELLS_QUEUE_OBJECTS\";\nconst WORKFLOW_OBJECTS = \"__CELLS_WORKFLOW_OBJECTS\";\n\n/**\n * Builds a runtime from a wrangler config and the Worker's module namespace — the same\n * inputs celld deploys. Hosts differ only in `host` (storage) and in how they load `main`.\n */\nexport function createProjectRuntime(\n config: WranglerConfig,\n module: WorkerModule,\n host: ProjectHost,\n): ProjectRuntime {\n config = withResourceIds(config);\n const unsupported: string[] = [];\n const durableObjects: NonNullable<CellRuntimeOptions[\"durableObjects\"]> = {};\n const sqliteClasses = new Set<string>();\n for (const m of config.migrations ?? []) {\n for (const c of m.new_sqlite_classes ?? []) sqliteClasses.add(c);\n for (const c of m.new_classes ?? []) sqliteClasses.add(c); // KV-backed on Cloudflare; SQLite here (superset)\n for (const r of m.renamed_classes ?? [])\n unsupported.push(`migrations.renamed_classes (${r.from} → ${r.to})`);\n }\n // wrangler's module rule types: the bundles apply CompiledWasm, Data and Text (module-rules.ts)\n for (const [i, r] of (config.rules ?? []).entries())\n if (![\"ESModule\", \"CommonJS\", \"CompiledWasm\", \"Data\", \"Text\"].includes(r.type))\n unsupported.push(`rules[${i}].type \"${r.type}\"`);\n for (const c of config.containers ?? [])\n unsupported.push(`containers[${c.class_name}] (cellb runs no containers)`);\n for (const b of config.durable_objects?.bindings ?? []) {\n if (b.script_name) unsupported.push(`durable_objects.bindings[${b.name}].script_name`);\n durableObjects[b.name] = { className: b.class_name };\n }\n const worker: WorkerModule = { ...module };\n let kv: ReturnType<NonNullable<ProjectBindings[\"kv\"]>[\"celldKv\"]> | undefined;\n if (config.kv_namespaces?.length) {\n kv = binding(host, \"kv\", \"kv_namespaces\").celldKv(host.files);\n worker.__KvNamespace = kv.KvNamespaceCell as never;\n durableObjects[KV_OBJECTS] = { className: \"__KvNamespace\" };\n }\n if (config.d1_databases?.length) {\n worker.__D1Database = binding(host, \"d1\", \"d1_databases\").D1DatabaseObject;\n durableObjects[D1_OBJECTS] = { className: \"__D1Database\" };\n }\n // Queues: every queue is a cell of a runtime-supplied class (as on celld).\n const consumers = new Map((config.queues?.consumers ?? []).map((c) => [c.queue, c]));\n // celld's own queue code (vendor/celld/queues.js): its queue cell, producer and consumer\n // batch, so a queue's cell (and pending messages) is celld's format.\n let queueDispatcher: QueueDispatcher | undefined;\n let queues: ReturnType<NonNullable<ProjectBindings[\"queues\"]>[\"celldQueues\"]> | undefined;\n if (config.queues?.producers?.length || consumers.size) {\n queues = binding(host, \"queues\", \"queues\").celldQueues({\n namespace: () => runtime.env[QUEUE_OBJECTS] as never,\n consumers: [...consumers.values()],\n compatibilityDate: config.compatibility_date,\n runConsumer: (batch) => queueDispatcher!.deliver(batch as never),\n });\n worker.__Queue = queues.QueueCell as never;\n durableObjects[QUEUE_OBJECTS] = { className: \"__Queue\" };\n }\n // Workflows: every instance is a cell of a runtime-supplied class (as on celld).\n // celld's own workflow code (vendor/celld/workflows.js): its instance cell and binding.\n let workflows:\n | ReturnType<NonNullable<ProjectBindings[\"workflows\"]>[\"celldWorkflows\"]>\n | undefined;\n if (config.workflows?.length) {\n workflows = binding(host, \"workflows\", \"workflows\").celldWorkflows({\n script: config.name ?? \"worker\",\n workflows: Object.fromEntries(config.workflows.map((w) => [w.name, w.class_name])),\n exports: () => module as Record<string, unknown>,\n env: () => runtime.env,\n namespace: () => runtime.env[WORKFLOW_OBJECTS],\n });\n worker[workflows.className] = workflows.WorkflowCell as never;\n durableObjects[WORKFLOW_OBJECTS] = { className: workflows.className };\n }\n if (config.ai && !host.ai)\n unsupported.push(\n `ai[${config.ai.binding}] (Workers AI: give the host an OpenAI-compatible \\`ai\\`)`,\n );\n for (const s of config.services ?? [])\n if (s.service !== config.name)\n unsupported.push(\n `services[${s.binding}] → \"${s.service}\" (only this script's own entrypoints)`,\n );\n const sqlExtensions: string[] = [];\n let deleteAllPreservesAlarm = false;\n for (const f of config.compatibility_flags ?? []) {\n if (f === \"delete_all_preserves_alarm\") deleteAllPreservesAlarm = true;\n else if (f === \"delete_all_deletes_alarm\")\n continue; // the default\n else if (f === \"sqlite_vec\")\n sqlExtensions.push(\"sqlite_vec\"); // vec0 virtual tables, as on celld\n else if (f === \"nodejs_compat\" || f === \"nodejs_compat_v2\")\n continue; // the host's bundler maps node:*\n else if (f === \"websocket_standard_binary_type\")\n continue; // the host picks the project's WebSocketPair\n else if (\n f === \"nodejs_compat_populate_process_env\" ||\n f === \"nodejs_compat_do_not_populate_process_env\"\n )\n continue; // the host fills process.env or not (populatesProcessEnv)\n else unsupported.push(`compatibility_flags: ${f}`);\n }\n\n const runtime = createCellRuntime({\n worker,\n durableObjects,\n vars: { ...config.vars, MINIFLARE_BLOBS: filesApiBlobService(host.files) },\n openSql: host.openSql,\n sqlExtensions,\n deleteAllPreservesAlarm,\n scriptName: config.name ?? \"worker\",\n // celld's fleet-wide namespaces for the resources several scripts can share.\n namespaceKeys: {\n __KvNamespace: \"cells:v1:kv:__KvNamespace\",\n __D1Database: \"cells:v1:d1:__D1Database\",\n __Queue: \"cells:v1:queue:__Queue\",\n },\n storage: host.storage,\n clock: host.clock,\n peers: host.peers,\n route: host.route,\n });\n const env = runtime.env as Record<string, unknown>;\n if (config.ai && host.ai) env[config.ai.binding] = workersAi(host.ai);\n // KV: celld's own client against celld's own namespace cell (cell name \"<id>/<shard>\").\n for (const ns of config.kv_namespaces ?? [])\n env[ns.binding] = new kv!.KvNamespace(() => env[KV_OBJECTS], `${ns.id}/0`);\n for (const p of config.queues?.producers ?? [])\n env[p.binding] = queues!.producer(p.queue, p.delivery_delay ?? 0);\n if (consumers.size) {\n const handler = (module.default as { queue?: (b: unknown, e: unknown, c: unknown) => unknown })\n .queue;\n if (typeof handler !== \"function\")\n unsupported.push(\"queues.consumers without a queue() handler\");\n queueDispatcher = {\n deliver: async (batch) => {\n const pending: Promise<unknown>[] = [];\n await handler?.call(module.default, batch, env, {\n waitUntil: (p: Promise<unknown>) => pending.push(p),\n passThroughOnException() {},\n });\n await Promise.allSettled(pending);\n },\n };\n }\n // The isolates of loaded Workers end with the runtime (on Node, a worker thread's port would\n // keep the process alive; in a browser, a Dedicated Worker would outlive the runtime).\n const isolated = host.isolatedModules as\n | (ModuleLoader & { close?(): void | Promise<void> })\n | undefined;\n if (config.worker_loaders?.length && isolated?.close) {\n const close = runtime.close.bind(runtime);\n runtime.close = async () => {\n await close();\n await isolated.close?.();\n };\n }\n for (const l of config.worker_loaders ?? []) {\n if (!host.loadModules) {\n unsupported.push(`worker_loaders[${l.binding}] (the host provides no module loader)`);\n continue;\n }\n const { workerLoader } = binding(host, \"workerLoader\", \"worker_loaders\");\n env[l.binding] = host.isolatedModules\n ? workerLoader(host.isolatedModules) // facets of loaded code run in the isolate as well\n : workerLoader(host.loadModules);\n }\n // Cron Triggers (validated at load time like `celld deploy` does).\n const crons = config.triggers?.crons ?? [];\n if (crons.length) {\n const scheduled = (\n module.default as { scheduled?: (c: unknown, e: unknown, x: unknown) => unknown }\n ).scheduled;\n if (typeof scheduled !== \"function\")\n unsupported.push(\"triggers.crons without a scheduled() handler\");\n else {\n const db = host.openSql(\"__cellb/cron\");\n const stop = binding(host, \"cron\", \"triggers.crons\").startCronTriggers(\n crons,\n (c, x) => runtime.runEvent(() => scheduled.call(module.default, c, env, x)),\n host.clock ?? systemClock,\n cronState(db),\n );\n const close = runtime.close.bind(runtime);\n runtime.close = async () => {\n stop();\n db.close();\n await close();\n };\n }\n }\n // Static assets: routed before the Worker; `assets.binding` exposes env.ASSETS.\n if (config.assets) {\n const hasWorker = typeof (module.default as { fetch?: unknown })?.fetch === \"function\";\n if (host.assetFiles?.has(\"/.assetsignore\"))\n throw new Error(\n `${config.assets.directory ?? \"assets\"}/.assetsignore is not supported by celld; remove it`,\n );\n const assets = binding(host, \"assets\", \"assets\").createAssets(\n host.assetFiles ?? new Map(),\n config.assets,\n hasWorker,\n );\n if (config.assets.binding) env[config.assets.binding] = assets.binding;\n const workerFetch = runtime.fetch.bind(runtime);\n runtime.fetch = async (req) =>\n assets.route(req) ??\n (hasWorker ? workerFetch(req) : new Response(\"Not found\", { status: 404 }));\n }\n for (const w of config.workflows ?? []) env[w.binding] = workflows!.binding(w.name);\n // Service bindings to this script's own entrypoints (a celld fleet runs one application):\n // default export or a named WorkerEntrypoint, with fetch() and JS RPC.\n for (const s of config.services ?? []) {\n if (s.service !== config.name) continue;\n const target = s.entrypoint ? module[s.entrypoint] : module.default;\n if (!target)\n unsupported.push(`services[${s.binding}].entrypoint \"${s.entrypoint}\" is not exported`);\n else env[s.binding] = entrypointStub(target, env, s.props);\n }\n // R2 objects live directly in the host's store, as celld keeps them in the fleet bucket.\n // With a celld fleet bucket, R2 objects live in it as celld keeps them; else in the FilesApi.\n for (const r2 of config.r2_buckets ?? []) {\n const { r2Bucket, r2BucketOn } = binding(host, \"r2\", \"r2_buckets\");\n const { celldR2Backend } = binding(host, \"r2Celld\", \"r2_buckets\");\n env[r2.binding] = host.storage?.objects\n ? r2BucketOn(celldR2Backend(host.storage.objects, r2.bucket_name), r2.binding)\n : r2Bucket(host.files, `/r2/${r2.bucket_name}`, r2.binding);\n }\n for (const d1 of config.d1_databases ?? [])\n env[d1.binding] = celldExec(\n binding(host, \"d1\", \"d1_databases\").makeD1Binding({\n fetcher: simulatorFetcher(\n env[D1_OBJECTS] as DurableObjectNamespace,\n d1.database_id as string, // set by withResourceIds\n ) as never,\n }) as D1Like,\n );\n for (const name of [...sqliteClasses])\n if (!Object.values(durableObjects).some((d) => d.className === name)) {\n // A migrated class without a binding is fine (reachable through other code paths only).\n }\n return { runtime, unsupported };\n}\n\ninterface D1Like {\n exec(sql: string): Promise<{ count: number; duration: number }>;\n prepare(sql: string): { run(): Promise<unknown> };\n}\n\n/**\n * `D1Database#exec` as celld implements it: statements are split by SQL syntax.\n * workerd's d1-api.ts splits on NEWLINES (Cloudflare's documented behaviour), so a\n * multi-line `CREATE TABLE` fails there but works on celld — and celld is the\n * reference here (verified on celld 0.6.2 by the d1 example in conformance/).\n */\nfunction celldExec<T extends D1Like>(db: T): T {\n const exec = async (sql: string) => {\n const t0 = Date.now();\n const statements = splitSqlStatements(sql).filter((s) => s.trim());\n for (const statement of statements) {\n if (/^\\s*BEGIN\\b/i.test(statement))\n throw new Error(\n \"D1_EXEC_ERROR: the SQL ends in an incomplete statement, which did not run: terminate the last statement with a semicolon\",\n );\n guard(statement);\n await db.prepare(statement).run();\n }\n return { count: statements.length, duration: Date.now() - t0 };\n };\n return celldD1(db, exec) as T;\n}\n\n/**\n * celld's D1 rules on top of workerd's client (celld docs/services/d1.md, checked by the\n * d1-details project): ATTACH/DETACH and TEMP objects are \"not authorized\", VACUUM is\n * \"authorization denied\"; there is one primary and no replica, so sessions return the\n * bookmark \"celld:primary\" and every result reports served_by_primary/served_by_region\n * \"local\"; a read-only statement reports last_row_id and changes as 0.\n */\nfunction guard(sql: string): void {\n if (/^\\s*(ATTACH|DETACH)\\b/i.test(sql) || /^\\s*CREATE\\s+(TEMP|TEMPORARY)\\b/i.test(sql))\n throw new Error(\"D1_ERROR: not authorized\");\n if (/^\\s*VACUUM\\b/i.test(sql)) throw new Error(\"D1_ERROR: authorization denied\");\n}\n\nfunction celldMeta(r: any): any {\n if (!r?.meta) return r;\n r.meta.served_by_primary = true;\n r.meta.served_by_region = \"local\";\n if (r.meta.changed_db === false) {\n r.meta.last_row_id = 0;\n r.meta.changes = 0;\n }\n return r;\n}\n\nfunction celldStatement(stmt: any): any {\n return new Proxy(stmt, {\n get(t, p, r) {\n const v = Reflect.get(t, p, r);\n if (p === \"bind\") return (...a: unknown[]) => celldStatement(v.apply(t, a));\n if (p === \"run\" || p === \"all\")\n return async (...a: unknown[]) => celldMeta(await v.apply(t, a));\n return typeof v === \"function\" ? v.bind(t) : v;\n },\n });\n}\n\nfunction celldD1(db: any, exec?: (sql: string) => Promise<unknown>): any {\n return new Proxy(db, {\n get(t, p, r) {\n if (p === \"exec\" && exec) return exec;\n const v = Reflect.get(t, p, r);\n if (p === \"prepare\")\n return (sql: string) => {\n guard(sql);\n return celldStatement(v.call(t, sql));\n };\n if (p === \"batch\")\n return async (stmts: unknown[], ...a: unknown[]) =>\n ((await v.call(t, stmts, ...a)) as unknown[]).map(celldMeta);\n if (p === \"withSession\")\n return () => {\n const session = celldD1(t);\n return new Proxy(session, {\n get: (s, q, rr) =>\n q === \"getBookmark\" ? () => \"celld:primary\" : Reflect.get(s, q, rr),\n });\n };\n if (p === \"getBookmark\") return () => \"celld:primary\";\n return typeof v === \"function\" ? v.bind(t) : v;\n },\n });\n}\n\n/** Last fired occurrence per cron expression, in a small SQLite database of the host. */\nfunction cronState(db: ReturnType<ProjectHost[\"openSql\"]>) {\n db.exec(\n \"CREATE TABLE IF NOT EXISTS cron_state (expression TEXT PRIMARY KEY, scheduled_time INTEGER)\",\n [],\n );\n return {\n get: (e: string) => {\n const row = db.exec(\"SELECT scheduled_time FROM cron_state WHERE expression = ?\", [e])\n .rows[0];\n return row ? Number(row[0]) : undefined;\n },\n set: (e: string, t: number) =>\n void db.exec(\"INSERT OR REPLACE INTO cron_state (expression, scheduled_time) VALUES (?, ?)\", [\n e,\n t,\n ]),\n };\n}\n\n/**\n * KV namespaces and D1 databases may omit their ids: wrangler provisions them on deploy, and\n * framework builds (Astro's Cloudflare adapter, for one) emit such entries. A KV namespace\n * then takes its binding name as id; a D1 database its `database_name`, else its binding name.\n * Entries with ids are kept as they are, so storage shared with celld keeps its names.\n */\nexport function withResourceIds(config: WranglerConfig): WranglerConfig {\n const kv = config.kv_namespaces;\n const d1 = config.d1_databases;\n if (!kv?.some((n) => !n.id) && !d1?.some((d) => !d.database_id)) return config;\n return {\n ...config,\n kv_namespaces: kv?.map((n) => (n.id ? n : { ...n, id: n.binding })),\n d1_databases: d1?.map((d) =>\n d.database_id ? d : { ...d, database_id: d.database_name ?? d.binding },\n ),\n };\n}\n\n/**\n * Whether `config` asks for nodejs_compat: the `nodejs_compat` or `nodejs_compat_v2` flag, as in\n * workerd and Wrangler. Other `nodejs_compat_*` flags (the process.env ones) tune nodejs_compat\n * and do nothing without it.\n */\nexport function hasNodeCompat(config: WranglerConfig): boolean {\n return (config.compatibility_flags ?? []).some(\n (f) => f === \"nodejs_compat\" || f === \"nodejs_compat_v2\",\n );\n}\n\n/** The configuration files of a project folder, in the order celld reads them. */\nexport const WRANGLER_FILES = [\"wrangler.jsonc\", \"wrangler.json\"];\n\n/**\n * workerd fills `process.env` with the project's text `vars` under nodejs_compat from\n * compatibility date 2025-04-01 (`nodejs_compat_populate_process_env`), unless\n * `nodejs_compat_do_not_populate_process_env` is set. Frameworks read their settings there\n * (EmDash's `EMDASH_SITE_URL`, for one).\n */\nexport function populatesProcessEnv(config: WranglerConfig): boolean {\n const flags = config.compatibility_flags ?? [];\n if (!hasNodeCompat(config)) return false;\n if (flags.includes(\"nodejs_compat_do_not_populate_process_env\")) return false;\n if (flags.includes(\"nodejs_compat_populate_process_env\")) return true;\n return (config.compatibility_date ?? \"\") >= \"2025-04-01\";\n}\n\n/** The text `vars` of a project, as `process.env` holds them. */\nexport function processEnvOf(config: WranglerConfig): Record<string, string> {\n const env: Record<string, string> = {};\n for (const [k, v] of Object.entries(config.vars ?? {})) if (typeof v === \"string\") env[k] = v;\n return env;\n}\n"]}
|
package/package.json
CHANGED