@statewalker/cellb 0.8.8 → 0.9.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 (92) hide show
  1. package/README.md +11 -7
  2. package/dist/adapters/node-sqlite-module.d.ts +6 -0
  3. package/dist/adapters/node-sqlite-module.js +12 -0
  4. package/dist/adapters/node-sqlite-module.js.map +1 -1
  5. package/dist/adapters/node-sqlite.js +3 -3
  6. package/dist/adapters/node-sqlite.js.map +1 -1
  7. package/dist/adapters/wasm-sqlite.d.ts +2 -0
  8. package/dist/adapters/wasm-sqlite.js +15 -0
  9. package/dist/adapters/wasm-sqlite.js.map +1 -1
  10. package/dist/bindings/cjs-module.d.ts +7 -0
  11. package/dist/bindings/cjs-module.js +96 -0
  12. package/dist/bindings/cjs-module.js.map +1 -0
  13. package/dist/bindings/cron.js +9 -2
  14. package/dist/bindings/cron.js.map +1 -1
  15. package/dist/bindings/module-registry.d.ts +43 -0
  16. package/dist/bindings/module-registry.js +192 -0
  17. package/dist/bindings/module-registry.js.map +1 -0
  18. package/dist/bindings/worker-loader.d.ts +23 -5
  19. package/dist/bindings/worker-loader.js +75 -4
  20. package/dist/bindings/worker-loader.js.map +1 -1
  21. package/dist/bucket/sqlite-object-store.js +2 -2
  22. package/dist/bucket/sqlite-object-store.js.map +1 -1
  23. package/dist/core/alarms.js +12 -2
  24. package/dist/core/alarms.js.map +1 -1
  25. package/dist/core/handles.d.ts +21 -1
  26. package/dist/core/handles.js +49 -3
  27. package/dist/core/handles.js.map +1 -1
  28. package/dist/core/namespace.js +4 -1
  29. package/dist/core/namespace.js.map +1 -1
  30. package/dist/core/runtime.d.ts +8 -0
  31. package/dist/core/runtime.js +3 -3
  32. package/dist/core/runtime.js.map +1 -1
  33. package/dist/index.d.ts +5 -0
  34. package/dist/index.js +5 -0
  35. package/dist/index.js.map +1 -1
  36. package/dist/isolate/browser.d.ts +1 -1
  37. package/dist/isolate/browser.js +3 -1
  38. package/dist/isolate/browser.js.map +1 -1
  39. package/dist/isolate/function-imports.d.ts +10 -0
  40. package/dist/isolate/function-imports.js +93 -0
  41. package/dist/isolate/function-imports.js.map +1 -0
  42. package/dist/isolate/host.js +20 -2
  43. package/dist/isolate/host.js.map +1 -1
  44. package/dist/isolate/isolate-worker.js +18 -2
  45. package/dist/isolate/isolate-worker.js.map +1 -1
  46. package/dist/isolate/isolate.js +11 -0
  47. package/dist/isolate/isolate.js.map +1 -1
  48. package/dist/isolate/node-entry.js +33 -0
  49. package/dist/isolate/node-entry.js.map +1 -1
  50. package/dist/isolate/protocol.d.ts +1 -0
  51. package/dist/isolate/protocol.js +242 -13
  52. package/dist/isolate/protocol.js.map +1 -1
  53. package/dist/isolate/writable-globals.d.ts +9 -0
  54. package/dist/isolate/writable-globals.js +45 -0
  55. package/dist/isolate/writable-globals.js.map +1 -0
  56. package/dist/node-compat/bundle-files.d.ts +26 -0
  57. package/dist/node-compat/bundle-files.js +210 -0
  58. package/dist/node-compat/bundle-files.js.map +1 -0
  59. package/dist/node-compat/fs.d.ts +13 -1
  60. package/dist/node-compat/fs.js +54 -15
  61. package/dist/node-compat/fs.js.map +1 -1
  62. package/dist/project/browser-host.d.ts +2 -0
  63. package/dist/project/browser-host.js +2 -0
  64. package/dist/project/browser-host.js.map +1 -1
  65. package/dist/project/browser-load.js +1 -0
  66. package/dist/project/browser-load.js.map +1 -1
  67. package/dist/project/browser-modules.d.ts +8 -2
  68. package/dist/project/browser-modules.js +30 -6
  69. package/dist/project/browser-modules.js.map +1 -1
  70. package/dist/project/built-project.d.ts +7 -0
  71. package/dist/project/built-project.js.map +1 -1
  72. package/dist/project/cloudflare-workers.d.ts +9 -0
  73. package/dist/project/cloudflare-workers.js +14 -0
  74. package/dist/project/cloudflare-workers.js.map +1 -1
  75. package/dist/project/module-rules.js +31 -10
  76. package/dist/project/module-rules.js.map +1 -1
  77. package/dist/project/node-project.d.ts +2 -0
  78. package/dist/project/node-project.js +157 -25
  79. package/dist/project/node-project.js.map +1 -1
  80. package/dist/project/site-loader.js +2 -1
  81. package/dist/project/site-loader.js.map +1 -1
  82. package/dist/project/uint8array-base64.d.ts +7 -0
  83. package/dist/project/uint8array-base64.js +96 -0
  84. package/dist/project/uint8array-base64.js.map +1 -0
  85. package/dist/project/workers-globals-module.d.ts +1 -0
  86. package/dist/project/workers-globals-module.js +3 -0
  87. package/dist/project/workers-globals-module.js.map +1 -1
  88. package/dist/project/wrangler.js +8 -9
  89. package/dist/project/wrangler.js.map +1 -1
  90. package/dist/ws/upgrade.js +18 -1
  91. package/dist/ws/upgrade.js.map +1 -1
  92. package/package.json +10 -10
@@ -1,8 +1,11 @@
1
1
  /**
2
2
  * `node:fs` for browsers (nodejs_compat): there is no file system, so every call fails with
3
3
  * `ENOENT` (as for a missing file) and `existsSync` is false. Code that probes for optional
4
- * files, such as an SDK reading `/proc/self/environ` inside a `try`, keeps working.
4
+ * files, such as an SDK reading `/proc/self/environ` inside a `try`, keeps working. The one
5
+ * directory there is is workerd's `/bundle`, read-only: the bundle's own non-JS modules
6
+ * (bundle-files.ts).
5
7
  */
8
+ import { bundleFs } from "./bundle-files.js";
6
9
  const missing = (op) => (path) => {
7
10
  throw Object.assign(new Error(`ENOENT: no such file or directory, ${op} '${String(path)}'`), {
8
11
  code: "ENOENT",
@@ -11,22 +14,52 @@ const missing = (op) => (path) => {
11
14
  });
12
15
  };
13
16
  const missingAsync = (op) => async (path) => missing(op)(path);
14
- export const existsSync = (_path) => false;
15
- export const readFileSync = missing("open");
17
+ const missingCallback = (op) => (path, ...rest) => {
18
+ const cb = rest.pop();
19
+ try {
20
+ missing(op)(path);
21
+ }
22
+ catch (e) {
23
+ queueMicrotask(() => cb(e));
24
+ }
25
+ };
26
+ const none = {
27
+ existsSync: (_path) => false,
28
+ readFileSync: missing("open"),
29
+ statSync: missing("stat"),
30
+ lstatSync: missing("lstat"),
31
+ readdirSync: missing("scandir"),
32
+ accessSync: missing("access"),
33
+ readFile: missingCallback("open"),
34
+ stat: missingCallback("stat"),
35
+ lstat: missingCallback("lstat"),
36
+ readdir: missingCallback("scandir"),
37
+ access: missingCallback("access"),
38
+ promises: {
39
+ readFile: missingAsync("open"),
40
+ writeFile: missingAsync("open"),
41
+ stat: missingAsync("stat"),
42
+ lstat: missingAsync("lstat"),
43
+ readdir: missingAsync("scandir"),
44
+ mkdir: missingAsync("mkdir"),
45
+ access: missingAsync("access"),
46
+ },
47
+ };
48
+ const fs = bundleFs(none);
49
+ export const existsSync = fs.existsSync;
50
+ export const readFileSync = fs.readFileSync;
16
51
  export const writeFileSync = missing("open");
17
- export const statSync = missing("stat");
18
- export const lstatSync = missing("lstat");
19
- export const readdirSync = missing("scandir");
52
+ export const statSync = fs.statSync;
53
+ export const lstatSync = fs.lstatSync;
54
+ export const readdirSync = fs.readdirSync;
55
+ export const accessSync = fs.accessSync;
20
56
  export const mkdirSync = missing("mkdir");
21
- export const promises = {
22
- readFile: missingAsync("open"),
23
- writeFile: missingAsync("open"),
24
- stat: missingAsync("stat"),
25
- lstat: missingAsync("lstat"),
26
- readdir: missingAsync("scandir"),
27
- mkdir: missingAsync("mkdir"),
28
- access: missingAsync("access"),
29
- };
57
+ export const readFile = fs.readFile;
58
+ export const stat = fs.stat;
59
+ export const lstat = fs.lstat;
60
+ export const readdir = fs.readdir;
61
+ export const access = fs.access;
62
+ export const promises = fs.promises;
30
63
  export default {
31
64
  existsSync,
32
65
  readFileSync,
@@ -34,7 +67,13 @@ export default {
34
67
  statSync,
35
68
  lstatSync,
36
69
  readdirSync,
70
+ accessSync,
37
71
  mkdirSync,
72
+ readFile,
73
+ stat,
74
+ lstat,
75
+ readdir,
76
+ access,
38
77
  promises,
39
78
  };
40
79
  //# sourceMappingURL=fs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/node-compat/fs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,OAAO,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,CAAC,IAAc,EAAE,EAAE;IACjD,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,sCAAsC,EAAE,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAC3F,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,EAAE;QACX,IAAI;KACL,CAAC,CAAC;AACL,CAAC,CAAC;AACF,MAAM,YAAY,GAChB,CAAC,EAAU,EAAE,EAAE,CACf,KAAK,EAAE,IAAc,EAAkB,EAAE,CACvC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAEtB,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC;AACrD,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAC5C,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAC7C,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AACxC,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAC1C,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAC9C,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAC1C,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC;IAC9B,SAAS,EAAE,YAAY,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC;IAC1B,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC;IAC5B,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC;IAChC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC;IAC5B,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC;CAC/B,CAAC;AAEF,eAAe;IACb,UAAU;IACV,YAAY;IACZ,aAAa;IACb,QAAQ;IACR,SAAS;IACT,WAAW;IACX,SAAS;IACT,QAAQ;CACT,CAAC","sourcesContent":["/**\n * `node:fs` for browsers (nodejs_compat): there is no file system, so every call fails with\n * `ENOENT` (as for a missing file) and `existsSync` is false. Code that probes for optional\n * files, such as an SDK reading `/proc/self/environ` inside a `try`, keeps working.\n */\nconst missing = (op: string) => (path?: unknown) => {\n throw Object.assign(new Error(`ENOENT: no such file or directory, ${op} '${String(path)}'`), {\n code: \"ENOENT\",\n syscall: op,\n path,\n });\n};\nconst missingAsync =\n (op: string) =>\n async (path?: unknown): Promise<never> =>\n missing(op)(path);\n\nexport const existsSync = (_path?: unknown) => false;\nexport const readFileSync = missing(\"open\");\nexport const writeFileSync = missing(\"open\");\nexport const statSync = missing(\"stat\");\nexport const lstatSync = missing(\"lstat\");\nexport const readdirSync = missing(\"scandir\");\nexport const mkdirSync = missing(\"mkdir\");\nexport const promises = {\n readFile: missingAsync(\"open\"),\n writeFile: missingAsync(\"open\"),\n stat: missingAsync(\"stat\"),\n lstat: missingAsync(\"lstat\"),\n readdir: missingAsync(\"scandir\"),\n mkdir: missingAsync(\"mkdir\"),\n access: missingAsync(\"access\"),\n};\n\nexport default {\n existsSync,\n readFileSync,\n writeFileSync,\n statSync,\n lstatSync,\n readdirSync,\n mkdirSync,\n promises,\n};\n"]}
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/node-compat/fs.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `node:fs` for browsers (nodejs_compat): there is no file system, so every call fails with\n * `ENOENT` (as for a missing file) and `existsSync` is false. Code that probes for optional\n * files, such as an SDK reading `/proc/self/environ` inside a `try`, keeps working. The one\n * directory there is is workerd's `/bundle`, read-only: the bundle's own non-JS modules\n * (bundle-files.ts).\n */\nimport { bundleFs } from \"./bundle-files.js\";\n\nconst missing = (op: string) => (path?: unknown) => {\n throw Object.assign(new Error(`ENOENT: no such file or directory, ${op} '${String(path)}'`), {\n code: \"ENOENT\",\n syscall: op,\n path,\n });\n};\nconst missingAsync =\n (op: string) =>\n async (path?: unknown): Promise<never> =>\n missing(op)(path);\nconst missingCallback =\n (op: string) =>\n (path: unknown, ...rest: unknown[]) => {\n const cb = rest.pop() as (e: unknown) => void;\n try {\n missing(op)(path);\n } catch (e) {\n queueMicrotask(() => cb(e));\n }\n };\n\nconst none = {\n existsSync: (_path?: unknown) => false,\n readFileSync: missing(\"open\"),\n statSync: missing(\"stat\"),\n lstatSync: missing(\"lstat\"),\n readdirSync: missing(\"scandir\"),\n accessSync: missing(\"access\"),\n readFile: missingCallback(\"open\"),\n stat: missingCallback(\"stat\"),\n lstat: missingCallback(\"lstat\"),\n readdir: missingCallback(\"scandir\"),\n access: missingCallback(\"access\"),\n promises: {\n readFile: missingAsync(\"open\"),\n writeFile: missingAsync(\"open\"),\n stat: missingAsync(\"stat\"),\n lstat: missingAsync(\"lstat\"),\n readdir: missingAsync(\"scandir\"),\n mkdir: missingAsync(\"mkdir\"),\n access: missingAsync(\"access\"),\n },\n};\nconst fs = bundleFs(none) as typeof none;\n\nexport const existsSync = fs.existsSync;\nexport const readFileSync = fs.readFileSync;\nexport const writeFileSync = missing(\"open\");\nexport const statSync = fs.statSync;\nexport const lstatSync = fs.lstatSync;\nexport const readdirSync = fs.readdirSync;\nexport const accessSync = fs.accessSync;\nexport const mkdirSync = missing(\"mkdir\");\nexport const readFile = fs.readFile;\nexport const stat = fs.stat;\nexport const lstat = fs.lstat;\nexport const readdir = fs.readdir;\nexport const access = fs.access;\nexport const promises = fs.promises;\n\nexport default {\n existsSync,\n readFileSync,\n writeFileSync,\n statSync,\n lstatSync,\n readdirSync,\n accessSync,\n mkdirSync,\n readFile,\n stat,\n lstat,\n readdir,\n access,\n promises,\n};\n"]}
@@ -192,5 +192,7 @@ export declare function browserProjectRuntime(opts: BrowserProjectOptions): Prom
192
192
  advertise(address: string): Promise<void>;
193
193
  close(): Promise<void>;
194
194
  } | undefined;
195
+ /** The cells' databases in the OPFS pool (none with a bucket: there the bucket has them). */
196
+ exportCells: () => Promise<[string, Uint8Array][]>;
195
197
  close: () => Promise<void>;
196
198
  }>;
@@ -197,6 +197,8 @@ export async function browserProjectRuntime(opts) {
197
197
  runtime,
198
198
  unsupported,
199
199
  bucket: shared,
200
+ /** The cells' databases in the OPFS pool (none with a bucket: there the bucket has them). */
201
+ exportCells: async () => openSql.exportFiles?.() ?? [],
200
202
  close: async () => {
201
203
  await runtime.close();
202
204
  openSql.release(); // the pool's files, for the next worker that opens it
@@ -1 +1 @@
1
- {"version":3,"file":"browser-host.js","sourceRoot":"","sources":["../../src/project/browser-host.ts"],"names":[],"mappings":"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","sourcesContent":["import { BrowserFilesApi } from \"@statewalker/webrun-files-browser\";\nimport { installLtxVfs } from \"../adapters/ltx-vfs.js\";\nimport {\n sahpoolOpener,\n tuneCellConnection,\n WasmSqliteDriver,\n wasmMemoryOpener,\n} from \"../adapters/wasm-sqlite.js\";\nimport type { AssetFiles } from \"../bindings/assets.js\";\nimport type { WorkersAiOptions } from \"../bindings/workers-ai.js\";\nimport { celldBucket } from \"../bucket/celld-cells.js\";\nimport { idbObjectStore } from \"../bucket/idb-object-store.js\";\nimport { filesApiObjectStore, type ObjectStore } from \"../bucket/object-store.js\";\nimport { s3ObjectStore } from \"../bucket/s3-object-store.js\";\nimport type { CellRuntimeOptions, WorkerModule } from \"../core/runtime.js\";\nimport { browserIsolatedLoader } from \"../isolate/browser.js\";\nimport type { LtxStoreFiles } from \"../ltx/ltx-page-server.js\";\nimport { installAsyncContext } from \"../node-compat/async_hooks.js\";\nimport { installNodeGlobals } from \"../node-compat/install.js\";\nimport { browserModuleLoader } from \"./browser-modules.js\";\nimport * as workersModule from \"./cloudflare-workers.js\";\nimport { siteModuleLoader, workersHostRegistry } from \"./site-loader.js\";\nimport { type WorkerScope, workerScope } from \"./worker-scope.js\";\nimport * as workersGlobals from \"./workers-globals-module.js\";\nimport {\n createProjectRuntime,\n hasNodeCompat,\n loadProjectBindings,\n loadTimeEnv,\n populatesProcessEnv,\n processEnvOf,\n type WranglerConfig,\n} from \"./wrangler.js\";\n\nexport { populatesProcessEnv, processEnvOf };\n\n/**\n * Where a browser-hosted project keeps its cells when they must outlive the page or move to\n * other nodes: a celld fleet bucket. Cells, facets and alarms are then exactly celld's\n * (ownership in `own.json`, LTX logs, wake index) and R2 objects live in it too, so the same\n * cells can be served by this browser, by other browsers and by celld nodes, in turn.\n *\n * - `s3`: an S3-compatible bucket, reached directly (the bucket must allow CORS for the page's\n * origin: methods GET/PUT/DELETE/HEAD, request headers `authorization`, `content-type`,\n * `x-amz-*`, `if-match`, `if-none-match`; exposed headers `etag`, `last-modified`,\n * `x-amz-meta-celld-r2`) or through a same-origin proxy (`endpoint` = the proxy,\n * `signAs` = the real endpoint: SigV4 signs the real host and path).\n * - `opfs`: a bucket in this origin's OPFS — persistence without a server. Conditional writes\n * are atomic only within one writer, so one tab or worker at a time should own its cells.\n * - `store`: any ObjectStore.\n */\nexport type BrowserBucket =\n | {\n s3: {\n endpoint: string;\n signAs?: string;\n bucket: string;\n prefix?: string;\n region?: string;\n accessKeyId: string;\n secretAccessKey: string;\n };\n node: string;\n leaseTtlMs?: number;\n }\n | { opfs: string; node: string; leaseTtlMs?: number }\n /**\n * `idb`: a bucket in this origin's IndexedDB (atomic conditional writes across tabs and\n * workers). Cells then run SQLite in memory and persist through the bucket's page-level logs:\n * no OPFS pool, so any number of workers can serve cells at once.\n */\n | { idb: string; node: string; leaseTtlMs?: number }\n /**\n * `ltx`: cells as celld keeps them, LTX files (a snapshot and one file per commit) in an OPFS\n * directory, read page by page (a SQLite VFS over a store worker): no OPFS pool, and a\n * cell's memory is its page cache, not its database. A cell is folded into one snapshot\n * (streamed) past `compactAfter` files (default 64), or once the files after its snapshot hold\n * more than half of it. See docs/browser-host.md.\n */\n | {\n ltx: string;\n node: string;\n leaseTtlMs?: number;\n compactAfter?: number;\n /**\n * The cells' FilesApi in the store worker. A preset on OPFS directory `ltx`: synchronous\n * handles (default, `opfs-sync`), OPFS's asynchronous API (`opfs`), or memory (nothing\n * kept). Or the app's own FilesApi, opened before cellb starts: `{ port }` from\n * `filesApiPort(files)` (served where the app opened it), or `{ module, args }` (built in\n * the store worker). `ltx` then names the storage (the scope of the cells' Web Locks).\n * A port is transferred to the store worker, so it serves one runtime: give each\n * `browserProjectRuntime` a new `filesApiPort`.\n */\n files?: LtxStoreFiles;\n /**\n * A store already running elsewhere (`serveLtxStore(files)`, on the page): no store\n * worker; the VFS sends its reads and commits there. `files` is then ignored. One store\n * per runtime; the app calls its `close()` when the runtime ends.\n */\n ltxStore?: { sab: SharedArrayBuffer; port: MessagePort };\n }\n | { store: ObjectStore; node: string; leaseTtlMs?: number };\n\nexport interface BrowserProjectOptions {\n config: WranglerConfig;\n /**\n * The project's Worker code, imported in this realm once its Workers globals (and with\n * nodejs_compat `Buffer` and `process`) are installed:\n * - `bundle`: one ES module built for browsers (`bundleWorkerForBrowser`), whose\n * `cloudflare:workers` is `PROJECT_WORKERS_MODULE_SHIM` and whose Workers globals read\n * `globalThis.__cellsGlobals`\n * (`null`: the project has no `main`). Worker Loader code becomes Blob-URL modules.\n * - `site`: the base URL of the project's site (`createProjectSite`, hosted by\n * webrun-site-host). `main` and Worker Loader code are imported from it.\n */\n code: { bundle: string | null } | { site: string };\n /**\n * A Dedicated Worker script that serves one loaded Worker (`serveIsolate`): Worker Loader\n * code then runs isolated, one Dedicated Worker per loaded Worker, as celld's isolates.\n * The package ships one: `@statewalker/cellb/isolate-worker`. A function instead starts the\n * Dedicated Worker itself (`() => new Worker(new URL(…, import.meta.url), { type: \"module\" })`,\n * a form bundlers follow).\n */\n isolateScript?: URL | (() => Worker);\n /** An initialized SQLite WASM module (`@sqlite.org/sqlite-wasm`). */\n sqlite3: unknown;\n /** OPFS sahpool name for this host's SQLite files (one pool per worker). */\n pool: string;\n /** OPFS directory for the project's FilesApi (Workers' fs-like bindings, R2 without bucket). */\n filesDir: string;\n assetFiles?: AssetFiles;\n bucket?: BrowserBucket;\n /**\n * Cells this runtime does not host: where to send their events (a `Send` over a MessagePort\n * to the runtime that hosts them, `linkOverPort`), or undefined to host the cell here. With\n * one runtime per worker and `shardOf` as the placement, cells run in parallel threads.\n */\n route?: CellRuntimeOptions[\"route\"];\n /** The OpenAI-compatible endpoint behind the project's `ai` binding (Workers AI). */\n ai?: WorkersAiOptions;\n}\n\nasync function bucketStore(b: BrowserBucket): Promise<ObjectStore> {\n if (\"store\" in b) return b.store;\n if (\"s3\" in b) return s3ObjectStore({ region: \"us-east-1\", ...b.s3 });\n if (\"idb\" in b) return idbObjectStore(b.idb);\n if (\"ltx\" in b) throw new Error(\"an ltx directory is cell storage, not a bucket\");\n const root = await navigator.storage.getDirectory();\n return filesApiObjectStore(\n new BrowserFilesApi({ rootHandle: await root.getDirectoryHandle(b.opfs, { create: true }) }),\n \"\",\n );\n}\n\n/**\n * Cells on the LTX VFS: each cell is a SQLite database whose main file is its LTX files, read\n * page by page (src/adapters/ltx-vfs.ts) from a store: a store worker of this worker's own (on\n * OPFS, memory, or the app's FilesApi through a port or a module), or a store the app runs\n * elsewhere (`ltxStore`).\n */\nexport async function ltxOpener(\n sqlite3: unknown,\n dir: string,\n compactAfter?: number,\n files?: LtxStoreFiles,\n ltxStore?: { sab: SharedArrayBuffer; port: MessagePort },\n) {\n let sab: SharedArrayBuffer;\n let post: (m: unknown) => void;\n let release: () => void;\n if (ltxStore) {\n // The store runs elsewhere (serveLtxStore): only the VFS here.\n sab = ltxStore.sab;\n const port = ltxStore.port;\n post = (m) => port.postMessage(m);\n release = () => port.close();\n } else {\n const store = new Worker(\n new URL(\n \"../ltx/ltx-store-worker.ts\",\n import.meta.url,\n ) /* `.js` in dist/ (scripts/build.mjs) */,\n { type: \"module\" },\n );\n sab = new SharedArrayBuffer(8 + 16 * 65536); // room for a read-ahead run of 64 KiB pages\n // Wait until the store worker runs before any synchronous call: a nested worker is started\n // (its script fetched) through this worker's event loop, which Atomics.wait would block.\n const ready = new Promise<void>((resolve, reject) => {\n store.addEventListener(\"message\", (e) => {\n if (e.data?.op === \"ready\") resolve();\n else if (e.data?.op === \"failed\")\n reject(new Error(`ltx store worker: ${e.data.error as string}`));\n });\n store.addEventListener(\"error\", (e) => reject(new Error(`ltx store worker: ${e.message}`)));\n });\n // A port to the app's FilesApi moves on to the store worker.\n const transfer = files && typeof files === \"object\" && \"port\" in files ? [files.port] : [];\n try {\n store.postMessage({ op: \"init\", sab, dir, compactAfter, files }, transfer);\n await ready;\n } catch (err) {\n store.terminate(); // a store worker that did not start is not left behind\n throw err;\n }\n post = (m) => store.postMessage(m);\n release = () => store.terminate();\n }\n const { name } = installLtxVfs(sqlite3, { sab, post });\n const s3 = sqlite3 as { oo1: { DB: new (o: Record<string, unknown>) => any } };\n const open = (cellKey: string) => {\n const db = new s3.oo1.DB({ filename: cellKey, vfs: name, flags: \"c\" });\n tuneCellConnection(sqlite3, db);\n db.exec(\"PRAGMA journal_mode=MEMORY; PRAGMA synchronous=FULL;\");\n // SQLite's C API for inTransaction() only (no page hook or session capture on this VFS).\n return new WasmSqliteDriver(db, undefined, undefined, (sqlite3 as { capi: never }).capi);\n };\n return Object.assign(open, {\n release,\n reserve: async (n: number) => n,\n });\n}\n\n/** Installs the Workers globals the code reads, then imports its `main`. */\nasync function importWorkerCode(\n config: WranglerConfig,\n code: BrowserProjectOptions[\"code\"],\n scope: WorkerScope,\n): Promise<WorkerModule> {\n const flags = config.compatibility_flags ?? [];\n const nodeCompat = hasNodeCompat(config);\n if (nodeCompat) {\n installNodeGlobals();\n // node:* for bundles built with cellbHostModule (another bundler than bundleWorkerForBrowser);\n // loaded after installNodeGlobals(), as the npm `util` polyfill reads `process`.\n (globalThis as Record<string, unknown>).__cellsNodeModules = (\n await import(\"../node-compat/browser-registry.js\")\n ).nodeRegistryEntries;\n if (populatesProcessEnv(config)) {\n const env = processEnvOf(config);\n // The bundle's own `process` reads it when evaluated; a site's modules use this realm's.\n (globalThis as Record<string, unknown>).__cellsProcessEnv = env;\n Object.assign((globalThis as { process: { env: Record<string, string> } }).process.env, env);\n }\n // node:async_hooks: continuations carry their AsyncLocalStorage stores (with AsyncContext\n // the engine does, and this installs nothing). The code's awaits are lowered so that they go\n // through them: by bundleWorkerForBrowser for a bundle, by createProjectSite (nodeCompat) for\n // a site's modules.\n installAsyncContext();\n }\n const globals = {\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 (\"site\" in code) {\n workersHostRegistry({\n workersModule,\n projectWorkersModule: {\n ...workersModule,\n env: scope.env,\n exports: scope.exports,\n waitUntil: scope.waitUntil,\n },\n loadedPrefix: `${code.site}loaded/`,\n emailModule: await import(\"./cloudflare-email.js\"),\n ...globals,\n // Loaded on demand, after installNodeGlobals(): the npm `util` polyfill reads `process`\n // when it is imported.\n node: nodeCompat\n ? (await import(\"../node-compat/browser-registry.js\")).nodeRegistryEntries\n : undefined,\n });\n return config.main\n ? await import(/* @vite-ignore */ `${code.site}modules/~/${config.main}`)\n : { default: {} };\n }\n const g = globalThis as Record<string, unknown>;\n g.__cellsWorkersModule = workersModule;\n g.__cellsProjectScope = scope; // `env` and `exports` of the bundle's cloudflare:workers\n g.__cellsGlobals = globals;\n return code.bundle\n ? await import(\n /* @vite-ignore */ URL.createObjectURL(new Blob([code.bundle], { type: \"text/javascript\" }))\n )\n : { default: {} };\n}\n\n/**\n * A project's runtime in this worker: installs the Workers globals, imports the code and\n * builds its Worker Loader; `close()` also releases the node's bucket lease.\n */\nexport async function browserProjectRuntime(opts: BrowserProjectOptions) {\n const scope = workerScope(loadTimeEnv(opts.config, opts.ai));\n const module = await importWorkerCode(opts.config, opts.code, scope);\n const site = \"site\" in opts.code ? opts.code.site : undefined;\n // With an IndexedDB bucket, cells live in memory and in the bucket's logs (no OPFS pool).\n const openSql =\n opts.bucket && \"ltx\" in opts.bucket\n ? await ltxOpener(\n opts.sqlite3,\n opts.bucket.ltx,\n opts.bucket.compactAfter,\n opts.bucket.files,\n opts.bucket.ltxStore,\n )\n : opts.bucket && \"idb\" in opts.bucket\n ? Object.assign(wasmMemoryOpener(opts.sqlite3 as never), {\n release() {},\n reserve: async (n: number) => n,\n })\n : await sahpoolOpener(opts.sqlite3 as never, {\n name: opts.pool,\n initialCapacity: 64, // grows on demand (sahpoolOpener)\n });\n const root = await navigator.storage.getDirectory();\n const files = new BrowserFilesApi({\n rootHandle: await root.getDirectoryHandle(opts.filesDir, { create: true }),\n });\n // An `ltx` directory is the cells' own storage (the VFS), not a fleet bucket.\n const store = opts.bucket && !(\"ltx\" in opts.bucket) ? await bucketStore(opts.bucket) : undefined;\n const shared =\n opts.bucket && store\n ? celldBucket(store, { node: opts.bucket.node, leaseTtlMs: opts.bucket.leaseTtlMs })\n : undefined;\n const { runtime, unsupported } = createProjectRuntime(opts.config, module, {\n bindings: await loadProjectBindings(opts.config),\n openSql,\n files,\n assetFiles: opts.assetFiles,\n loadModules: site ? siteModuleLoader(site) : browserModuleLoader(),\n isolatedModules: opts.isolateScript\n ? browserIsolatedLoader({\n isolateScript: opts.isolateScript,\n siteBaseUrl: site,\n storagePrefix: `${opts.pool}-iso`,\n storage: () => shared, // facets of loaded code are logged like the root's own\n })\n : undefined,\n storage: shared, // R2 objects in the fleet bucket too, as celld keeps them\n route: opts.route,\n ai: opts.ai,\n });\n scope.bind(runtime);\n return {\n runtime,\n unsupported,\n bucket: shared,\n close: async () => {\n await runtime.close();\n openSql.release(); // the pool's files, for the next worker that opens it\n },\n };\n}\n"]}
1
+ {"version":3,"file":"browser-host.js","sourceRoot":"","sources":["../../src/project/browser-host.ts"],"names":[],"mappings":"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","sourcesContent":["import { BrowserFilesApi } from \"@statewalker/webrun-files-browser\";\nimport { installLtxVfs } from \"../adapters/ltx-vfs.js\";\nimport {\n sahpoolOpener,\n tuneCellConnection,\n WasmSqliteDriver,\n wasmMemoryOpener,\n} from \"../adapters/wasm-sqlite.js\";\nimport type { AssetFiles } from \"../bindings/assets.js\";\nimport type { WorkersAiOptions } from \"../bindings/workers-ai.js\";\nimport { celldBucket } from \"../bucket/celld-cells.js\";\nimport { idbObjectStore } from \"../bucket/idb-object-store.js\";\nimport { filesApiObjectStore, type ObjectStore } from \"../bucket/object-store.js\";\nimport { s3ObjectStore } from \"../bucket/s3-object-store.js\";\nimport type { CellRuntimeOptions, WorkerModule } from \"../core/runtime.js\";\nimport { browserIsolatedLoader } from \"../isolate/browser.js\";\nimport type { LtxStoreFiles } from \"../ltx/ltx-page-server.js\";\nimport { installAsyncContext } from \"../node-compat/async_hooks.js\";\nimport { installNodeGlobals } from \"../node-compat/install.js\";\nimport { browserModuleLoader } from \"./browser-modules.js\";\nimport * as workersModule from \"./cloudflare-workers.js\";\nimport { siteModuleLoader, workersHostRegistry } from \"./site-loader.js\";\nimport { type WorkerScope, workerScope } from \"./worker-scope.js\";\nimport * as workersGlobals from \"./workers-globals-module.js\";\nimport {\n createProjectRuntime,\n hasNodeCompat,\n loadProjectBindings,\n loadTimeEnv,\n populatesProcessEnv,\n processEnvOf,\n type WranglerConfig,\n} from \"./wrangler.js\";\n\nexport { populatesProcessEnv, processEnvOf };\n\n/**\n * Where a browser-hosted project keeps its cells when they must outlive the page or move to\n * other nodes: a celld fleet bucket. Cells, facets and alarms are then exactly celld's\n * (ownership in `own.json`, LTX logs, wake index) and R2 objects live in it too, so the same\n * cells can be served by this browser, by other browsers and by celld nodes, in turn.\n *\n * - `s3`: an S3-compatible bucket, reached directly (the bucket must allow CORS for the page's\n * origin: methods GET/PUT/DELETE/HEAD, request headers `authorization`, `content-type`,\n * `x-amz-*`, `if-match`, `if-none-match`; exposed headers `etag`, `last-modified`,\n * `x-amz-meta-celld-r2`) or through a same-origin proxy (`endpoint` = the proxy,\n * `signAs` = the real endpoint: SigV4 signs the real host and path).\n * - `opfs`: a bucket in this origin's OPFS — persistence without a server. Conditional writes\n * are atomic only within one writer, so one tab or worker at a time should own its cells.\n * - `store`: any ObjectStore.\n */\nexport type BrowserBucket =\n | {\n s3: {\n endpoint: string;\n signAs?: string;\n bucket: string;\n prefix?: string;\n region?: string;\n accessKeyId: string;\n secretAccessKey: string;\n };\n node: string;\n leaseTtlMs?: number;\n }\n | { opfs: string; node: string; leaseTtlMs?: number }\n /**\n * `idb`: a bucket in this origin's IndexedDB (atomic conditional writes across tabs and\n * workers). Cells then run SQLite in memory and persist through the bucket's page-level logs:\n * no OPFS pool, so any number of workers can serve cells at once.\n */\n | { idb: string; node: string; leaseTtlMs?: number }\n /**\n * `ltx`: cells as celld keeps them, LTX files (a snapshot and one file per commit) in an OPFS\n * directory, read page by page (a SQLite VFS over a store worker): no OPFS pool, and a\n * cell's memory is its page cache, not its database. A cell is folded into one snapshot\n * (streamed) past `compactAfter` files (default 64), or once the files after its snapshot hold\n * more than half of it. See docs/browser-host.md.\n */\n | {\n ltx: string;\n node: string;\n leaseTtlMs?: number;\n compactAfter?: number;\n /**\n * The cells' FilesApi in the store worker. A preset on OPFS directory `ltx`: synchronous\n * handles (default, `opfs-sync`), OPFS's asynchronous API (`opfs`), or memory (nothing\n * kept). Or the app's own FilesApi, opened before cellb starts: `{ port }` from\n * `filesApiPort(files)` (served where the app opened it), or `{ module, args }` (built in\n * the store worker). `ltx` then names the storage (the scope of the cells' Web Locks).\n * A port is transferred to the store worker, so it serves one runtime: give each\n * `browserProjectRuntime` a new `filesApiPort`.\n */\n files?: LtxStoreFiles;\n /**\n * A store already running elsewhere (`serveLtxStore(files)`, on the page): no store\n * worker; the VFS sends its reads and commits there. `files` is then ignored. One store\n * per runtime; the app calls its `close()` when the runtime ends.\n */\n ltxStore?: { sab: SharedArrayBuffer; port: MessagePort };\n }\n | { store: ObjectStore; node: string; leaseTtlMs?: number };\n\nexport interface BrowserProjectOptions {\n config: WranglerConfig;\n /**\n * The project's Worker code, imported in this realm once its Workers globals (and with\n * nodejs_compat `Buffer` and `process`) are installed:\n * - `bundle`: one ES module built for browsers (`bundleWorkerForBrowser`), whose\n * `cloudflare:workers` is `PROJECT_WORKERS_MODULE_SHIM` and whose Workers globals read\n * `globalThis.__cellsGlobals`\n * (`null`: the project has no `main`). Worker Loader code becomes Blob-URL modules.\n * - `site`: the base URL of the project's site (`createProjectSite`, hosted by\n * webrun-site-host). `main` and Worker Loader code are imported from it.\n */\n code: { bundle: string | null } | { site: string };\n /**\n * A Dedicated Worker script that serves one loaded Worker (`serveIsolate`): Worker Loader\n * code then runs isolated, one Dedicated Worker per loaded Worker, as celld's isolates.\n * The package ships one: `@statewalker/cellb/isolate-worker`. A function instead starts the\n * Dedicated Worker itself (`() => new Worker(new URL(…, import.meta.url), { type: \"module\" })`,\n * a form bundlers follow).\n */\n isolateScript?: URL | (() => Worker);\n /** An initialized SQLite WASM module (`@sqlite.org/sqlite-wasm`). */\n sqlite3: unknown;\n /** OPFS sahpool name for this host's SQLite files (one pool per worker). */\n pool: string;\n /** OPFS directory for the project's FilesApi (Workers' fs-like bindings, R2 without bucket). */\n filesDir: string;\n assetFiles?: AssetFiles;\n bucket?: BrowserBucket;\n /**\n * Cells this runtime does not host: where to send their events (a `Send` over a MessagePort\n * to the runtime that hosts them, `linkOverPort`), or undefined to host the cell here. With\n * one runtime per worker and `shardOf` as the placement, cells run in parallel threads.\n */\n route?: CellRuntimeOptions[\"route\"];\n /** The OpenAI-compatible endpoint behind the project's `ai` binding (Workers AI). */\n ai?: WorkersAiOptions;\n}\n\nasync function bucketStore(b: BrowserBucket): Promise<ObjectStore> {\n if (\"store\" in b) return b.store;\n if (\"s3\" in b) return s3ObjectStore({ region: \"us-east-1\", ...b.s3 });\n if (\"idb\" in b) return idbObjectStore(b.idb);\n if (\"ltx\" in b) throw new Error(\"an ltx directory is cell storage, not a bucket\");\n const root = await navigator.storage.getDirectory();\n return filesApiObjectStore(\n new BrowserFilesApi({ rootHandle: await root.getDirectoryHandle(b.opfs, { create: true }) }),\n \"\",\n );\n}\n\n/**\n * Cells on the LTX VFS: each cell is a SQLite database whose main file is its LTX files, read\n * page by page (src/adapters/ltx-vfs.ts) from a store: a store worker of this worker's own (on\n * OPFS, memory, or the app's FilesApi through a port or a module), or a store the app runs\n * elsewhere (`ltxStore`).\n */\nexport async function ltxOpener(\n sqlite3: unknown,\n dir: string,\n compactAfter?: number,\n files?: LtxStoreFiles,\n ltxStore?: { sab: SharedArrayBuffer; port: MessagePort },\n) {\n let sab: SharedArrayBuffer;\n let post: (m: unknown) => void;\n let release: () => void;\n if (ltxStore) {\n // The store runs elsewhere (serveLtxStore): only the VFS here.\n sab = ltxStore.sab;\n const port = ltxStore.port;\n post = (m) => port.postMessage(m);\n release = () => port.close();\n } else {\n const store = new Worker(\n new URL(\n \"../ltx/ltx-store-worker.ts\",\n import.meta.url,\n ) /* `.js` in dist/ (scripts/build.mjs) */,\n { type: \"module\" },\n );\n sab = new SharedArrayBuffer(8 + 16 * 65536); // room for a read-ahead run of 64 KiB pages\n // Wait until the store worker runs before any synchronous call: a nested worker is started\n // (its script fetched) through this worker's event loop, which Atomics.wait would block.\n const ready = new Promise<void>((resolve, reject) => {\n store.addEventListener(\"message\", (e) => {\n if (e.data?.op === \"ready\") resolve();\n else if (e.data?.op === \"failed\")\n reject(new Error(`ltx store worker: ${e.data.error as string}`));\n });\n store.addEventListener(\"error\", (e) => reject(new Error(`ltx store worker: ${e.message}`)));\n });\n // A port to the app's FilesApi moves on to the store worker.\n const transfer = files && typeof files === \"object\" && \"port\" in files ? [files.port] : [];\n try {\n store.postMessage({ op: \"init\", sab, dir, compactAfter, files }, transfer);\n await ready;\n } catch (err) {\n store.terminate(); // a store worker that did not start is not left behind\n throw err;\n }\n post = (m) => store.postMessage(m);\n release = () => store.terminate();\n }\n const { name } = installLtxVfs(sqlite3, { sab, post });\n const s3 = sqlite3 as { oo1: { DB: new (o: Record<string, unknown>) => any } };\n const open = (cellKey: string) => {\n const db = new s3.oo1.DB({ filename: cellKey, vfs: name, flags: \"c\" });\n tuneCellConnection(sqlite3, db);\n db.exec(\"PRAGMA journal_mode=MEMORY; PRAGMA synchronous=FULL;\");\n // SQLite's C API for inTransaction() only (no page hook or session capture on this VFS).\n return new WasmSqliteDriver(db, undefined, undefined, (sqlite3 as { capi: never }).capi);\n };\n return Object.assign(open, {\n release,\n reserve: async (n: number) => n,\n });\n}\n\n/** Installs the Workers globals the code reads, then imports its `main`. */\nasync function importWorkerCode(\n config: WranglerConfig,\n code: BrowserProjectOptions[\"code\"],\n scope: WorkerScope,\n): Promise<WorkerModule> {\n const flags = config.compatibility_flags ?? [];\n const nodeCompat = hasNodeCompat(config);\n if (nodeCompat) {\n installNodeGlobals();\n // node:* for bundles built with cellbHostModule (another bundler than bundleWorkerForBrowser);\n // loaded after installNodeGlobals(), as the npm `util` polyfill reads `process`.\n (globalThis as Record<string, unknown>).__cellsNodeModules = (\n await import(\"../node-compat/browser-registry.js\")\n ).nodeRegistryEntries;\n if (populatesProcessEnv(config)) {\n const env = processEnvOf(config);\n // The bundle's own `process` reads it when evaluated; a site's modules use this realm's.\n (globalThis as Record<string, unknown>).__cellsProcessEnv = env;\n Object.assign((globalThis as { process: { env: Record<string, string> } }).process.env, env);\n }\n // node:async_hooks: continuations carry their AsyncLocalStorage stores (with AsyncContext\n // the engine does, and this installs nothing). The code's awaits are lowered so that they go\n // through them: by bundleWorkerForBrowser for a bundle, by createProjectSite (nodeCompat) for\n // a site's modules.\n installAsyncContext();\n }\n const globals = {\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 (\"site\" in code) {\n workersHostRegistry({\n workersModule,\n projectWorkersModule: {\n ...workersModule,\n env: scope.env,\n exports: scope.exports,\n waitUntil: scope.waitUntil,\n },\n loadedPrefix: `${code.site}loaded/`,\n emailModule: await import(\"./cloudflare-email.js\"),\n ...globals,\n // Loaded on demand, after installNodeGlobals(): the npm `util` polyfill reads `process`\n // when it is imported.\n node: nodeCompat\n ? (await import(\"../node-compat/browser-registry.js\")).nodeRegistryEntries\n : undefined,\n });\n return config.main\n ? await import(/* @vite-ignore */ `${code.site}modules/~/${config.main}`)\n : { default: {} };\n }\n const g = globalThis as Record<string, unknown>;\n g.__cellsWorkersModule = workersModule;\n g.__cellsProjectScope = scope; // `env` and `exports` of the bundle's cloudflare:workers\n g.__cellsGlobals = globals;\n return code.bundle\n ? await import(\n /* @vite-ignore */ URL.createObjectURL(new Blob([code.bundle], { type: \"text/javascript\" }))\n )\n : { default: {} };\n}\n\n/**\n * A project's runtime in this worker: installs the Workers globals, imports the code and\n * builds its Worker Loader; `close()` also releases the node's bucket lease.\n */\nexport async function browserProjectRuntime(opts: BrowserProjectOptions) {\n const scope = workerScope(loadTimeEnv(opts.config, opts.ai));\n const module = await importWorkerCode(opts.config, opts.code, scope);\n const site = \"site\" in opts.code ? opts.code.site : undefined;\n // With an IndexedDB bucket, cells live in memory and in the bucket's logs (no OPFS pool).\n const openSql =\n opts.bucket && \"ltx\" in opts.bucket\n ? await ltxOpener(\n opts.sqlite3,\n opts.bucket.ltx,\n opts.bucket.compactAfter,\n opts.bucket.files,\n opts.bucket.ltxStore,\n )\n : opts.bucket && \"idb\" in opts.bucket\n ? Object.assign(wasmMemoryOpener(opts.sqlite3 as never), {\n release() {},\n reserve: async (n: number) => n,\n })\n : await sahpoolOpener(opts.sqlite3 as never, {\n name: opts.pool,\n initialCapacity: 64, // grows on demand (sahpoolOpener)\n });\n const root = await navigator.storage.getDirectory();\n const files = new BrowserFilesApi({\n rootHandle: await root.getDirectoryHandle(opts.filesDir, { create: true }),\n });\n // An `ltx` directory is the cells' own storage (the VFS), not a fleet bucket.\n const store = opts.bucket && !(\"ltx\" in opts.bucket) ? await bucketStore(opts.bucket) : undefined;\n const shared =\n opts.bucket && store\n ? celldBucket(store, { node: opts.bucket.node, leaseTtlMs: opts.bucket.leaseTtlMs })\n : undefined;\n const { runtime, unsupported } = createProjectRuntime(opts.config, module, {\n bindings: await loadProjectBindings(opts.config),\n openSql,\n files,\n assetFiles: opts.assetFiles,\n loadModules: site ? siteModuleLoader(site) : browserModuleLoader(),\n isolatedModules: opts.isolateScript\n ? browserIsolatedLoader({\n isolateScript: opts.isolateScript,\n siteBaseUrl: site,\n storagePrefix: `${opts.pool}-iso`,\n storage: () => shared, // facets of loaded code are logged like the root's own\n })\n : undefined,\n storage: shared, // R2 objects in the fleet bucket too, as celld keeps them\n route: opts.route,\n ai: opts.ai,\n });\n scope.bind(runtime);\n return {\n runtime,\n unsupported,\n bucket: shared,\n /** The cells' databases in the OPFS pool (none with a bucket: there the bucket has them). */\n exportCells: async (): Promise<[string, Uint8Array][]> =>\n (openSql as { exportFiles?: () => [string, Uint8Array][] }).exportFiles?.() ?? [],\n close: async () => {\n await runtime.close();\n openSql.release(); // the pool's files, for the next worker that opens it\n },\n };\n}\n"]}
@@ -81,6 +81,7 @@ async function run(built, code, options, release) {
81
81
  runtime,
82
82
  unsupported: project.unsupported,
83
83
  fetch: (req) => runtime.fetch(req),
84
+ exportCells: () => project.exportCells(),
84
85
  close: async () => {
85
86
  try {
86
87
  await project.close();
@@ -1 +1 @@
1
- {"version":3,"file":"browser-load.js","sourceRoot":"","sources":["../../src/project/browser-load.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `loadProject` in a browser (`@statewalker/cellb/browser`), in a Dedicated Worker: fetches a\n * folder written by `cellb build`, or compiles a source folder with the `compile` it is given,\n * and runs it with `browserProjectRuntime`.\n */\n\nimport { type BrowserBucket, browserProjectRuntime } from \"./browser-host.js\";\nimport {\n BUILD_MANIFEST,\n type BuiltProject,\n filesApiReader,\n isFilesApi,\n type LoadedProject,\n type LoadProjectOptions,\n type ProjectSource,\n readBuildManifest,\n readBuiltProject,\n urlReader,\n} from \"./built-project.js\";\nimport {\n type CompiledProject,\n hasNodeCompat,\n type ProjectCompiler,\n readSourceProject,\n WRANGLER_FILES,\n} from \"./source-project.js\";\n\nexport interface BrowserLoadProjectOptions extends LoadProjectOptions<BrowserBucket> {\n /**\n * Where loaded Workers (Worker Loader) run: the package's own isolate worker by default; a\n * script URL or a function starting a Dedicated Worker instead; `false` to run them in this\n * realm.\n */\n isolateScript?: URL | (() => Worker) | false;\n /**\n * How a source folder (`wrangler.jsonc`, `main`, `package.json`, assets) becomes code, for a\n * FilesApi that holds one: `bundleCompiler` (`@statewalker/cellb/bundle`: webrun-bundler and\n * esbuild-wasm, one ES module) or `siteCompiler` (`@statewalker/cellb/site`: modules compiled\n * one by one and served from a ServiceWorker). Without it, only `cellb build` folders load.\n * A folder written by `cellb build` loads as built either way.\n */\n compile?: ProjectCompiler;\n}\n\n/** The isolate worker this package ships (bundlers follow the `new Worker(new URL(…))` form). */\nconst ownIsolate = () =>\n new Worker(new URL(\"../isolate/isolate-worker.ts\", import.meta.url), { type: \"module\" });\n\n/**\n * Loads a project and runs it in this worker.\n *\n * `source`: the URL of a `cellb build` folder (relative URLs resolve against the page or\n * worker), or a FilesApi holding one — or, with `options.compile`, a FilesApi holding the\n * project's sources (`wrangler.jsonc` and `main` at its root, `package.json`, assets).\n * `options.data` names the OPFS pool (`<data>`) and the project's files directory\n * (`<data>-files`); it defaults to the project's `name`.\n */\nexport async function loadProject(\n source: ProjectSource,\n options: BrowserLoadProjectOptions = {},\n): Promise<LoadedProject> {\n let reader: ReturnType<typeof urlReader>;\n let where: string;\n if (isFilesApi(source)) {\n reader = filesApiReader(source);\n where = \"the FilesApi\";\n } else {\n const url = new URL(String(source), (globalThis as { location?: Location }).location?.href);\n if (!url.pathname.endsWith(\"/\")) url.pathname += \"/\";\n reader = urlReader(url);\n where = url.href;\n }\n const manifest = await readBuildManifest(reader);\n let built: BuiltProject;\n let compiled: CompiledProject | undefined;\n if (manifest) built = await readBuiltProject(reader, manifest);\n else if (isFilesApi(source) && options.compile) {\n const project = await readSourceProject(source);\n if (!project)\n throw new Error(\n `the FilesApi has neither ${BUILD_MANIFEST} nor ${WRANGLER_FILES.join(\" nor \")}`,\n );\n const { config } = project;\n compiled = config.main\n ? await options.compile.compile({ files: source, config, nodeCompat: hasNodeCompat(config) })\n : { code: { bundle: null } };\n built = { config, code: null, assets: project.assets ?? new Map() };\n } else\n throw new Error(\n isFilesApi(source)\n ? `${where} has no ${BUILD_MANIFEST}: pass \\`compile\\` to load a source folder, or load a folder written by \\`cellb build\\``\n : `${where} has no ${BUILD_MANIFEST}: browsers load folders written by \\`cellb build\\` by URL (a source folder loads from a FilesApi, with \\`compile\\`)`,\n );\n try {\n const close = compiled?.close?.bind(compiled);\n const release = close && (() => close());\n return await run(built, compiled?.code ?? { bundle: built.code }, options, release);\n } catch (err) {\n await compiled?.close?.().catch(() => {});\n throw err;\n }\n}\n\nasync function run(\n built: BuiltProject,\n code: CompiledProject[\"code\"],\n options: BrowserLoadProjectOptions,\n release?: () => Promise<void>,\n): Promise<LoadedProject> {\n const data = options.data ?? built.config.name ?? \"cellb\";\n const sqlite3 = options.sqlite3 ?? (await defaultSqlite3());\n const isolateScript =\n options.isolateScript === false ? undefined : (options.isolateScript ?? ownIsolate);\n const project = await browserProjectRuntime({\n config: built.config,\n code,\n assetFiles: built.assets,\n sqlite3,\n pool: data,\n filesDir: `${data}-files`,\n bucket: options.bucket,\n ai: options.ai,\n isolateScript,\n });\n const { runtime } = project;\n return {\n config: built.config,\n runtime,\n unsupported: project.unsupported,\n fetch: (req) => runtime.fetch(req),\n close: async () => {\n try {\n await project.close();\n } finally {\n await release?.();\n }\n },\n };\n}\n\nlet sqlite3Module: Promise<unknown> | undefined;\n/** `@sqlite.org/sqlite-wasm`, initialized once per worker. */\nfunction defaultSqlite3(): Promise<unknown> {\n sqlite3Module ??= import(\"@sqlite.org/sqlite-wasm\").then(({ default: init }) =>\n (init as (o: object) => Promise<unknown>)({ print() {}, printErr() {} }),\n );\n return sqlite3Module;\n}\n"]}
1
+ {"version":3,"file":"browser-load.js","sourceRoot":"","sources":["../../src/project/browser-load.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `loadProject` in a browser (`@statewalker/cellb/browser`), in a Dedicated Worker: fetches a\n * folder written by `cellb build`, or compiles a source folder with the `compile` it is given,\n * and runs it with `browserProjectRuntime`.\n */\n\nimport { type BrowserBucket, browserProjectRuntime } from \"./browser-host.js\";\nimport {\n BUILD_MANIFEST,\n type BuiltProject,\n filesApiReader,\n isFilesApi,\n type LoadedProject,\n type LoadProjectOptions,\n type ProjectSource,\n readBuildManifest,\n readBuiltProject,\n urlReader,\n} from \"./built-project.js\";\nimport {\n type CompiledProject,\n hasNodeCompat,\n type ProjectCompiler,\n readSourceProject,\n WRANGLER_FILES,\n} from \"./source-project.js\";\n\nexport interface BrowserLoadProjectOptions extends LoadProjectOptions<BrowserBucket> {\n /**\n * Where loaded Workers (Worker Loader) run: the package's own isolate worker by default; a\n * script URL or a function starting a Dedicated Worker instead; `false` to run them in this\n * realm.\n */\n isolateScript?: URL | (() => Worker) | false;\n /**\n * How a source folder (`wrangler.jsonc`, `main`, `package.json`, assets) becomes code, for a\n * FilesApi that holds one: `bundleCompiler` (`@statewalker/cellb/bundle`: webrun-bundler and\n * esbuild-wasm, one ES module) or `siteCompiler` (`@statewalker/cellb/site`: modules compiled\n * one by one and served from a ServiceWorker). Without it, only `cellb build` folders load.\n * A folder written by `cellb build` loads as built either way.\n */\n compile?: ProjectCompiler;\n}\n\n/** The isolate worker this package ships (bundlers follow the `new Worker(new URL(…))` form). */\nconst ownIsolate = () =>\n new Worker(new URL(\"../isolate/isolate-worker.ts\", import.meta.url), { type: \"module\" });\n\n/**\n * Loads a project and runs it in this worker.\n *\n * `source`: the URL of a `cellb build` folder (relative URLs resolve against the page or\n * worker), or a FilesApi holding one — or, with `options.compile`, a FilesApi holding the\n * project's sources (`wrangler.jsonc` and `main` at its root, `package.json`, assets).\n * `options.data` names the OPFS pool (`<data>`) and the project's files directory\n * (`<data>-files`); it defaults to the project's `name`.\n */\nexport async function loadProject(\n source: ProjectSource,\n options: BrowserLoadProjectOptions = {},\n): Promise<LoadedProject> {\n let reader: ReturnType<typeof urlReader>;\n let where: string;\n if (isFilesApi(source)) {\n reader = filesApiReader(source);\n where = \"the FilesApi\";\n } else {\n const url = new URL(String(source), (globalThis as { location?: Location }).location?.href);\n if (!url.pathname.endsWith(\"/\")) url.pathname += \"/\";\n reader = urlReader(url);\n where = url.href;\n }\n const manifest = await readBuildManifest(reader);\n let built: BuiltProject;\n let compiled: CompiledProject | undefined;\n if (manifest) built = await readBuiltProject(reader, manifest);\n else if (isFilesApi(source) && options.compile) {\n const project = await readSourceProject(source);\n if (!project)\n throw new Error(\n `the FilesApi has neither ${BUILD_MANIFEST} nor ${WRANGLER_FILES.join(\" nor \")}`,\n );\n const { config } = project;\n compiled = config.main\n ? await options.compile.compile({ files: source, config, nodeCompat: hasNodeCompat(config) })\n : { code: { bundle: null } };\n built = { config, code: null, assets: project.assets ?? new Map() };\n } else\n throw new Error(\n isFilesApi(source)\n ? `${where} has no ${BUILD_MANIFEST}: pass \\`compile\\` to load a source folder, or load a folder written by \\`cellb build\\``\n : `${where} has no ${BUILD_MANIFEST}: browsers load folders written by \\`cellb build\\` by URL (a source folder loads from a FilesApi, with \\`compile\\`)`,\n );\n try {\n const close = compiled?.close?.bind(compiled);\n const release = close && (() => close());\n return await run(built, compiled?.code ?? { bundle: built.code }, options, release);\n } catch (err) {\n await compiled?.close?.().catch(() => {});\n throw err;\n }\n}\n\nasync function run(\n built: BuiltProject,\n code: CompiledProject[\"code\"],\n options: BrowserLoadProjectOptions,\n release?: () => Promise<void>,\n): Promise<LoadedProject> {\n const data = options.data ?? built.config.name ?? \"cellb\";\n const sqlite3 = options.sqlite3 ?? (await defaultSqlite3());\n const isolateScript =\n options.isolateScript === false ? undefined : (options.isolateScript ?? ownIsolate);\n const project = await browserProjectRuntime({\n config: built.config,\n code,\n assetFiles: built.assets,\n sqlite3,\n pool: data,\n filesDir: `${data}-files`,\n bucket: options.bucket,\n ai: options.ai,\n isolateScript,\n });\n const { runtime } = project;\n return {\n config: built.config,\n runtime,\n unsupported: project.unsupported,\n fetch: (req) => runtime.fetch(req),\n exportCells: () => project.exportCells(),\n close: async () => {\n try {\n await project.close();\n } finally {\n await release?.();\n }\n },\n };\n}\n\nlet sqlite3Module: Promise<unknown> | undefined;\n/** `@sqlite.org/sqlite-wasm`, initialized once per worker. */\nfunction defaultSqlite3(): Promise<unknown> {\n sqlite3Module ??= import(\"@sqlite.org/sqlite-wasm\").then(({ default: init }) =>\n (init as (o: object) => Promise<unknown>)({ print() {}, printErr() {} }),\n );\n return sqlite3Module;\n}\n"]}
@@ -6,7 +6,7 @@ import { type ModuleLoader } from "../bindings/worker-loader.js";
6
6
  * bundled with the Worker, so it declares no names beyond its exports: esbuild would rename the
7
7
  * Worker's own variables of the same name, and those names show in error messages.
8
8
  */
9
- export declare const PROJECT_WORKERS_MODULE_SHIM = "const m = globalThis.__cellsWorkersModule; export const DurableObject = m.DurableObject, WorkerEntrypoint = m.WorkerEntrypoint, WorkflowEntrypoint = m.WorkflowEntrypoint, RpcTarget = m.RpcTarget; export default m; export const env = globalThis.__cellsProjectScope?.env ?? {}, exports = globalThis.__cellsProjectScope?.exports ?? {}, waitUntil = (p) => globalThis.__cellsProjectScope?.waitUntil(p);";
9
+ export declare const PROJECT_WORKERS_MODULE_SHIM = "const m = globalThis.__cellsWorkersModule; export const DurableObject = m.DurableObject, WorkerEntrypoint = m.WorkerEntrypoint, WorkflowEntrypoint = m.WorkflowEntrypoint, RpcTarget = m.RpcTarget, abortIsolate = m.abortIsolate; export default m; export const env = globalThis.__cellsProjectScope?.env ?? {}, exports = globalThis.__cellsProjectScope?.exports ?? {}, waitUntil = (p) => globalThis.__cellsProjectScope?.waitUntil(p);";
10
10
  /**
11
11
  * Worker Loader in a browser realm: each module of a WorkerCode becomes a Blob-URL ES
12
12
  * module. `cloudflare:workers` resolves to a shim reading the runtime's own classes from
@@ -14,4 +14,10 @@ export declare const PROJECT_WORKERS_MODULE_SHIM = "const m = globalThis.__cells
14
14
  * `workersModuleShim`, the same for every load); relative imports resolve to the Blob URLs of
15
15
  * sibling modules; with a log sink the module gets a module-scoped `console` (Tail Workers).
16
16
  */
17
- export declare function browserModuleLoader(workersModuleShim?: string): ModuleLoader;
17
+ export declare function browserModuleLoader(workersModuleShim?: string, opts?: {
18
+ /**
19
+ * This realm is the loaded Worker's own (an isolate): an `import()` in code it builds with
20
+ * `Function` resolves against its modules too (isolate/function-imports.ts).
21
+ */
22
+ functionImports?: boolean;
23
+ }): ModuleLoader;
@@ -1,8 +1,10 @@
1
- import { moduleText, outboundFetch, } from "../bindings/worker-loader.js";
1
+ import { IMPORT_FROM, prefixModule, resolveModuleName, routeDynamicImports, } from "../bindings/module-registry.js";
2
+ import { compileWasmModules, moduleText, outboundFetch, } from "../bindings/worker-loader.js";
2
3
  import { ctxExports } from "../core/handles.js";
4
+ import { FUNCTION_IMPORT } from "../isolate/function-imports.js";
3
5
  import { rewriteModuleSpecifiers } from "./module-specifiers.js";
4
6
  import { workerScope } from "./worker-scope.js";
5
- const WORKERS_CLASSES = "const m = globalThis.__cellsWorkersModule; export const DurableObject = m.DurableObject, WorkerEntrypoint = m.WorkerEntrypoint, WorkflowEntrypoint = m.WorkflowEntrypoint, RpcTarget = m.RpcTarget; export default m;";
7
+ const WORKERS_CLASSES = "const m = globalThis.__cellsWorkersModule; export const DurableObject = m.DurableObject, WorkerEntrypoint = m.WorkerEntrypoint, WorkflowEntrypoint = m.WorkflowEntrypoint, RpcTarget = m.RpcTarget, abortIsolate = m.abortIsolate; export default m;";
6
8
  /**
7
9
  * `cloudflare:workers` for a project's own bundle: the classes, and the project's `env` and
8
10
  * `exports` from `globalThis.__cellsProjectScope` (set by `browserProjectRuntime`, and by
@@ -18,10 +20,11 @@ export const PROJECT_WORKERS_MODULE_SHIM = `${WORKERS_CLASSES} export const env
18
20
  * `workersModuleShim`, the same for every load); relative imports resolve to the Blob URLs of
19
21
  * sibling modules; with a log sink the module gets a module-scoped `console` (Tail Workers).
20
22
  */
21
- export function browserModuleLoader(workersModuleShim) {
23
+ export function browserModuleLoader(workersModuleShim, opts = {}) {
22
24
  const blob = (text) => URL.createObjectURL(new Blob([text], { type: "text/javascript" }));
23
25
  const fixedShimUrl = workersModuleShim && blob(workersModuleShim);
24
- return async (_id, code, logs) => {
26
+ return async (_id, loaded, logs) => {
27
+ const code = await compileWasmModules(loaded);
25
28
  const env = code.env ?? {};
26
29
  const scope = fixedShimUrl ? undefined : workerScope(env);
27
30
  let shimUrl = fixedShimUrl;
@@ -59,6 +62,27 @@ export function browserModuleLoader(workersModuleShim) {
59
62
  g.__cellsOutbound[key] = outbound;
60
63
  consolePrelude += `const fetch = globalThis.__cellsOutbound[${JSON.stringify(key)}];\n`;
61
64
  }
65
+ // `import()` the Blob URLs cannot link (a computed specifier, a module's whole name) resolves
66
+ // against this load's modules at run time (module-registry.ts).
67
+ const names = new Set(Object.keys(code.modules));
68
+ const importsKey = `i${Math.random().toString(36).slice(2)}`;
69
+ const g = globalThis;
70
+ g.__cellsImports ??= {};
71
+ const imports = g.__cellsImports;
72
+ imports[importsKey] = (spec, importer) => {
73
+ const name = resolveModuleName(String(spec), importer, names);
74
+ return import(/* @vite-ignore */ name === undefined ? String(spec) : urlOf(name));
75
+ };
76
+ // Code built with `Function` has no module of its own: it resolves from the main module.
77
+ if (opts.functionImports)
78
+ g[FUNCTION_IMPORT] = (spec) => imports[importsKey](spec, code.mainModule);
79
+ const routed = (name) => {
80
+ const text = source(name);
81
+ const out = routeDynamicImports(text, name);
82
+ return out === undefined
83
+ ? text
84
+ : prefixModule(out, `const ${IMPORT_FROM} = globalThis.__cellsImports[${JSON.stringify(importsKey)}]; `);
85
+ };
62
86
  const urls = new Map();
63
87
  // Modules whose Blob URL is being made: a Blob URL exists only once its text (with its
64
88
  // imports' URLs) does, so modules that import each other cannot be loaded this way.
@@ -67,7 +91,7 @@ export function browserModuleLoader(workersModuleShim) {
67
91
  const m = code.modules[name];
68
92
  if (m === undefined)
69
93
  throw new Error(`Worker Loader: module "${name}" not found`);
70
- return moduleText(m);
94
+ return moduleText(m, name, names);
71
95
  };
72
96
  const urlOf = (name) => {
73
97
  const known = urls.get(name);
@@ -79,7 +103,7 @@ export function browserModuleLoader(workersModuleShim) {
79
103
  const base = name.includes("/") ? name.slice(0, name.lastIndexOf("/") + 1) : "";
80
104
  // Only the module's own imports: the same words in a string, a template or a comment are
81
105
  // not imports (a code generator's template may well contain `from "cloudflare:workers"`).
82
- const text = rewriteModuleSpecifiers(source(name), (spec) => {
106
+ const text = rewriteModuleSpecifiers(routed(name), (spec) => {
83
107
  if (spec === "cloudflare:workers")
84
108
  return shimUrl;
85
109
  if (spec.startsWith("./") || spec.startsWith("../"))
@@ -1 +1 @@
1
- {"version":3,"file":"browser-modules.js","sourceRoot":"","sources":["../../src/project/browser-modules.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type LogSink,\n type ModuleLoader,\n moduleText,\n outboundFetch,\n type WorkerCode,\n} from \"../bindings/worker-loader.js\";\nimport { ctxExports } from \"../core/handles.js\";\nimport { rewriteModuleSpecifiers } from \"./module-specifiers.js\";\nimport { workerScope } from \"./worker-scope.js\";\n\nconst WORKERS_CLASSES =\n \"const m = globalThis.__cellsWorkersModule; export const DurableObject = m.DurableObject, WorkerEntrypoint = m.WorkerEntrypoint, WorkflowEntrypoint = m.WorkflowEntrypoint, RpcTarget = m.RpcTarget; export default m;\";\n\n/**\n * `cloudflare:workers` for a project's own bundle: the classes, and the project's `env` and\n * `exports` from `globalThis.__cellsProjectScope` (set by `browserProjectRuntime`, and by\n * `serveIsolate` for the loaded Worker an isolate runs). The shim is\n * bundled with the Worker, so it declares no names beyond its exports: esbuild would rename the\n * Worker's own variables of the same name, and those names show in error messages.\n */\nexport const PROJECT_WORKERS_MODULE_SHIM = `${WORKERS_CLASSES} export const env = globalThis.__cellsProjectScope?.env ?? {}, exports = globalThis.__cellsProjectScope?.exports ?? {}, waitUntil = (p) => globalThis.__cellsProjectScope?.waitUntil(p);`;\n\n/**\n * Worker Loader in a browser realm: each module of a WorkerCode becomes a Blob-URL ES\n * module. `cloudflare:workers` resolves to a shim reading the runtime's own classes from\n * `globalThis.__cellsWorkersModule` and the loaded code's own `env` and `exports` (or to\n * `workersModuleShim`, the same for every load); relative imports resolve to the Blob URLs of\n * sibling modules; with a log sink the module gets a module-scoped `console` (Tail Workers).\n */\nexport function browserModuleLoader(workersModuleShim?: string): ModuleLoader {\n const blob = (text: string) => URL.createObjectURL(new Blob([text], { type: \"text/javascript\" }));\n const fixedShimUrl = workersModuleShim && blob(workersModuleShim);\n return async (_id: string, code: WorkerCode, logs?: LogSink) => {\n const env = code.env ?? {};\n const scope = fixedShimUrl ? undefined : workerScope(env);\n let shimUrl = fixedShimUrl;\n if (scope) {\n const key = `s${Math.random().toString(36).slice(2)}`;\n const g = globalThis as Record<string, unknown>;\n g.__cellsWorkerScopes ??= {};\n (g.__cellsWorkerScopes as Record<string, unknown>)[key] = scope;\n shimUrl = blob(\n `${WORKERS_CLASSES} const s = globalThis.__cellsWorkerScopes[${JSON.stringify(key)}]; export const env = s.env, exports = s.exports, waitUntil = s.waitUntil;`,\n );\n }\n let consolePrelude = \"\";\n if (logs) {\n const key = `c${Math.random().toString(36).slice(2)}`;\n const g = globalThis as Record<string, unknown>;\n g.__cellsConsoles ??= {};\n const real = globalThis.console;\n const wrap =\n (level: \"log\" | \"info\" | \"warn\" | \"error\" | \"debug\") =>\n (...args: unknown[]) => {\n logs(level, args);\n real[level](...args);\n };\n (g.__cellsConsoles as Record<string, unknown>)[key] = Object.assign(Object.create(real), {\n log: wrap(\"log\"),\n info: wrap(\"info\"),\n warn: wrap(\"warn\"),\n error: wrap(\"error\"),\n debug: wrap(\"debug\"),\n });\n consolePrelude = `const console = globalThis.__cellsConsoles[${JSON.stringify(key)}];\\n`;\n }\n const outbound = outboundFetch(code);\n if (outbound) {\n const key = `o${Math.random().toString(36).slice(2)}`;\n const g = globalThis as Record<string, unknown>;\n g.__cellsOutbound ??= {};\n (g.__cellsOutbound as Record<string, unknown>)[key] = outbound;\n consolePrelude += `const fetch = globalThis.__cellsOutbound[${JSON.stringify(key)}];\\n`;\n }\n const urls = new Map<string, string>();\n // Modules whose Blob URL is being made: a Blob URL exists only once its text (with its\n // imports' URLs) does, so modules that import each other cannot be loaded this way.\n const making: string[] = [];\n const source = (name: string) => {\n const m = code.modules[name];\n if (m === undefined) throw new Error(`Worker Loader: module \"${name}\" not found`);\n return moduleText(m);\n };\n const urlOf = (name: string): string => {\n const known = urls.get(name);\n if (known) return known;\n if (making.includes(name))\n throw new Error(\n `Worker Loader: modules import each other (${[...making.slice(making.indexOf(name)), name].join(\" → \")}); a browser realm loads each module from a Blob URL, which cannot form a cycle`,\n );\n making.push(name);\n const base = name.includes(\"/\") ? name.slice(0, name.lastIndexOf(\"/\") + 1) : \"\";\n // Only the module's own imports: the same words in a string, a template or a comment are\n // not imports (a code generator's template may well contain `from \"cloudflare:workers\"`).\n const text = rewriteModuleSpecifiers(source(name), (spec) => {\n if (spec === \"cloudflare:workers\") return shimUrl;\n if (spec.startsWith(\"./\") || spec.startsWith(\"../\"))\n return urlOf(new URL(spec, `file:///${base}`).pathname.slice(1));\n return undefined;\n });\n const url = URL.createObjectURL(\n new Blob([consolePrelude + text], { type: \"text/javascript\" }),\n );\n urls.set(name, url);\n making.pop();\n return url;\n };\n const module = (await import(/* @vite-ignore */ urlOf(code.mainModule))) as Record<\n string,\n unknown\n >;\n scope?.bind({ env, exports: ctxExports(module, env) });\n return module;\n };\n}\n"]}
1
+ {"version":3,"file":"browser-modules.js","sourceRoot":"","sources":["../../src/project/browser-modules.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n IMPORT_FROM,\n prefixModule,\n resolveModuleName,\n routeDynamicImports,\n} from \"../bindings/module-registry.js\";\nimport {\n compileWasmModules,\n type LogSink,\n type ModuleLoader,\n moduleText,\n outboundFetch,\n type WorkerCode,\n} from \"../bindings/worker-loader.js\";\nimport { ctxExports } from \"../core/handles.js\";\nimport { FUNCTION_IMPORT } from \"../isolate/function-imports.js\";\nimport { rewriteModuleSpecifiers } from \"./module-specifiers.js\";\nimport { workerScope } from \"./worker-scope.js\";\n\nconst WORKERS_CLASSES =\n \"const m = globalThis.__cellsWorkersModule; export const DurableObject = m.DurableObject, WorkerEntrypoint = m.WorkerEntrypoint, WorkflowEntrypoint = m.WorkflowEntrypoint, RpcTarget = m.RpcTarget, abortIsolate = m.abortIsolate; export default m;\";\n\n/**\n * `cloudflare:workers` for a project's own bundle: the classes, and the project's `env` and\n * `exports` from `globalThis.__cellsProjectScope` (set by `browserProjectRuntime`, and by\n * `serveIsolate` for the loaded Worker an isolate runs). The shim is\n * bundled with the Worker, so it declares no names beyond its exports: esbuild would rename the\n * Worker's own variables of the same name, and those names show in error messages.\n */\nexport const PROJECT_WORKERS_MODULE_SHIM = `${WORKERS_CLASSES} export const env = globalThis.__cellsProjectScope?.env ?? {}, exports = globalThis.__cellsProjectScope?.exports ?? {}, waitUntil = (p) => globalThis.__cellsProjectScope?.waitUntil(p);`;\n\n/**\n * Worker Loader in a browser realm: each module of a WorkerCode becomes a Blob-URL ES\n * module. `cloudflare:workers` resolves to a shim reading the runtime's own classes from\n * `globalThis.__cellsWorkersModule` and the loaded code's own `env` and `exports` (or to\n * `workersModuleShim`, the same for every load); relative imports resolve to the Blob URLs of\n * sibling modules; with a log sink the module gets a module-scoped `console` (Tail Workers).\n */\nexport function browserModuleLoader(\n workersModuleShim?: string,\n opts: {\n /**\n * This realm is the loaded Worker's own (an isolate): an `import()` in code it builds with\n * `Function` resolves against its modules too (isolate/function-imports.ts).\n */\n functionImports?: boolean;\n } = {},\n): ModuleLoader {\n const blob = (text: string) => URL.createObjectURL(new Blob([text], { type: \"text/javascript\" }));\n const fixedShimUrl = workersModuleShim && blob(workersModuleShim);\n return async (_id: string, loaded: WorkerCode, logs?: LogSink) => {\n const code = await compileWasmModules(loaded);\n const env = code.env ?? {};\n const scope = fixedShimUrl ? undefined : workerScope(env);\n let shimUrl = fixedShimUrl;\n if (scope) {\n const key = `s${Math.random().toString(36).slice(2)}`;\n const g = globalThis as Record<string, unknown>;\n g.__cellsWorkerScopes ??= {};\n (g.__cellsWorkerScopes as Record<string, unknown>)[key] = scope;\n shimUrl = blob(\n `${WORKERS_CLASSES} const s = globalThis.__cellsWorkerScopes[${JSON.stringify(key)}]; export const env = s.env, exports = s.exports, waitUntil = s.waitUntil;`,\n );\n }\n let consolePrelude = \"\";\n if (logs) {\n const key = `c${Math.random().toString(36).slice(2)}`;\n const g = globalThis as Record<string, unknown>;\n g.__cellsConsoles ??= {};\n const real = globalThis.console;\n const wrap =\n (level: \"log\" | \"info\" | \"warn\" | \"error\" | \"debug\") =>\n (...args: unknown[]) => {\n logs(level, args);\n real[level](...args);\n };\n (g.__cellsConsoles as Record<string, unknown>)[key] = Object.assign(Object.create(real), {\n log: wrap(\"log\"),\n info: wrap(\"info\"),\n warn: wrap(\"warn\"),\n error: wrap(\"error\"),\n debug: wrap(\"debug\"),\n });\n consolePrelude = `const console = globalThis.__cellsConsoles[${JSON.stringify(key)}];\\n`;\n }\n const outbound = outboundFetch(code);\n if (outbound) {\n const key = `o${Math.random().toString(36).slice(2)}`;\n const g = globalThis as Record<string, unknown>;\n g.__cellsOutbound ??= {};\n (g.__cellsOutbound as Record<string, unknown>)[key] = outbound;\n consolePrelude += `const fetch = globalThis.__cellsOutbound[${JSON.stringify(key)}];\\n`;\n }\n // `import()` the Blob URLs cannot link (a computed specifier, a module's whole name) resolves\n // against this load's modules at run time (module-registry.ts).\n const names = new Set(Object.keys(code.modules));\n const importsKey = `i${Math.random().toString(36).slice(2)}`;\n const g = globalThis as Record<string, unknown>;\n g.__cellsImports ??= {};\n const imports = g.__cellsImports as Record<string, unknown>;\n imports[importsKey] = (spec: unknown, importer: string) => {\n const name = resolveModuleName(String(spec), importer, names);\n return import(/* @vite-ignore */ name === undefined ? String(spec) : urlOf(name));\n };\n // Code built with `Function` has no module of its own: it resolves from the main module.\n if (opts.functionImports)\n g[FUNCTION_IMPORT] = (spec: unknown) =>\n (imports[importsKey] as (s: unknown, i: string) => Promise<unknown>)(spec, code.mainModule);\n const routed = (name: string) => {\n const text = source(name);\n const out = routeDynamicImports(text, name);\n return out === undefined\n ? text\n : prefixModule(\n out,\n `const ${IMPORT_FROM} = globalThis.__cellsImports[${JSON.stringify(importsKey)}]; `,\n );\n };\n const urls = new Map<string, string>();\n // Modules whose Blob URL is being made: a Blob URL exists only once its text (with its\n // imports' URLs) does, so modules that import each other cannot be loaded this way.\n const making: string[] = [];\n const source = (name: string) => {\n const m = code.modules[name];\n if (m === undefined) throw new Error(`Worker Loader: module \"${name}\" not found`);\n return moduleText(m, name, names);\n };\n const urlOf = (name: string): string => {\n const known = urls.get(name);\n if (known) return known;\n if (making.includes(name))\n throw new Error(\n `Worker Loader: modules import each other (${[...making.slice(making.indexOf(name)), name].join(\" → \")}); a browser realm loads each module from a Blob URL, which cannot form a cycle`,\n );\n making.push(name);\n const base = name.includes(\"/\") ? name.slice(0, name.lastIndexOf(\"/\") + 1) : \"\";\n // Only the module's own imports: the same words in a string, a template or a comment are\n // not imports (a code generator's template may well contain `from \"cloudflare:workers\"`).\n const text = rewriteModuleSpecifiers(routed(name), (spec) => {\n if (spec === \"cloudflare:workers\") return shimUrl;\n if (spec.startsWith(\"./\") || spec.startsWith(\"../\"))\n return urlOf(new URL(spec, `file:///${base}`).pathname.slice(1));\n return undefined;\n });\n const url = URL.createObjectURL(\n new Blob([consolePrelude + text], { type: \"text/javascript\" }),\n );\n urls.set(name, url);\n making.pop();\n return url;\n };\n const module = (await import(/* @vite-ignore */ urlOf(code.mainModule))) as Record<\n string,\n unknown\n >;\n scope?.bind({ env, exports: ctxExports(module, env) });\n return module;\n };\n}\n"]}
@@ -70,6 +70,13 @@ export interface LoadedProject {
70
70
  unsupported: string[];
71
71
  /** A request to the project, as its Worker (and assets) answer it. */
72
72
  fetch(req: Request): Promise<Response>;
73
+ /**
74
+ * In a browser (an OPFS pool): the cells' databases as `[file name, bytes]`, named as
75
+ * `nodeSqliteOpener(dir)` names them, so that a data directory on Node (`loadProject(dir,
76
+ * { data })`) starts where this browser's cells are. CellB's own databases (`__cellb_*`) are
77
+ * included; R2 objects are not. Empty with a bucket (it holds the cells); not defined on Node.
78
+ */
79
+ exportCells?(): Promise<[string, Uint8Array][]>;
73
80
  close(): Promise<void>;
74
81
  }
75
82
  /** Reads JSON (or JSONC) at `path`, or undefined when the file is missing. */
@@ -1 +1 @@
1
- {"version":3,"file":"built-project.js","sourceRoot":"","sources":["../../src/project/built-project.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The folder `cellb build` writes, and what `loadProject` reads, on both platforms:\n *\n * wrangler.json the project's configuration (`main` → \"worker.js\", `assets.directory` → \"assets\")\n * worker.js `main` bundled for a browser realm (bundleWorkerForBrowser), if there is a `main`\n * assets/… the files of `assets.directory`, as they are\n * cellb.json this manifest: the format, and the asset paths (a static host cannot list a folder)\n *\n * Platform-neutral: it reads through a `ProjectReader` (Node's fs, `fetch` of a URL, a FilesApi).\n */\nimport type { FilesApi } from \"@statewalker/webrun-files\";\nimport type { AssetFiles } from \"../bindings/assets.js\";\nimport type { WorkersAiOptions } from \"../bindings/workers-ai.js\";\nimport type { CellRuntime } from \"../core/runtime.js\";\nimport { parseJsonc } from \"./jsonc.js\";\nimport type { WranglerConfig } from \"./wrangler.js\";\n\n/** The manifest's file name in a built folder. */\nexport const BUILD_MANIFEST = \"cellb.json\";\n/** The format a built folder declares in its manifest. */\nexport const BUILD_FORMAT = \"cellb-build/1\";\n/** The bundled `main` in a built folder. */\nexport const BUILT_WORKER = \"worker.js\";\n/** The assets directory in a built folder. */\nexport const BUILT_ASSETS = \"assets\";\n\nexport interface BuildManifest {\n format: typeof BUILD_FORMAT;\n /** `worker.js`, or null for a project without `main` (assets only). */\n main: string | null;\n /** The asset files, as paths under `assets/` (\"/index.html\", \"/css/site.css\"). */\n assets: string[];\n}\n\n/** A built project in memory: what `browserProjectRuntime` takes. */\nexport interface BuiltProject {\n config: WranglerConfig;\n /** `main` bundled for a browser realm, or null. */\n code: string | null;\n assets: AssetFiles;\n}\n\n/** Reads the files of a project folder, wherever it lives; `undefined` for a missing file. */\nexport interface ProjectReader {\n bytes(path: string): Promise<Uint8Array | undefined>;\n /** The files under `dir`, as paths relative to it (\"/a/b.html\"); only where the source can list. */\n list?(dir: string): Promise<string[]>;\n}\n\n/** Where `loadProject` finds a project. */\nexport type ProjectSource =\n /** Node: a folder with wrangler.json(c), built or not; browser: the URL of a `cellb build` folder. */\n | string\n | URL\n /** Any FilesApi holding either kind of folder at its root. */\n | FilesApi;\n\n/** Options of `loadProject`, the same on Node and in browsers. */\nexport interface LoadProjectOptions<Bucket = unknown> {\n /**\n * Where cells keep their data. Node: a directory (SQLite files and the project's files under\n * it; default: memory). Browser: an OPFS name, the pool (`<data>`) and the files directory\n * (`<data>-files`) (default: the project's `name`).\n */\n data?: string;\n /** A fleet bucket: a `BrowserBucket` in browsers, a `CellStorage` on Node. */\n bucket?: Bucket;\n /** The OpenAI-compatible endpoint behind the project's `ai` binding (Workers AI). */\n ai?: WorkersAiOptions;\n /** Browser only: an initialized SQLite WASM module (default: loads `@sqlite.org/sqlite-wasm`). */\n sqlite3?: unknown;\n}\n\n/** A running project. */\nexport interface LoadedProject {\n config: WranglerConfig;\n runtime: CellRuntime;\n /** Configuration entries cellb does not run (reported, not silently ignored). */\n unsupported: string[];\n /** A request to the project, as its Worker (and assets) answer it. */\n fetch(req: Request): Promise<Response>;\n close(): Promise<void>;\n}\n\nconst decoder = new TextDecoder();\n\n/** Reads JSON (or JSONC) at `path`, or undefined when the file is missing. */\nexport async function readJson<T>(reader: ProjectReader, path: string): Promise<T | undefined> {\n const bytes = await reader.bytes(path);\n return bytes ? (parseJsonc(decoder.decode(bytes)) as T) : undefined;\n}\n\n/** The manifest of a built folder, or undefined when the folder is not one. */\nexport async function readBuildManifest(reader: ProjectReader): Promise<BuildManifest | undefined> {\n const manifest = await readJson<BuildManifest>(reader, BUILD_MANIFEST);\n if (!manifest) return undefined;\n if (manifest.format !== BUILD_FORMAT)\n throw new Error(`${BUILD_MANIFEST}: unknown format ${JSON.stringify(manifest.format)}`);\n return manifest;\n}\n\n/** Reads a `cellb build` folder: its configuration, its bundled `main` and its assets. */\nexport async function readBuiltProject(\n reader: ProjectReader,\n manifest?: BuildManifest,\n): Promise<BuiltProject> {\n manifest ??= await readBuildManifest(reader);\n if (!manifest) throw new Error(`no ${BUILD_MANIFEST}: not a folder written by \\`cellb build\\``);\n const config = await readJson<WranglerConfig>(reader, \"wrangler.json\");\n if (!config) throw new Error(\"no wrangler.json in the built folder\");\n let code: string | null = null;\n if (manifest.main) {\n const bytes = await reader.bytes(manifest.main);\n if (!bytes) throw new Error(`${manifest.main} is missing from the built folder`);\n code = decoder.decode(bytes);\n }\n const assets: AssetFiles = new Map();\n await Promise.all(\n manifest.assets.map(async (p) => {\n const bytes = await reader.bytes(`${BUILT_ASSETS}${p}`);\n if (!bytes) throw new Error(`${BUILT_ASSETS}${p} is missing from the built folder`);\n assets.set(p, bytes);\n }),\n );\n return { config, code, assets };\n}\n\n/** A reader over a FilesApi, rooted at `root` (\"/\" by default). */\nexport function filesApiReader(files: FilesApi, root = \"/\"): ProjectReader {\n const base = root.endsWith(\"/\") ? root : `${root}/`;\n const at = (p: string) => `${base}${p.replace(/^\\/+/, \"\")}`;\n return {\n async bytes(path) {\n const full = at(path);\n const stats = await files.stats(full);\n if (!stats || stats.kind !== \"file\") return undefined;\n const chunks: Uint8Array[] = [];\n for await (const c of files.read(full)) chunks.push(c);\n return concat(chunks);\n },\n async list(dir) {\n const full = at(dir).replace(/\\/+$/, \"\");\n const out: string[] = [];\n for await (const e of files.list(full, { recursive: true }))\n if (e.kind === \"file\") out.push(e.path.slice(full.length));\n return out;\n },\n };\n}\n\n/** A reader over HTTP: files of the folder at `base` (a URL ending in \"/\"). */\nexport function urlReader(base: URL, fetchFn: typeof fetch = fetch): ProjectReader {\n return {\n async bytes(path) {\n const res = await fetchFn(new URL(path.replace(/^\\/+/, \"\"), base));\n if (res.status === 404) {\n await res.body?.cancel();\n return undefined;\n }\n if (!res.ok) throw new Error(`GET ${new URL(path, base)}: ${res.status} ${res.statusText}`);\n return new Uint8Array(await res.arrayBuffer());\n },\n };\n}\n\n/** Whether `v` is a FilesApi (a source given as files rather than a path or URL). */\nexport function isFilesApi(v: unknown): v is FilesApi {\n return (\n typeof v === \"object\" &&\n v !== null &&\n !(v instanceof URL) &&\n typeof (v as FilesApi).read === \"function\" &&\n typeof (v as FilesApi).list === \"function\" &&\n typeof (v as FilesApi).stats === \"function\"\n );\n}\n\n/** A built project's configuration as `wrangler.json` holds it: `main` and assets renamed. */\nexport function builtConfig(config: WranglerConfig): WranglerConfig {\n const out: WranglerConfig = { ...config };\n if (config.main) out.main = BUILT_WORKER;\n if (config.assets) out.assets = { ...config.assets, directory: BUILT_ASSETS };\n return out;\n}\n\nfunction concat(chunks: Uint8Array[]): Uint8Array {\n if (chunks.length === 1) return chunks[0];\n const out = new Uint8Array(chunks.reduce((n, c) => n + c.length, 0));\n let at = 0;\n for (const c of chunks) {\n out.set(c, at);\n at += c.length;\n }\n return out;\n}\n"]}
1
+ {"version":3,"file":"built-project.js","sourceRoot":"","sources":["../../src/project/built-project.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The folder `cellb build` writes, and what `loadProject` reads, on both platforms:\n *\n * wrangler.json the project's configuration (`main` → \"worker.js\", `assets.directory` → \"assets\")\n * worker.js `main` bundled for a browser realm (bundleWorkerForBrowser), if there is a `main`\n * assets/… the files of `assets.directory`, as they are\n * cellb.json this manifest: the format, and the asset paths (a static host cannot list a folder)\n *\n * Platform-neutral: it reads through a `ProjectReader` (Node's fs, `fetch` of a URL, a FilesApi).\n */\nimport type { FilesApi } from \"@statewalker/webrun-files\";\nimport type { AssetFiles } from \"../bindings/assets.js\";\nimport type { WorkersAiOptions } from \"../bindings/workers-ai.js\";\nimport type { CellRuntime } from \"../core/runtime.js\";\nimport { parseJsonc } from \"./jsonc.js\";\nimport type { WranglerConfig } from \"./wrangler.js\";\n\n/** The manifest's file name in a built folder. */\nexport const BUILD_MANIFEST = \"cellb.json\";\n/** The format a built folder declares in its manifest. */\nexport const BUILD_FORMAT = \"cellb-build/1\";\n/** The bundled `main` in a built folder. */\nexport const BUILT_WORKER = \"worker.js\";\n/** The assets directory in a built folder. */\nexport const BUILT_ASSETS = \"assets\";\n\nexport interface BuildManifest {\n format: typeof BUILD_FORMAT;\n /** `worker.js`, or null for a project without `main` (assets only). */\n main: string | null;\n /** The asset files, as paths under `assets/` (\"/index.html\", \"/css/site.css\"). */\n assets: string[];\n}\n\n/** A built project in memory: what `browserProjectRuntime` takes. */\nexport interface BuiltProject {\n config: WranglerConfig;\n /** `main` bundled for a browser realm, or null. */\n code: string | null;\n assets: AssetFiles;\n}\n\n/** Reads the files of a project folder, wherever it lives; `undefined` for a missing file. */\nexport interface ProjectReader {\n bytes(path: string): Promise<Uint8Array | undefined>;\n /** The files under `dir`, as paths relative to it (\"/a/b.html\"); only where the source can list. */\n list?(dir: string): Promise<string[]>;\n}\n\n/** Where `loadProject` finds a project. */\nexport type ProjectSource =\n /** Node: a folder with wrangler.json(c), built or not; browser: the URL of a `cellb build` folder. */\n | string\n | URL\n /** Any FilesApi holding either kind of folder at its root. */\n | FilesApi;\n\n/** Options of `loadProject`, the same on Node and in browsers. */\nexport interface LoadProjectOptions<Bucket = unknown> {\n /**\n * Where cells keep their data. Node: a directory (SQLite files and the project's files under\n * it; default: memory). Browser: an OPFS name, the pool (`<data>`) and the files directory\n * (`<data>-files`) (default: the project's `name`).\n */\n data?: string;\n /** A fleet bucket: a `BrowserBucket` in browsers, a `CellStorage` on Node. */\n bucket?: Bucket;\n /** The OpenAI-compatible endpoint behind the project's `ai` binding (Workers AI). */\n ai?: WorkersAiOptions;\n /** Browser only: an initialized SQLite WASM module (default: loads `@sqlite.org/sqlite-wasm`). */\n sqlite3?: unknown;\n}\n\n/** A running project. */\nexport interface LoadedProject {\n config: WranglerConfig;\n runtime: CellRuntime;\n /** Configuration entries cellb does not run (reported, not silently ignored). */\n unsupported: string[];\n /** A request to the project, as its Worker (and assets) answer it. */\n fetch(req: Request): Promise<Response>;\n /**\n * In a browser (an OPFS pool): the cells' databases as `[file name, bytes]`, named as\n * `nodeSqliteOpener(dir)` names them, so that a data directory on Node (`loadProject(dir,\n * { data })`) starts where this browser's cells are. CellB's own databases (`__cellb_*`) are\n * included; R2 objects are not. Empty with a bucket (it holds the cells); not defined on Node.\n */\n exportCells?(): Promise<[string, Uint8Array][]>;\n close(): Promise<void>;\n}\n\nconst decoder = new TextDecoder();\n\n/** Reads JSON (or JSONC) at `path`, or undefined when the file is missing. */\nexport async function readJson<T>(reader: ProjectReader, path: string): Promise<T | undefined> {\n const bytes = await reader.bytes(path);\n return bytes ? (parseJsonc(decoder.decode(bytes)) as T) : undefined;\n}\n\n/** The manifest of a built folder, or undefined when the folder is not one. */\nexport async function readBuildManifest(reader: ProjectReader): Promise<BuildManifest | undefined> {\n const manifest = await readJson<BuildManifest>(reader, BUILD_MANIFEST);\n if (!manifest) return undefined;\n if (manifest.format !== BUILD_FORMAT)\n throw new Error(`${BUILD_MANIFEST}: unknown format ${JSON.stringify(manifest.format)}`);\n return manifest;\n}\n\n/** Reads a `cellb build` folder: its configuration, its bundled `main` and its assets. */\nexport async function readBuiltProject(\n reader: ProjectReader,\n manifest?: BuildManifest,\n): Promise<BuiltProject> {\n manifest ??= await readBuildManifest(reader);\n if (!manifest) throw new Error(`no ${BUILD_MANIFEST}: not a folder written by \\`cellb build\\``);\n const config = await readJson<WranglerConfig>(reader, \"wrangler.json\");\n if (!config) throw new Error(\"no wrangler.json in the built folder\");\n let code: string | null = null;\n if (manifest.main) {\n const bytes = await reader.bytes(manifest.main);\n if (!bytes) throw new Error(`${manifest.main} is missing from the built folder`);\n code = decoder.decode(bytes);\n }\n const assets: AssetFiles = new Map();\n await Promise.all(\n manifest.assets.map(async (p) => {\n const bytes = await reader.bytes(`${BUILT_ASSETS}${p}`);\n if (!bytes) throw new Error(`${BUILT_ASSETS}${p} is missing from the built folder`);\n assets.set(p, bytes);\n }),\n );\n return { config, code, assets };\n}\n\n/** A reader over a FilesApi, rooted at `root` (\"/\" by default). */\nexport function filesApiReader(files: FilesApi, root = \"/\"): ProjectReader {\n const base = root.endsWith(\"/\") ? root : `${root}/`;\n const at = (p: string) => `${base}${p.replace(/^\\/+/, \"\")}`;\n return {\n async bytes(path) {\n const full = at(path);\n const stats = await files.stats(full);\n if (!stats || stats.kind !== \"file\") return undefined;\n const chunks: Uint8Array[] = [];\n for await (const c of files.read(full)) chunks.push(c);\n return concat(chunks);\n },\n async list(dir) {\n const full = at(dir).replace(/\\/+$/, \"\");\n const out: string[] = [];\n for await (const e of files.list(full, { recursive: true }))\n if (e.kind === \"file\") out.push(e.path.slice(full.length));\n return out;\n },\n };\n}\n\n/** A reader over HTTP: files of the folder at `base` (a URL ending in \"/\"). */\nexport function urlReader(base: URL, fetchFn: typeof fetch = fetch): ProjectReader {\n return {\n async bytes(path) {\n const res = await fetchFn(new URL(path.replace(/^\\/+/, \"\"), base));\n if (res.status === 404) {\n await res.body?.cancel();\n return undefined;\n }\n if (!res.ok) throw new Error(`GET ${new URL(path, base)}: ${res.status} ${res.statusText}`);\n return new Uint8Array(await res.arrayBuffer());\n },\n };\n}\n\n/** Whether `v` is a FilesApi (a source given as files rather than a path or URL). */\nexport function isFilesApi(v: unknown): v is FilesApi {\n return (\n typeof v === \"object\" &&\n v !== null &&\n !(v instanceof URL) &&\n typeof (v as FilesApi).read === \"function\" &&\n typeof (v as FilesApi).list === \"function\" &&\n typeof (v as FilesApi).stats === \"function\"\n );\n}\n\n/** A built project's configuration as `wrangler.json` holds it: `main` and assets renamed. */\nexport function builtConfig(config: WranglerConfig): WranglerConfig {\n const out: WranglerConfig = { ...config };\n if (config.main) out.main = BUILT_WORKER;\n if (config.assets) out.assets = { ...config.assets, directory: BUILT_ASSETS };\n return out;\n}\n\nfunction concat(chunks: Uint8Array[]): Uint8Array {\n if (chunks.length === 1) return chunks[0];\n const out = new Uint8Array(chunks.reduce((n, c) => n + c.length, 0));\n let at = 0;\n for (const c of chunks) {\n out.set(c, at);\n at += c.length;\n }\n return out;\n}\n"]}
@@ -10,3 +10,12 @@ export declare class WorkflowEntrypoint<Env = unknown> {
10
10
  constructor(ctx: unknown, env: Env);
11
11
  }
12
12
  export { RpcTarget } from "../core/durable-object.js";
13
+ /** Where an isolate's runtime installs what `abortIsolate` does there (src/isolate/isolate.ts). */
14
+ export declare const ABORT_ISOLATE: unique symbol;
15
+ /**
16
+ * workerd's `abortIsolate(reason)`: ends the isolate the calling code runs in, and never returns.
17
+ * In a loaded Worker's isolate, the host terminates it: calls in flight reject, and the next
18
+ * `get()` of its id loads the code again. Elsewhere (a project's own realm, a loaded Worker in
19
+ * the project's realm) there is no isolate of its own to end, so the call only throws.
20
+ */
21
+ export declare function abortIsolate(reason?: unknown): never;
@@ -13,4 +13,18 @@ export class WorkflowEntrypoint {
13
13
  }
14
14
  }
15
15
  export { RpcTarget } from "../core/durable-object.js";
16
+ /** Where an isolate's runtime installs what `abortIsolate` does there (src/isolate/isolate.ts). */
17
+ export const ABORT_ISOLATE = Symbol.for("cellb.abort-isolate");
18
+ /**
19
+ * workerd's `abortIsolate(reason)`: ends the isolate the calling code runs in, and never returns.
20
+ * In a loaded Worker's isolate, the host terminates it: calls in flight reject, and the next
21
+ * `get()` of its id loads the code again. Elsewhere (a project's own realm, a loaded Worker in
22
+ * the project's realm) there is no isolate of its own to end, so the call only throws.
23
+ */
24
+ export function abortIsolate(reason) {
25
+ const abort = globalThis[ABORT_ISOLATE];
26
+ if (abort)
27
+ return abort(reason);
28
+ throw new Error(`abortIsolate(${String(reason ?? "")}): this code runs in no isolate of its own (cellb runs only loaded Workers in isolates)`);
29
+ }
16
30
  //# sourceMappingURL=cloudflare-workers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cloudflare-workers.js","sourceRoot":"","sources":["../../src/project/cloudflare-workers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE5E,2FAA2F;AAC3F,MAAM,OAAO,kBAAkB;IACnB,GAAG,CAAU;IACb,GAAG,CAAM;IACnB,YAAY,GAAY,EAAE,GAAQ;QAChC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;CACF;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC","sourcesContent":["/**\n * The `cloudflare:workers` module for Worker code run by cellb (mapped by the\n * bundler / webrun-modules). Exposes the classes Workers code imports.\n */\nexport { DurableObject, WorkerEntrypoint } from \"../core/durable-object.js\";\n\n/** Base class of Workflows (`class X extends WorkflowEntrypoint { run(event, step) }`). */\nexport class WorkflowEntrypoint<Env = unknown> {\n protected ctx: unknown;\n protected env: Env;\n constructor(ctx: unknown, env: Env) {\n this.ctx = ctx;\n this.env = env;\n }\n}\n\nexport { RpcTarget } from \"../core/durable-object.js\";\n"]}
1
+ {"version":3,"file":"cloudflare-workers.js","sourceRoot":"","sources":["../../src/project/cloudflare-workers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE5E,2FAA2F;AAC3F,MAAM,OAAO,kBAAkB;IACnB,GAAG,CAAU;IACb,GAAG,CAAM;IACnB,YAAY,GAAY,EAAE,GAAQ;QAChC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;CACF;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEtD,mGAAmG;AACnG,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,MAAgB;IAC3C,MAAM,KAAK,GAAI,UAAkE,CAAC,aAAa,CAAC,CAAC;IACjG,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC;IAChC,MAAM,IAAI,KAAK,CACb,gBAAgB,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,yFAAyF,CAC9H,CAAC;AACJ,CAAC","sourcesContent":["/**\n * The `cloudflare:workers` module for Worker code run by cellb (mapped by the\n * bundler / webrun-modules). Exposes the classes Workers code imports.\n */\nexport { DurableObject, WorkerEntrypoint } from \"../core/durable-object.js\";\n\n/** Base class of Workflows (`class X extends WorkflowEntrypoint { run(event, step) }`). */\nexport class WorkflowEntrypoint<Env = unknown> {\n protected ctx: unknown;\n protected env: Env;\n constructor(ctx: unknown, env: Env) {\n this.ctx = ctx;\n this.env = env;\n }\n}\n\nexport { RpcTarget } from \"../core/durable-object.js\";\n\n/** Where an isolate's runtime installs what `abortIsolate` does there (src/isolate/isolate.ts). */\nexport const ABORT_ISOLATE = Symbol.for(\"cellb.abort-isolate\");\n\n/**\n * workerd's `abortIsolate(reason)`: ends the isolate the calling code runs in, and never returns.\n * In a loaded Worker's isolate, the host terminates it: calls in flight reject, and the next\n * `get()` of its id loads the code again. Elsewhere (a project's own realm, a loaded Worker in\n * the project's realm) there is no isolate of its own to end, so the call only throws.\n */\nexport function abortIsolate(reason?: unknown): never {\n const abort = (globalThis as Record<symbol, ((r: unknown) => never) | undefined>)[ABORT_ISOLATE];\n if (abort) return abort(reason);\n throw new Error(\n `abortIsolate(${String(reason ?? \"\")}): this code runs in no isolate of its own (cellb runs only loaded Workers in isolates)`,\n );\n}\n"]}