@statewalker/cellb 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +46 -3
  2. package/bin/cellb.mjs +20 -0
  3. package/dist/browser.d.ts +2 -0
  4. package/dist/browser.js +1 -0
  5. package/dist/browser.js.map +1 -1
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.js +62 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/isolate/browser.d.ts +2 -1
  10. package/dist/isolate/browser.js +2 -1
  11. package/dist/isolate/browser.js.map +1 -1
  12. package/dist/isolate/isolate.js +5 -3
  13. package/dist/isolate/isolate.js.map +1 -1
  14. package/dist/isolate/protocol.d.ts +4 -2
  15. package/dist/isolate/protocol.js +4 -4
  16. package/dist/isolate/protocol.js.map +1 -1
  17. package/dist/node.d.ts +3 -0
  18. package/dist/node.js +2 -0
  19. package/dist/node.js.map +1 -1
  20. package/dist/project/browser-host.d.ts +6 -12
  21. package/dist/project/browser-host.js +2 -25
  22. package/dist/project/browser-host.js.map +1 -1
  23. package/dist/project/browser-load.d.ts +22 -0
  24. package/dist/project/browser-load.js +63 -0
  25. package/dist/project/browser-load.js.map +1 -0
  26. package/dist/project/build.d.ts +14 -0
  27. package/dist/project/build.js +53 -0
  28. package/dist/project/build.js.map +1 -0
  29. package/dist/project/built-project.d.ts +88 -0
  30. package/dist/project/built-project.js +118 -0
  31. package/dist/project/built-project.js.map +1 -0
  32. package/dist/project/node-load.d.ts +14 -0
  33. package/dist/project/node-load.js +187 -0
  34. package/dist/project/node-load.js.map +1 -0
  35. package/dist/project/wrangler.d.ts +9 -0
  36. package/dist/project/wrangler.js +24 -0
  37. package/dist/project/wrangler.js.map +1 -1
  38. package/dist/ws/server.d.ts +24 -6
  39. package/dist/ws/server.js +52 -16
  40. package/dist/ws/server.js.map +1 -1
  41. package/package.json +6 -1
@@ -0,0 +1,187 @@
1
+ /**
2
+ * `loadProject` on Node (`@statewalker/cellb/node`): one call that reads a project, built or
3
+ * not, and runs it.
4
+ */
5
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
6
+ import { tmpdir } from "node:os";
7
+ import { dirname, join, resolve } from "node:path";
8
+ import { fileURLToPath, pathToFileURL } from "node:url";
9
+ import { MemFilesApi } from "@statewalker/webrun-files-mem";
10
+ import { NodeFilesApi } from "@statewalker/webrun-files-node";
11
+ import { nodeSqliteOpener } from "../adapters/node-sqlite.js";
12
+ import { BUILD_MANIFEST, BUILT_WORKER, filesApiReader, isFilesApi, readBuildManifest, readBuiltProject, urlReader, } from "./built-project.js";
13
+ import * as workersClasses from "./cloudflare-workers.js";
14
+ import { loadNodeProject, nodeIsolatedLoader, nodeModuleLoader } from "./node-project.js";
15
+ import { workerScope } from "./worker-scope.js";
16
+ import * as workersGlobals from "./workers-globals-module.js";
17
+ import { createProjectRuntime, loadTimeEnv, populatesProcessEnv, processEnvOf, } from "./wrangler.js";
18
+ /**
19
+ * Loads a project and runs it in this process.
20
+ *
21
+ * `source`: a folder with `wrangler.json(c)` (its `main` bundled with esbuild, as
22
+ * `loadNodeProject` does), a folder written by `cellb build` (its `worker.js` imported as built),
23
+ * an `http(s):` URL of a built folder, or a FilesApi holding either kind of folder.
24
+ *
25
+ * `options.data`: a directory for the cells' SQLite files and the project's files
26
+ * (`<data>/files`); without it, both are in memory.
27
+ */
28
+ export async function loadProject(source, options = {}) {
29
+ const host = nodeHost(options);
30
+ const close = async (runtime, cleanup) => {
31
+ await runtime.close();
32
+ cleanup?.();
33
+ };
34
+ // A folder on disk: read where it lies.
35
+ const dir = localDir(source);
36
+ if (dir !== undefined) {
37
+ const reader = fsReader(dir);
38
+ const manifest = await readBuildManifest(reader);
39
+ if (manifest)
40
+ return runBuilt(await readBuiltProject(reader, manifest), host);
41
+ const { runtime, unsupported, config } = await loadNodeProject(dir, host);
42
+ return {
43
+ config,
44
+ runtime,
45
+ unsupported,
46
+ fetch: (req) => runtime.fetch(req),
47
+ close: () => close(runtime),
48
+ };
49
+ }
50
+ // A FilesApi: a built folder is read from it; a source folder is copied out for esbuild.
51
+ if (isFilesApi(source)) {
52
+ const reader = filesApiReader(source);
53
+ const manifest = await readBuildManifest(reader);
54
+ if (manifest)
55
+ return runBuilt(await readBuiltProject(reader, manifest), host);
56
+ const tmp = await copyOut(source);
57
+ try {
58
+ const { runtime, unsupported, config } = await loadNodeProject(tmp, host);
59
+ return {
60
+ config,
61
+ runtime,
62
+ unsupported,
63
+ fetch: (req) => runtime.fetch(req),
64
+ close: () => close(runtime, () => rmSync(tmp, { recursive: true, force: true })),
65
+ };
66
+ }
67
+ catch (err) {
68
+ rmSync(tmp, { recursive: true, force: true });
69
+ throw err;
70
+ }
71
+ }
72
+ // A URL of a built folder.
73
+ const url = folderUrl(source);
74
+ const reader = urlReader(url);
75
+ const manifest = await readBuildManifest(reader);
76
+ if (!manifest)
77
+ throw new Error(`${url} has no ${BUILD_MANIFEST}: load a folder written by \`cellb build\``);
78
+ return runBuilt(await readBuiltProject(reader, manifest), host);
79
+ }
80
+ /** What `options` become on Node: SQLite files and a FilesApi under `data`, or memory. */
81
+ function nodeHost(options) {
82
+ let files;
83
+ if (options.data) {
84
+ const data = resolve(options.data);
85
+ mkdirSync(join(data, "files"), { recursive: true });
86
+ files = new NodeFilesApi({ rootDir: join(data, "files") });
87
+ }
88
+ else
89
+ files = new MemFilesApi();
90
+ return {
91
+ openSql: nodeSqliteOpener(options.data ? resolve(options.data) : undefined),
92
+ files,
93
+ storage: options.bucket,
94
+ ai: options.ai,
95
+ };
96
+ }
97
+ /**
98
+ * Runs a built project on Node: `worker.js` was bundled for a browser realm, so it reads the
99
+ * Workers globals and `cloudflare:workers` from the globals this sets, as in a browser worker.
100
+ * (One such project per process: the globals are the process's.)
101
+ */
102
+ async function runBuilt(built, host) {
103
+ const { config } = built;
104
+ const flags = config.compatibility_flags ?? [];
105
+ const scope = workerScope(loadTimeEnv(config, host.ai));
106
+ const g = globalThis;
107
+ g.__cellsWorkersModule = workersClasses;
108
+ g.__cellsProjectScope = scope;
109
+ g.__cellsGlobals = {
110
+ ...workersGlobals,
111
+ Request: workersGlobals.CellsRequest,
112
+ Response: workersGlobals.CellsResponse,
113
+ WebSocketPair: flags.includes("websocket_standard_binary_type")
114
+ ? workersGlobals.StandardWebSocketPair
115
+ : workersGlobals.WebSocketPair,
116
+ };
117
+ if (populatesProcessEnv(config)) {
118
+ const env = processEnvOf(config);
119
+ g.__cellsProcessEnv = env;
120
+ for (const [k, v] of Object.entries(env))
121
+ process.env[k] ??= v;
122
+ }
123
+ let module = { default: {} };
124
+ if (built.code !== null) {
125
+ const tmp = mkdtempSync(join(tmpdir(), "cellb-built-"));
126
+ const file = join(tmp, BUILT_WORKER.replace(/\.js$/, ".mjs"));
127
+ writeFileSync(file, built.code);
128
+ try {
129
+ module = (await import(/* @vite-ignore */ pathToFileURL(file).href));
130
+ }
131
+ finally {
132
+ rmSync(tmp, { recursive: true, force: true });
133
+ }
134
+ }
135
+ const project = createProjectRuntime(config, module, {
136
+ loadModules: nodeModuleLoader,
137
+ isolatedModules: nodeIsolatedLoader(() => host.storage),
138
+ assetFiles: built.assets,
139
+ ...host,
140
+ });
141
+ scope.bind(project.runtime);
142
+ const { runtime, unsupported } = project;
143
+ return {
144
+ config,
145
+ runtime,
146
+ unsupported,
147
+ fetch: (req) => runtime.fetch(req),
148
+ close: () => runtime.close(),
149
+ };
150
+ }
151
+ /** The folder a source names on this machine: a path or a `file:` URL. */
152
+ function localDir(source) {
153
+ if (typeof source === "string") {
154
+ if (/^https?:\/\//i.test(source))
155
+ return undefined;
156
+ return resolve(source.startsWith("file:") ? fileURLToPath(source) : source);
157
+ }
158
+ if (source instanceof URL && source.protocol === "file:")
159
+ return fileURLToPath(source);
160
+ return undefined;
161
+ }
162
+ function folderUrl(source) {
163
+ const url = new URL(String(source));
164
+ if (!url.pathname.endsWith("/"))
165
+ url.pathname += "/";
166
+ return url;
167
+ }
168
+ function fsReader(dir) {
169
+ return {
170
+ async bytes(path) {
171
+ const full = join(dir, path);
172
+ return existsSync(full) ? new Uint8Array(readFileSync(full)) : undefined;
173
+ },
174
+ };
175
+ }
176
+ /** Copies a FilesApi's files into a temporary folder (esbuild bundles from disk). */
177
+ async function copyOut(files) {
178
+ const tmp = mkdtempSync(join(tmpdir(), "cellb-project-"));
179
+ const reader = filesApiReader(files);
180
+ for (const path of (await reader.list?.("/")) ?? []) {
181
+ const out = join(tmp, path);
182
+ mkdirSync(dirname(out), { recursive: true });
183
+ writeFileSync(out, (await reader.bytes(path)));
184
+ }
185
+ return tmp;
186
+ }
187
+ //# sourceMappingURL=node-load.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-load.js","sourceRoot":"","sources":["../../src/project/node-load.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClG,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAG9D,OAAO,EACL,cAAc,EACd,YAAY,EAEZ,cAAc,EACd,UAAU,EAKV,iBAAiB,EACjB,gBAAgB,EAChB,SAAS,GACV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1F,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,cAAc,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EACL,oBAAoB,EACpB,WAAW,EAEX,mBAAmB,EACnB,YAAY,GACb,MAAM,eAAe,CAAC;AAIvB;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAqB,EACrB,OAAO,GAA2B,EAAE;IAEpC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,EAAE,OAAmC,EAAE,OAAoB,EAAE,EAAE;QAChF,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,EAAE,EAAE,CAAC;IACd,CAAC,CAAC;IACF,wCAAwC;IACxC,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACjD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC,MAAM,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9E,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1E,OAAO;YACL,MAAM;YACN,OAAO;YACP,WAAW;YACX,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;YAClC,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;SAC5B,CAAC;IACJ,CAAC;IACD,yFAAyF;IACzF,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACjD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC,MAAM,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9E,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC1E,OAAO;gBACL,MAAM;gBACN,OAAO;gBACP,WAAW;gBACX,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;gBAClC,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;aACjF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IACD,2BAA2B;IAC3B,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACjD,IAAI,CAAC,QAAQ;QACX,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,WAAW,cAAc,4CAA4C,CAAC,CAAC;IAC/F,OAAO,QAAQ,CAAC,MAAM,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;AAClE,CAAC;AAED,0FAA0F;AAC1F,SAAS,QAAQ,CAAC,OAA+B;IAC/C,IAAI,KAAe,CAAC;IACpB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,KAAK,GAAG,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7D,CAAC;;QAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;IACjC,OAAO;QACL,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3E,KAAK;QACL,OAAO,EAAE,OAAO,CAAC,MAAM;QACvB,EAAE,EAAE,OAAO,CAAC,EAAE;KACf,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,QAAQ,CACrB,KAAmB,EACnB,IAAsC;IAEtC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IACzB,MAAM,KAAK,GAAG,MAAM,CAAC,mBAAmB,IAAI,EAAE,CAAC;IAC/C,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACxD,MAAM,CAAC,GAAG,UAAqC,CAAC;IAChD,CAAC,CAAC,oBAAoB,GAAG,cAAc,CAAC;IACxC,CAAC,CAAC,mBAAmB,GAAG,KAAK,CAAC;IAC9B,CAAC,CAAC,cAAc,GAAG;QACjB,GAAG,cAAc;QACjB,OAAO,EAAE,cAAc,CAAC,YAAY;QACpC,QAAQ,EAAE,cAAc,CAAC,aAAa;QACtC,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,gCAAgC,CAAC;YAC7D,CAAC,CAAC,cAAc,CAAC,qBAAqB;YACtC,CAAC,CAAC,cAAc,CAAC,aAAa;KACjC,CAAC;IACF,IAAI,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC,CAAC,iBAAiB,GAAG,GAAG,CAAC;QAC1B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,MAAM,GAAiB,EAAE,OAAO,EAAE,EAAE,EAAkB,CAAC;IAC3D,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QAC9D,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,kBAAkB,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAiB,CAAC;QACvF,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE;QACnD,WAAW,EAAE,gBAAgB;QAC7B,eAAe,EAAE,kBAAkB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;QACvD,UAAU,EAAE,KAAK,CAAC,MAAM;QACxB,GAAG,IAAI;KACR,CAAC,CAAC;IACH,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5B,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IACzC,OAAO;QACL,MAAM;QACN,OAAO;QACP,WAAW;QACX,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;QAClC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE;KAC7B,CAAC;AACJ,CAAC;AAED,0EAA0E;AAC1E,SAAS,QAAQ,CAAC,MAAqB;IACrC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,IAAI,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,OAAO,SAAS,CAAC;QACnD,OAAO,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;IACvF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,SAAS,CAAC,MAAqB;IACtC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACpC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC;IACrD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW;IAC3B,OAAO;QACL,KAAK,CAAC,KAAK,CAAC,IAAI;YACd,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC7B,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3E,CAAC;KACF,CAAC;AACJ,CAAC;AAED,qFAAqF;AACrF,KAAK,UAAU,OAAO,CAAC,KAAe;IACpC,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC5B,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,aAAa,CAAC,GAAG,EAAE,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAe,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC","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 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 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"]}
@@ -114,3 +114,12 @@ export declare function createProjectRuntime(config: WranglerConfig, module: Wor
114
114
  * Entries with ids are kept as they are, so storage shared with celld keeps its names.
115
115
  */
116
116
  export declare function withResourceIds(config: WranglerConfig): WranglerConfig;
117
+ /**
118
+ * workerd fills `process.env` with the project's text `vars` under nodejs_compat from
119
+ * compatibility date 2025-04-01 (`nodejs_compat_populate_process_env`), unless
120
+ * `nodejs_compat_do_not_populate_process_env` is set. Frameworks read their settings there
121
+ * (EmDash's `EMDASH_SITE_URL`, for one).
122
+ */
123
+ export declare function populatesProcessEnv(config: WranglerConfig): boolean;
124
+ /** The text `vars` of a project, as `process.env` holds them. */
125
+ export declare function processEnvOf(config: WranglerConfig): Record<string, string>;
@@ -349,4 +349,28 @@ export function withResourceIds(config) {
349
349
  d1_databases: d1?.map((d) => d.database_id ? d : { ...d, database_id: d.database_name ?? d.binding }),
350
350
  };
351
351
  }
352
+ /**
353
+ * workerd fills `process.env` with the project's text `vars` under nodejs_compat from
354
+ * compatibility date 2025-04-01 (`nodejs_compat_populate_process_env`), unless
355
+ * `nodejs_compat_do_not_populate_process_env` is set. Frameworks read their settings there
356
+ * (EmDash's `EMDASH_SITE_URL`, for one).
357
+ */
358
+ export function populatesProcessEnv(config) {
359
+ const flags = config.compatibility_flags ?? [];
360
+ if (!flags.some((f) => f.startsWith("nodejs_compat")))
361
+ return false;
362
+ if (flags.includes("nodejs_compat_do_not_populate_process_env"))
363
+ return false;
364
+ if (flags.includes("nodejs_compat_populate_process_env"))
365
+ return true;
366
+ return (config.compatibility_date ?? "") >= "2025-04-01";
367
+ }
368
+ /** The text `vars` of a project, as `process.env` holds them. */
369
+ export function processEnvOf(config) {
370
+ const env = {};
371
+ for (const [k, v] of Object.entries(config.vars ?? {}))
372
+ if (typeof v === "string")
373
+ env[k] = v;
374
+ return env;
375
+ }
352
376
  //# sourceMappingURL=wrangler.js.map
@@ -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, type AssetsConfig, createAssets } from \"../bindings/assets.js\";\nimport { celldKv } from \"../bindings/celld-kv.js\";\nimport { celldQueues, type QueueConsumerConfig } from \"../bindings/celld-queues.js\";\nimport { celldWorkflows } from \"../bindings/celld-workflows.js\";\nimport { startCronTriggers } from \"../bindings/cron.js\";\nimport { r2Bucket, r2BucketOn } from \"../bindings/r2.js\";\nimport { celldR2Backend } from \"../bindings/r2-celld.js\";\nimport { type ModuleLoader, workerLoader } 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 { D1DatabaseObject, makeD1Binding } from \"../miniflare-compat/vendored.js\";\nimport { systemClock } from \"../ports.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 /** 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}\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 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<typeof celldKv> | undefined;\n if (config.kv_namespaces?.length) {\n kv = 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 = 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<typeof celldQueues> | undefined;\n if (config.queues?.producers?.length || consumers.size) {\n 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: ReturnType<typeof celldWorkflows> | undefined;\n if (config.workflows?.length) {\n 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 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 else\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 = 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 = createAssets(host.assetFiles ?? new Map(), config.assets, hasWorker);\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 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 for (const d1 of config.d1_databases ?? [])\n env[d1.binding] = celldExec(\n 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"]}
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, type AssetsConfig, createAssets } from \"../bindings/assets.js\";\nimport { celldKv } from \"../bindings/celld-kv.js\";\nimport { celldQueues, type QueueConsumerConfig } from \"../bindings/celld-queues.js\";\nimport { celldWorkflows } from \"../bindings/celld-workflows.js\";\nimport { startCronTriggers } from \"../bindings/cron.js\";\nimport { r2Bucket, r2BucketOn } from \"../bindings/r2.js\";\nimport { celldR2Backend } from \"../bindings/r2-celld.js\";\nimport { type ModuleLoader, workerLoader } 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 { D1DatabaseObject, makeD1Binding } from \"../miniflare-compat/vendored.js\";\nimport { systemClock } from \"../ports.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 /** 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}\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 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<typeof celldKv> | undefined;\n if (config.kv_namespaces?.length) {\n kv = 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 = 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<typeof celldQueues> | undefined;\n if (config.queues?.producers?.length || consumers.size) {\n 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: ReturnType<typeof celldWorkflows> | undefined;\n if (config.workflows?.length) {\n 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 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 else\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 = 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 = createAssets(host.assetFiles ?? new Map(), config.assets, hasWorker);\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 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 for (const d1 of config.d1_databases ?? [])\n env[d1.binding] = celldExec(\n 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 * 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 (!flags.some((f) => f.startsWith(\"nodejs_compat\"))) 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,4 +1,5 @@
1
1
  import { ServerWebSocket } from "@statewalker/webrun-http-browser/sw";
2
+ import { type Frame } from "./frames.js";
2
3
  /**
3
4
  * Cloudflare Workers' server-side WebSocket (one end of a WebSocketPair), on
4
5
  * webrun-http-browser's `ServerWebSocket` and its frames, with workerd's semantics:
@@ -10,7 +11,7 @@ import { ServerWebSocket } from "@statewalker/webrun-http-browser/sw";
10
11
  * - the heartbeat watch starts with the client's first ping and keeps that period: a pair's ends
11
12
  * used in one realm never ping, and a tab that closes turns hidden (announcing a longer period)
12
13
  * on its way out;
13
- * - attachments, `peer`, `hibernatable`, and `goAway` for the ends accepted in this realm.
14
+ * - attachments, `peer`, `hibernatable`, and `goAway` for the server ends of this realm.
14
15
  *
15
16
  * Hibernation (`ctx.acceptWebSocket`) is a later prototype.
16
17
  */
@@ -21,7 +22,8 @@ export declare class CfWebSocket extends ServerWebSocket {
21
22
  static readonly READY_STATE_CLOSING = 2;
22
23
  static readonly READY_STATE_CLOSED = 3;
23
24
  extensions: string | null;
24
- constructor(port: MessagePort);
25
+ /** `queued`: frames the end received before `port` reached it, delivered first (a 101's). */
26
+ constructor(port: MessagePort, queued?: Frame[]);
25
27
  /** The other end of the WebSocketPair (the runtime checks how the server end was accepted). */
26
28
  peer?: CfWebSocket;
27
29
  /** Accepted through ctx.acceptWebSocket() (hibernatable) rather than accept(). */
@@ -33,9 +35,11 @@ export declare class CfWebSocket extends ServerWebSocket {
33
35
  serializeAttachment(v: unknown): void;
34
36
  deserializeAttachment(): unknown;
35
37
  /**
36
- * Closes every server end accepted in this realm with 1001 (going away). A shard worker that
37
- * hands its cells to another tab does it before it stops, so that clients reconnect at once
38
- * instead of noticing through the heartbeat; Worker code cannot send 1001 itself (`close`).
38
+ * Closes every server end of this realm with 1001 (going away): the accepted ones, and those
39
+ * whose client end was handed over but which were never accepted. A shard worker that hands
40
+ * its cells to another tab does it before it stops, and an isolate before it is terminated,
41
+ * so that clients reconnect at once instead of noticing through the heartbeat; Worker code
42
+ * cannot send 1001 itself (`close`).
39
43
  */
40
44
  static goAway(reason?: string): void;
41
45
  }
@@ -71,9 +75,23 @@ export declare class WebSocketPair {
71
75
  export declare class StandardWebSocketPair extends WebSocketPair {
72
76
  constructor();
73
77
  }
78
+ /**
79
+ * Detaches the CLIENT end returned in a 101 response: its own port, and the frames the server
80
+ * sent before the response was handed over (partyserver greets in onConnect, before it returns
81
+ * the 101), which reached this end and wait in its queue. A holder that replays them
82
+ * (`new CfWebSocket(port, frames)`) needs no relay. Only when this end itself sent frames not
83
+ * yet acknowledged does `detach()` keep a relay (it absorbs their acknowledgements); the frames
84
+ * then travel through it.
85
+ */
86
+ export declare function takeClientEnd(ws: CfWebSocket): {
87
+ port: MessagePort;
88
+ frames: Frame[];
89
+ };
74
90
  /**
75
91
  * Detaches the transport of the CLIENT end returned in a 101 response, so the
76
- * runtime can hand the raw MessagePort to the real client (transferable).
92
+ * runtime can hand the raw MessagePort to the real client (transferable). Frames the server
93
+ * sent before the hand-over go to the new holder first, then the rest (ServerWebSocket.detach
94
+ * relays them).
77
95
  */
78
96
  export declare function takeClientPort(ws: CfWebSocket): MessagePort;
79
97
  export declare class CellsResponse extends Response {
package/dist/ws/server.js CHANGED
@@ -1,7 +1,10 @@
1
1
  import { ServerWebSocket } from "@statewalker/webrun-http-browser/sw";
2
2
  import { checkClose } from "./frames.js";
3
- /** Server ends accepted in this realm and not yet closed (see `CfWebSocket.goAway`). */
4
- const acceptedEnds = new Set();
3
+ /**
4
+ * Server ends of this realm that a client may be waiting on, not yet closed: the accepted ones,
5
+ * and those whose client end was handed over (see `CfWebSocket.goAway`).
6
+ */
7
+ const serverEnds = new Set();
5
8
  /**
6
9
  * Cloudflare Workers' server-side WebSocket (one end of a WebSocketPair), on
7
10
  * webrun-http-browser's `ServerWebSocket` and its frames, with workerd's semantics:
@@ -13,7 +16,7 @@ const acceptedEnds = new Set();
13
16
  * - the heartbeat watch starts with the client's first ping and keeps that period: a pair's ends
14
17
  * used in one realm never ping, and a tab that closes turns hidden (announcing a longer period)
15
18
  * on its way out;
16
- * - attachments, `peer`, `hibernatable`, and `goAway` for the ends accepted in this realm.
19
+ * - attachments, `peer`, `hibernatable`, and `goAway` for the server ends of this realm.
17
20
  *
18
21
  * Hibernation (`ctx.acceptWebSocket`) is a later prototype.
19
22
  */
@@ -24,7 +27,8 @@ export class CfWebSocket extends ServerWebSocket {
24
27
  static READY_STATE_CLOSED = 3;
25
28
  extensions = null;
26
29
  #attachment;
27
- constructor(port) {
30
+ /** `queued`: frames the end received before `port` reached it, delivered first (a 101's). */
31
+ constructor(port, queued = []) {
28
32
  super(port, {
29
33
  watch: "first-ping",
30
34
  heartbeatPeriod: "first",
@@ -36,6 +40,9 @@ export class CfWebSocket extends ServerWebSocket {
36
40
  // workerd's server ends have no url or subprotocol of their own.
37
41
  Object.defineProperty(this, "url", { value: null, writable: true, configurable: true });
38
42
  Object.defineProperty(this, "protocol", { value: null, writable: true, configurable: true });
43
+ // Ahead of anything from the port, which reaches this end in a later task.
44
+ if (queued.length)
45
+ this._queue.unshift(...queued);
39
46
  }
40
47
  /** The other end of the WebSocketPair (the runtime checks how the server end was accepted). */
41
48
  peer;
@@ -50,7 +57,7 @@ export class CfWebSocket extends ServerWebSocket {
50
57
  catch {
51
58
  throw new TypeError("This WebSocket end was handed to a client; it cannot be accepted.");
52
59
  }
53
- acceptedEnds.add(this);
60
+ serverEnds.add(this);
54
61
  }
55
62
  send(data) {
56
63
  if (this.readyState !== 1)
@@ -61,7 +68,7 @@ export class CfWebSocket extends ServerWebSocket {
61
68
  checkClose(code, reason);
62
69
  }
63
70
  _onClosed() {
64
- acceptedEnds.delete(this);
71
+ serverEnds.delete(this);
65
72
  super._onClosed();
66
73
  }
67
74
  serializeAttachment(v) {
@@ -71,13 +78,15 @@ export class CfWebSocket extends ServerWebSocket {
71
78
  return structuredClone(this.#attachment);
72
79
  }
73
80
  /**
74
- * Closes every server end accepted in this realm with 1001 (going away). A shard worker that
75
- * hands its cells to another tab does it before it stops, so that clients reconnect at once
76
- * instead of noticing through the heartbeat; Worker code cannot send 1001 itself (`close`).
81
+ * Closes every server end of this realm with 1001 (going away): the accepted ones, and those
82
+ * whose client end was handed over but which were never accepted. A shard worker that hands
83
+ * its cells to another tab does it before it stops, and an isolate before it is terminated,
84
+ * so that clients reconnect at once instead of noticing through the heartbeat; Worker code
85
+ * cannot send 1001 itself (`close`).
77
86
  */
78
87
  static goAway(reason = "moving to another worker") {
79
- for (const ws of acceptedEnds) {
80
- acceptedEnds.delete(ws);
88
+ for (const ws of serverEnds) {
89
+ serverEnds.delete(ws);
81
90
  if (ws.readyState >= 2)
82
91
  continue;
83
92
  ws._startClose(1001, reason);
@@ -143,16 +152,43 @@ export class StandardWebSocketPair extends WebSocketPair {
143
152
  this[1].binaryType = "blob";
144
153
  }
145
154
  }
155
+ /**
156
+ * Detaches the CLIENT end returned in a 101 response: its own port, and the frames the server
157
+ * sent before the response was handed over (partyserver greets in onConnect, before it returns
158
+ * the 101), which reached this end and wait in its queue. A holder that replays them
159
+ * (`new CfWebSocket(port, frames)`) needs no relay. Only when this end itself sent frames not
160
+ * yet acknowledged does `detach()` keep a relay (it absorbs their acknowledgements); the frames
161
+ * then travel through it.
162
+ */
163
+ export function takeClientEnd(ws) {
164
+ const frames = ws.bufferedAmount === 0 ? ws._queue.splice(0) : [];
165
+ let port;
166
+ try {
167
+ port = ws.detach(); // with its queue emptied: the end's own port
168
+ }
169
+ catch {
170
+ ws._queue.unshift(...frames);
171
+ throw new TypeError("WebSocket end already handed over");
172
+ }
173
+ // Its server end now has a client waiting, accepted or not: `goAway` must reach it.
174
+ const server = ws.peer;
175
+ if (server && server.readyState < 2)
176
+ serverEnds.add(server);
177
+ return { port, frames };
178
+ }
146
179
  /**
147
180
  * Detaches the transport of the CLIENT end returned in a 101 response, so the
148
- * runtime can hand the raw MessagePort to the real client (transferable).
181
+ * runtime can hand the raw MessagePort to the real client (transferable). Frames the server
182
+ * sent before the hand-over go to the new holder first, then the rest (ServerWebSocket.detach
183
+ * relays them).
149
184
  */
150
185
  export function takeClientPort(ws) {
151
- // Frames the server sent before the response was handed over (partyserver greets in
152
- // onConnect, before it returns the 101) reached this end and wait in its queue: the new holder
153
- // gets them first, then the rest (ServerWebSocket.detach).
154
186
  try {
155
- return ws.detach();
187
+ const port = ws.detach();
188
+ const server = ws.peer;
189
+ if (server && server.readyState < 2)
190
+ serverEnds.add(server);
191
+ return port;
156
192
  }
157
193
  catch {
158
194
  throw new TypeError("WebSocket end already handed over");