@statewalker/cellb 0.7.0 → 0.8.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 (44) hide show
  1. package/README.md +2 -1
  2. package/dist/bindings/html-rewriter.d.ts +7 -0
  3. package/dist/bindings/html-rewriter.js +4 -11
  4. package/dist/bindings/html-rewriter.js.map +1 -1
  5. package/dist/index.d.ts +1 -1
  6. package/dist/index.js +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/project/browser-bundle.d.ts +3 -0
  9. package/dist/project/browser-bundle.js +2 -0
  10. package/dist/project/browser-bundle.js.map +1 -1
  11. package/dist/project/browser-host.js +2 -1
  12. package/dist/project/browser-host.js.map +1 -1
  13. package/dist/project/browser-modules.js +14 -4
  14. package/dist/project/browser-modules.js.map +1 -1
  15. package/dist/project/browser-shards.d.ts +2 -23
  16. package/dist/project/browser-shards.js +2 -8
  17. package/dist/project/browser-shards.js.map +1 -1
  18. package/dist/project/browser-tab-protocol.d.ts +30 -0
  19. package/dist/project/browser-tab-protocol.js +9 -0
  20. package/dist/project/browser-tab-protocol.js.map +1 -0
  21. package/dist/project/browser-tabs.js +1 -1
  22. package/dist/project/browser-tabs.js.map +1 -1
  23. package/dist/project/build.js +1 -0
  24. package/dist/project/build.js.map +1 -1
  25. package/dist/project/lower-await.js +22 -2
  26. package/dist/project/lower-await.js.map +1 -1
  27. package/dist/project/module-rules.d.ts +26 -0
  28. package/dist/project/module-rules.js +131 -0
  29. package/dist/project/module-rules.js.map +1 -0
  30. package/dist/project/module-specifiers.d.ts +14 -0
  31. package/dist/project/module-specifiers.js +302 -0
  32. package/dist/project/module-specifiers.js.map +1 -0
  33. package/dist/project/node-load.js +2 -1
  34. package/dist/project/node-load.js.map +1 -1
  35. package/dist/project/node-project.d.ts +3 -0
  36. package/dist/project/node-project.js +5 -1
  37. package/dist/project/node-project.js.map +1 -1
  38. package/dist/project/wrangler.d.ts +27 -3
  39. package/dist/project/wrangler.js +45 -22
  40. package/dist/project/wrangler.js.map +1 -1
  41. package/dist/tabs.d.ts +1 -0
  42. package/dist/tabs.js +8 -0
  43. package/dist/tabs.js.map +1 -0
  44. package/package.json +5 -1
@@ -0,0 +1,131 @@
1
+ /**
2
+ * wrangler's module `rules` for the esbuild bundles of a project's `main` (Node and `cellb build`):
3
+ * `CompiledWasm` (default export a `WebAssembly.Module`), `Data` (an `ArrayBuffer`) and `Text` (a
4
+ * string), matched on the import specifier by `globs`, as wrangler bundles. The bytes are inlined
5
+ * as base64 (about 1.33 times their size), so a bundle stays one self-contained module (a browser
6
+ * loads it by URL).
7
+ */
8
+ import { readFileSync } from "node:fs";
9
+ /** wrangler's (and workerd's) defaults, applied after a project's own rules. */
10
+ export const DEFAULT_MODULE_RULES = [
11
+ { type: "Text", globs: ["**/*.txt", "**/*.html", "**/*.sql"] },
12
+ { type: "Data", globs: ["**/*.bin"] },
13
+ { type: "CompiledWasm", globs: ["**/*.wasm", "**/*.wasm?module"] },
14
+ ];
15
+ /** The rule types the bundles apply; ESModule and CommonJS are esbuild's own business. */
16
+ const TYPES = new Set(["CompiledWasm", "Data", "Text"]);
17
+ /**
18
+ * A glob as an esbuild filter (Go regexp) on the import specifier, as wrangler matches it
19
+ * (glob-to-regexp with globstar): `**` spans any folders, `*` stays within one, the rest is literal.
20
+ */
21
+ export function globFilter(glob) {
22
+ let re = "";
23
+ for (let i = 0; i < glob.length; i++) {
24
+ const c = glob[i];
25
+ if (glob.startsWith("**/", i)) {
26
+ re += "(?:[^/]*/)*";
27
+ i += 2;
28
+ }
29
+ else if (glob.startsWith("**", i)) {
30
+ re += ".*";
31
+ i++;
32
+ }
33
+ else if (c === "*")
34
+ re += "[^/]*";
35
+ else
36
+ re += c.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
37
+ }
38
+ return new RegExp(`^${re}$`);
39
+ }
40
+ /**
41
+ * The rules in effect, as wrangler's `parseRules`: the project's, then the defaults. The first rule
42
+ * of a type without `fallthrough: true` closes the type: later rules of it are dropped (`ignored`
43
+ * names the project's own, unless the closing rule says `fallthrough: false`).
44
+ */
45
+ export function effectiveRules(userRules = []) {
46
+ const all = [...userRules, ...DEFAULT_MODULE_RULES];
47
+ const closedAt = new Map();
48
+ const rules = [];
49
+ const ignored = [];
50
+ for (const [i, rule] of all.entries()) {
51
+ const at = closedAt.get(rule.type);
52
+ if (at !== undefined) {
53
+ if (i < userRules.length && all[at].fallthrough !== false)
54
+ ignored.push(`rules[${i}] (${rule.type}) is ignored: rules[${at}] has the same type and no \`fallthrough = true\``);
55
+ continue;
56
+ }
57
+ if (rule.fallthrough !== true)
58
+ closedAt.set(rule.type, i);
59
+ rules.push(rule);
60
+ }
61
+ return { rules, ignored };
62
+ }
63
+ // Shared by every inlined file: base64 → bytes (Uint8Array.fromBase64 where the engine has it).
64
+ const DECODE = `export const bytes = (s) => {
65
+ if (typeof Uint8Array.fromBase64 === "function") return Uint8Array.fromBase64(s);
66
+ const t = atob(s);
67
+ const u = new Uint8Array(t.length);
68
+ for (let i = 0; i < t.length; i++) u[i] = t.charCodeAt(i);
69
+ return u;
70
+ };`;
71
+ /** The module a matched file becomes. */
72
+ function ruleModule(type, file) {
73
+ // A BOM stays part of the text, as wrangler uploads the file's bytes.
74
+ if (type === "Text")
75
+ return `export default ${JSON.stringify(new TextDecoder("utf-8", { ignoreBOM: true }).decode(file))};`;
76
+ const b64 = JSON.stringify(file.toString("base64"));
77
+ return [
78
+ 'import { bytes } from "cellb-rule:decode";',
79
+ type === "CompiledWasm"
80
+ ? // asynchronous: no engine limit on the size of a synchronous compile (Chromium's main thread)
81
+ `export default await WebAssembly.compile(bytes(${b64}));`
82
+ : `export default bytes(${b64}).buffer;`,
83
+ ].join("\n");
84
+ }
85
+ /** The esbuild plugin applying `rules` (with the defaults) to a bundle's imports. */
86
+ export function moduleRulesPlugin(userRules) {
87
+ return {
88
+ name: "cellb-module-rules",
89
+ setup(b) {
90
+ const { rules, ignored } = effectiveRules(userRules);
91
+ for (const message of ignored)
92
+ console.warn(`[cellb] ${message}`);
93
+ for (const rule of rules) {
94
+ if (!TYPES.has(rule.type))
95
+ continue;
96
+ for (const glob of rule.globs)
97
+ b.onResolve({ filter: globFilter(glob) }, async (a) => {
98
+ // files on disk only: in-memory modules (Worker Loader code) bring `{ wasm }` entries
99
+ if (a.namespace !== "file" || a.pluginData?.cellbModuleRule)
100
+ return undefined;
101
+ // esbuild resolves the file (relative, or a package's through `exports`); the rule loads it
102
+ const r = await b.resolve(a.path.replace(/\?module$/, ""), {
103
+ kind: a.kind,
104
+ importer: a.importer,
105
+ resolveDir: a.resolveDir,
106
+ pluginData: { cellbModuleRule: true },
107
+ });
108
+ if (r.errors.length)
109
+ return { errors: r.errors };
110
+ // The type is part of the module's identity: one file reached by rules of two types
111
+ // is two modules.
112
+ return { path: r.path, namespace: `cellb-rule-${rule.type}` };
113
+ });
114
+ }
115
+ b.onResolve({ filter: /^cellb-rule:decode$/ }, () => ({
116
+ path: "decode",
117
+ namespace: "cellb-rule-decode",
118
+ }));
119
+ b.onLoad({ filter: /.*/, namespace: "cellb-rule-decode" }, () => ({
120
+ contents: DECODE,
121
+ loader: "js",
122
+ }));
123
+ for (const type of TYPES)
124
+ b.onLoad({ filter: /.*/, namespace: `cellb-rule-${type}` }, (a) => ({
125
+ contents: ruleModule(type, readFileSync(a.path)),
126
+ loader: "js",
127
+ }));
128
+ },
129
+ };
130
+ }
131
+ //# sourceMappingURL=module-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-rules.js","sourceRoot":"","sources":["../../src/project/module-rules.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * wrangler's module `rules` for the esbuild bundles of a project's `main` (Node and `cellb build`):\n * `CompiledWasm` (default export a `WebAssembly.Module`), `Data` (an `ArrayBuffer`) and `Text` (a\n * string), matched on the import specifier by `globs`, as wrangler bundles. The bytes are inlined\n * as base64 (about 1.33 times their size), so a bundle stays one self-contained module (a browser\n * loads it by URL).\n */\nimport { readFileSync } from \"node:fs\";\nimport type { Plugin } from \"esbuild\";\n\n/** A wrangler `rules` entry. */\nexport interface ModuleRule {\n type: \"ESModule\" | \"CommonJS\" | \"CompiledWasm\" | \"Data\" | \"Text\" | (string & {});\n globs: string[];\n /** `true`: later rules of the same type (the defaults among them) apply too. */\n fallthrough?: boolean;\n}\n\n/** wrangler's (and workerd's) defaults, applied after a project's own rules. */\nexport const DEFAULT_MODULE_RULES: ModuleRule[] = [\n { type: \"Text\", globs: [\"**/*.txt\", \"**/*.html\", \"**/*.sql\"] },\n { type: \"Data\", globs: [\"**/*.bin\"] },\n { type: \"CompiledWasm\", globs: [\"**/*.wasm\", \"**/*.wasm?module\"] },\n];\n\n/** The rule types the bundles apply; ESModule and CommonJS are esbuild's own business. */\nconst TYPES = new Set([\"CompiledWasm\", \"Data\", \"Text\"]);\n\n/**\n * A glob as an esbuild filter (Go regexp) on the import specifier, as wrangler matches it\n * (glob-to-regexp with globstar): `**` spans any folders, `*` stays within one, the rest is literal.\n */\nexport function globFilter(glob: string): RegExp {\n let re = \"\";\n for (let i = 0; i < glob.length; i++) {\n const c = glob[i];\n if (glob.startsWith(\"**/\", i)) {\n re += \"(?:[^/]*/)*\";\n i += 2;\n } else if (glob.startsWith(\"**\", i)) {\n re += \".*\";\n i++;\n } else if (c === \"*\") re += \"[^/]*\";\n else re += c.replace(/[.+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n }\n return new RegExp(`^${re}$`);\n}\n\n/**\n * The rules in effect, as wrangler's `parseRules`: the project's, then the defaults. The first rule\n * of a type without `fallthrough: true` closes the type: later rules of it are dropped (`ignored`\n * names the project's own, unless the closing rule says `fallthrough: false`).\n */\nexport function effectiveRules(userRules: ModuleRule[] = []): {\n rules: ModuleRule[];\n ignored: string[];\n} {\n const all = [...userRules, ...DEFAULT_MODULE_RULES];\n const closedAt = new Map<string, number>();\n const rules: ModuleRule[] = [];\n const ignored: string[] = [];\n for (const [i, rule] of all.entries()) {\n const at = closedAt.get(rule.type);\n if (at !== undefined) {\n if (i < userRules.length && all[at].fallthrough !== false)\n ignored.push(\n `rules[${i}] (${rule.type}) is ignored: rules[${at}] has the same type and no \\`fallthrough = true\\``,\n );\n continue;\n }\n if (rule.fallthrough !== true) closedAt.set(rule.type, i);\n rules.push(rule);\n }\n return { rules, ignored };\n}\n\n// Shared by every inlined file: base64 → bytes (Uint8Array.fromBase64 where the engine has it).\nconst DECODE = `export const bytes = (s) => {\n if (typeof Uint8Array.fromBase64 === \"function\") return Uint8Array.fromBase64(s);\n const t = atob(s);\n const u = new Uint8Array(t.length);\n for (let i = 0; i < t.length; i++) u[i] = t.charCodeAt(i);\n return u;\n};`;\n\n/** The module a matched file becomes. */\nfunction ruleModule(type: string, file: Buffer): string {\n // A BOM stays part of the text, as wrangler uploads the file's bytes.\n if (type === \"Text\")\n return `export default ${JSON.stringify(new TextDecoder(\"utf-8\", { ignoreBOM: true }).decode(file))};`;\n const b64 = JSON.stringify(file.toString(\"base64\"));\n return [\n 'import { bytes } from \"cellb-rule:decode\";',\n type === \"CompiledWasm\"\n ? // asynchronous: no engine limit on the size of a synchronous compile (Chromium's main thread)\n `export default await WebAssembly.compile(bytes(${b64}));`\n : `export default bytes(${b64}).buffer;`,\n ].join(\"\\n\");\n}\n\n/** The esbuild plugin applying `rules` (with the defaults) to a bundle's imports. */\nexport function moduleRulesPlugin(userRules?: ModuleRule[]): Plugin {\n return {\n name: \"cellb-module-rules\",\n setup(b) {\n const { rules, ignored } = effectiveRules(userRules);\n for (const message of ignored) console.warn(`[cellb] ${message}`);\n for (const rule of rules) {\n if (!TYPES.has(rule.type)) continue;\n for (const glob of rule.globs)\n b.onResolve({ filter: globFilter(glob) }, async (a) => {\n // files on disk only: in-memory modules (Worker Loader code) bring `{ wasm }` entries\n if (a.namespace !== \"file\" || a.pluginData?.cellbModuleRule) return undefined;\n // esbuild resolves the file (relative, or a package's through `exports`); the rule loads it\n const r = await b.resolve(a.path.replace(/\\?module$/, \"\"), {\n kind: a.kind,\n importer: a.importer,\n resolveDir: a.resolveDir,\n pluginData: { cellbModuleRule: true },\n });\n if (r.errors.length) return { errors: r.errors };\n // The type is part of the module's identity: one file reached by rules of two types\n // is two modules.\n return { path: r.path, namespace: `cellb-rule-${rule.type}` };\n });\n }\n b.onResolve({ filter: /^cellb-rule:decode$/ }, () => ({\n path: \"decode\",\n namespace: \"cellb-rule-decode\",\n }));\n b.onLoad({ filter: /.*/, namespace: \"cellb-rule-decode\" }, () => ({\n contents: DECODE,\n loader: \"js\",\n }));\n for (const type of TYPES)\n b.onLoad({ filter: /.*/, namespace: `cellb-rule-${type}` }, (a) => ({\n contents: ruleModule(type, readFileSync(a.path)),\n loader: \"js\",\n }));\n },\n };\n}\n"]}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Rewrites the module specifiers of an ES module's own imports: `import … from "x"`,
3
+ * `import "x"`, `export … from "x"` and `import("x")`, and only those. The text is scanned as
4
+ * code, so the same words inside a string, a template literal's text, a comment or a regular
5
+ * expression are left alone (a regex over the whole text would rewrite them, e.g. a code
6
+ * generator's template that contains `from "cloudflare:workers"`).
7
+ *
8
+ * A small scanner rather than a parser: the browser module loader runs in every isolate and
9
+ * shard worker, where a full JS parser would add its whole size.
10
+ *
11
+ * `resolve(spec)` returns the replacement specifier, or undefined to keep it. A dynamic import
12
+ * is rewritten only when its argument is one literal (a string, or a template without `${`).
13
+ */
14
+ export declare function rewriteModuleSpecifiers(code: string, resolve: (spec: string) => string | undefined): string;
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Rewrites the module specifiers of an ES module's own imports: `import … from "x"`,
3
+ * `import "x"`, `export … from "x"` and `import("x")`, and only those. The text is scanned as
4
+ * code, so the same words inside a string, a template literal's text, a comment or a regular
5
+ * expression are left alone (a regex over the whole text would rewrite them, e.g. a code
6
+ * generator's template that contains `from "cloudflare:workers"`).
7
+ *
8
+ * A small scanner rather than a parser: the browser module loader runs in every isolate and
9
+ * shard worker, where a full JS parser would add its whole size.
10
+ *
11
+ * `resolve(spec)` returns the replacement specifier, or undefined to keep it. A dynamic import
12
+ * is rewritten only when its argument is one literal (a string, or a template without `${`).
13
+ */
14
+ export function rewriteModuleSpecifiers(code, resolve) {
15
+ const edits = [];
16
+ const n = code.length;
17
+ // The last significant token, to tell a regular expression from a division: a punctuator
18
+ // (`(`, `=`, …), "id" (an identifier or a keyword not in REGEX_AFTER_WORD), "num", "str",
19
+ // "re", "++"/"--", or ")" / "]" / "}" (a division follows, unless the `)` closed the head of
20
+ // `if`/`while`/`for`/`with`, which a statement, and so a regex, may follow).
21
+ let prev = "";
22
+ let prevWord = ""; // the identifier `prev` stands for, when it is "id"
23
+ // Template literals being scanned: for each `${`, the brace depth it opened at.
24
+ const templates = [];
25
+ let depth = 0;
26
+ // For each open `(`: whether it is the head of if/while/for/with.
27
+ const parens = [];
28
+ const WORD_START = new Uint8Array(128);
29
+ const WORD = new Uint8Array(128);
30
+ for (let c = 0; c < 128; c++) {
31
+ const ch = String.fromCharCode(c);
32
+ WORD_START[c] = /[A-Za-z_$]/.test(ch) ? 1 : 0;
33
+ WORD[c] = /[A-Za-z0-9_$]/.test(ch) ? 1 : 0;
34
+ }
35
+ const isIdStart = (c) => (c < 128 ? WORD_START[c] === 1 : c > 0xa0 || c === 0x5c);
36
+ const isId = (c) => (c < 128 ? WORD[c] === 1 : c > 0xa0 || c === 0x5c);
37
+ const isSpace = (c) => c === 32 || (c >= 9 && c <= 13) || c === 0xa0 || c === 0xfeff || c === 0x2028 || c === 0x2029;
38
+ const REGEX_AFTER_WORD = new Set([
39
+ "return",
40
+ "typeof",
41
+ "instanceof",
42
+ "in",
43
+ "of",
44
+ "new",
45
+ "delete",
46
+ "void",
47
+ "throw",
48
+ "case",
49
+ "do",
50
+ "else",
51
+ "yield",
52
+ "await",
53
+ "default",
54
+ "extends",
55
+ ]);
56
+ const HEADS = new Set(["if", "while", "for", "with"]);
57
+ const regexAllowed = () => {
58
+ if (prev === "id")
59
+ return REGEX_AFTER_WORD.has(prevWord);
60
+ if (prev === "" || prev === "head)")
61
+ return true;
62
+ return /^[(,=:[!&|?{};+\-*%<>~^]$/.test(prev);
63
+ };
64
+ const skipSpace = (from) => {
65
+ let j = from;
66
+ for (;;) {
67
+ while (j < n && isSpace(code.charCodeAt(j)))
68
+ j++;
69
+ if (code.startsWith("//", j)) {
70
+ while (j < n && code[j] !== "\n" && code[j] !== "\r")
71
+ j++;
72
+ }
73
+ else if (code.startsWith("/*", j)) {
74
+ const end = code.indexOf("*/", j + 2);
75
+ j = end < 0 ? n : end + 2;
76
+ }
77
+ else
78
+ return j;
79
+ }
80
+ };
81
+ /** The end (exclusive) of the quoted string starting at `from`. */
82
+ const stringEnd = (from) => {
83
+ const q = code[from];
84
+ let j = from + 1;
85
+ while (j < n && code[j] !== q) {
86
+ if (code[j] === "\\") {
87
+ j++;
88
+ if (code[j] === "\r" && code[j + 1] === "\n")
89
+ j++; // a CRLF line continuation
90
+ }
91
+ else if (code[j] === "\n" || code[j] === "\r")
92
+ break;
93
+ j++;
94
+ }
95
+ return j + 1;
96
+ };
97
+ /** The string's value, decoding the simple escapes; undefined for anything else. */
98
+ const decode = (raw) => {
99
+ let out = "";
100
+ for (let j = 0; j < raw.length; j++) {
101
+ const c = raw[j];
102
+ if (c !== "\\") {
103
+ out += c;
104
+ continue;
105
+ }
106
+ const e = raw[++j];
107
+ const hex = (len) => {
108
+ const h = raw.slice(j + 1, j + 1 + len);
109
+ if (!new RegExp(`^[0-9a-fA-F]{${len}}$`).test(h))
110
+ return undefined;
111
+ j += len;
112
+ return String.fromCharCode(Number.parseInt(h, 16));
113
+ };
114
+ const d = e === "x"
115
+ ? hex(2)
116
+ : e === "u"
117
+ ? hex(4)
118
+ : e === "'" || e === '"' || e === "\\" || e === "/"
119
+ ? e
120
+ : undefined;
121
+ if (d === undefined)
122
+ return undefined;
123
+ out += d;
124
+ }
125
+ return out;
126
+ };
127
+ /** A string literal (or, for import(), a template without `${`) at `from`, after spaces. */
128
+ const literalAt = (from, template) => {
129
+ const j = skipSpace(from);
130
+ const q = code[j];
131
+ if (q === '"' || q === "'")
132
+ return { start: j, end: stringEnd(j) };
133
+ if (template && q === "`") {
134
+ const end = code.indexOf("`", j + 1);
135
+ if (end < 0)
136
+ return undefined;
137
+ const raw = code.slice(j + 1, end);
138
+ if (raw.includes("${") || raw.includes("\\"))
139
+ return undefined;
140
+ return { start: j, end: end + 1 };
141
+ }
142
+ return undefined;
143
+ };
144
+ const take = (s) => {
145
+ if (!s)
146
+ return;
147
+ const spec = decode(code.slice(s.start + 1, s.end - 1));
148
+ if (spec === undefined)
149
+ return;
150
+ const to = resolve(spec);
151
+ if (to !== undefined)
152
+ edits.push({ start: s.start, end: s.end, text: JSON.stringify(to) });
153
+ };
154
+ /** Scans template text from `from` (just after a backtick, or a `}` closing `${…}`). */
155
+ const templateText = (from) => {
156
+ let j = from;
157
+ while (j < n) {
158
+ const c = code[j];
159
+ if (c === "\\")
160
+ j += 2;
161
+ else if (c === "`")
162
+ return j + 1;
163
+ else if (c === "$" && code[j + 1] === "{") {
164
+ templates.push(depth);
165
+ depth++;
166
+ return j + 2;
167
+ }
168
+ else
169
+ j++;
170
+ }
171
+ return n;
172
+ };
173
+ let i = 0;
174
+ if (code.startsWith("#!"))
175
+ while (i < n && code[i] !== "\n")
176
+ i++; // a hashbang line
177
+ while (i < n) {
178
+ const cc = code.charCodeAt(i);
179
+ const c = code[i];
180
+ if (isSpace(cc)) {
181
+ i++;
182
+ continue;
183
+ }
184
+ if (c === "/" && (code[i + 1] === "/" || code[i + 1] === "*")) {
185
+ i = skipSpace(i);
186
+ continue;
187
+ }
188
+ if (c === '"' || c === "'") {
189
+ i = stringEnd(i);
190
+ prev = "str";
191
+ continue;
192
+ }
193
+ if (c === "`") {
194
+ i = templateText(i + 1);
195
+ prev = "str";
196
+ continue;
197
+ }
198
+ if (c === "/" && regexAllowed()) {
199
+ let j = i + 1;
200
+ let inClass = false;
201
+ let closed = false;
202
+ while (j < n && code[j] !== "\n" && code[j] !== "\r") {
203
+ const d = code[j];
204
+ if (d === "\\")
205
+ j++;
206
+ else if (d === "[")
207
+ inClass = true;
208
+ else if (d === "]")
209
+ inClass = false;
210
+ else if (d === "/" && !inClass) {
211
+ closed = true;
212
+ break;
213
+ }
214
+ j++;
215
+ }
216
+ if (closed) {
217
+ j++;
218
+ while (j < n && isId(code.charCodeAt(j)))
219
+ j++; // flags
220
+ }
221
+ i = j;
222
+ prev = "re";
223
+ continue;
224
+ }
225
+ if (isIdStart(cc)) {
226
+ let j = i + 1;
227
+ while (j < n && isId(code.charCodeAt(j)))
228
+ j++;
229
+ const word = code.slice(i, j);
230
+ const member = prev === "." || prev === "?.";
231
+ if (!member && word === "from" && (prev === "}" || prev === "*" || prev === "id"))
232
+ take(literalAt(j, false));
233
+ else if (!member && word === "import") {
234
+ const k = skipSpace(j);
235
+ if (code[k] === "(") {
236
+ // import(x): only a whole literal argument (not "./a/" + b).
237
+ const s = literalAt(k + 1, true);
238
+ const after = s && code[skipSpace(s.end)];
239
+ if (after === ")" || after === ",")
240
+ take(s);
241
+ }
242
+ else
243
+ take(literalAt(j, false)); // a side-effect import of a bare string
244
+ }
245
+ i = j;
246
+ prev = "id";
247
+ prevWord = word;
248
+ continue;
249
+ }
250
+ if (cc >= 48 && cc <= 57) {
251
+ let j = i + 1;
252
+ while (j < n && (isId(code.charCodeAt(j)) || code[j] === "."))
253
+ j++;
254
+ i = j;
255
+ prev = "num";
256
+ continue;
257
+ }
258
+ if ((c === "+" || c === "-") && code[i + 1] === c) {
259
+ // `a++ / b` divides; `x = ++a` has the operator before an operand, which then sets prev.
260
+ prev = c + c;
261
+ i += 2;
262
+ continue;
263
+ }
264
+ if (c === "?" && code[i + 1] === "." && !/[0-9]/.test(code[i + 2] ?? "")) {
265
+ prev = "?.";
266
+ i += 2;
267
+ continue;
268
+ }
269
+ if (c === "(") {
270
+ parens.push(prev === "id" && HEADS.has(prevWord));
271
+ prev = "(";
272
+ i++;
273
+ continue;
274
+ }
275
+ if (c === ")") {
276
+ prev = parens.pop() ? "head)" : ")";
277
+ i++;
278
+ continue;
279
+ }
280
+ if (c === "{")
281
+ depth++;
282
+ else if (c === "}") {
283
+ depth--;
284
+ if (templates.length && templates[templates.length - 1] === depth) {
285
+ templates.pop();
286
+ i = templateText(i + 1);
287
+ prev = "str";
288
+ continue;
289
+ }
290
+ }
291
+ prev = c;
292
+ i++;
293
+ }
294
+ let out = "";
295
+ let at = 0;
296
+ for (const e of edits) {
297
+ out += code.slice(at, e.start) + e.text;
298
+ at = e.end;
299
+ }
300
+ return out + code.slice(at);
301
+ }
302
+ //# sourceMappingURL=module-specifiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-specifiers.js","sourceRoot":"","sources":["../../src/project/module-specifiers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Rewrites the module specifiers of an ES module's own imports: `import … from \"x\"`,\n * `import \"x\"`, `export … from \"x\"` and `import(\"x\")`, and only those. The text is scanned as\n * code, so the same words inside a string, a template literal's text, a comment or a regular\n * expression are left alone (a regex over the whole text would rewrite them, e.g. a code\n * generator's template that contains `from \"cloudflare:workers\"`).\n *\n * A small scanner rather than a parser: the browser module loader runs in every isolate and\n * shard worker, where a full JS parser would add its whole size.\n *\n * `resolve(spec)` returns the replacement specifier, or undefined to keep it. A dynamic import\n * is rewritten only when its argument is one literal (a string, or a template without `${`).\n */\nexport function rewriteModuleSpecifiers(\n code: string,\n resolve: (spec: string) => string | undefined,\n): string {\n const edits: { start: number; end: number; text: string }[] = [];\n const n = code.length;\n // The last significant token, to tell a regular expression from a division: a punctuator\n // (`(`, `=`, …), \"id\" (an identifier or a keyword not in REGEX_AFTER_WORD), \"num\", \"str\",\n // \"re\", \"++\"/\"--\", or \")\" / \"]\" / \"}\" (a division follows, unless the `)` closed the head of\n // `if`/`while`/`for`/`with`, which a statement, and so a regex, may follow).\n let prev = \"\";\n let prevWord = \"\"; // the identifier `prev` stands for, when it is \"id\"\n // Template literals being scanned: for each `${`, the brace depth it opened at.\n const templates: number[] = [];\n let depth = 0;\n // For each open `(`: whether it is the head of if/while/for/with.\n const parens: boolean[] = [];\n\n const WORD_START = new Uint8Array(128);\n const WORD = new Uint8Array(128);\n for (let c = 0; c < 128; c++) {\n const ch = String.fromCharCode(c);\n WORD_START[c] = /[A-Za-z_$]/.test(ch) ? 1 : 0;\n WORD[c] = /[A-Za-z0-9_$]/.test(ch) ? 1 : 0;\n }\n const isIdStart = (c: number) => (c < 128 ? WORD_START[c] === 1 : c > 0xa0 || c === 0x5c);\n const isId = (c: number) => (c < 128 ? WORD[c] === 1 : c > 0xa0 || c === 0x5c);\n const isSpace = (c: number) =>\n c === 32 || (c >= 9 && c <= 13) || c === 0xa0 || c === 0xfeff || c === 0x2028 || c === 0x2029;\n\n const REGEX_AFTER_WORD = new Set([\n \"return\",\n \"typeof\",\n \"instanceof\",\n \"in\",\n \"of\",\n \"new\",\n \"delete\",\n \"void\",\n \"throw\",\n \"case\",\n \"do\",\n \"else\",\n \"yield\",\n \"await\",\n \"default\",\n \"extends\",\n ]);\n const HEADS = new Set([\"if\", \"while\", \"for\", \"with\"]);\n const regexAllowed = () => {\n if (prev === \"id\") return REGEX_AFTER_WORD.has(prevWord);\n if (prev === \"\" || prev === \"head)\") return true;\n return /^[(,=:[!&|?{};+\\-*%<>~^]$/.test(prev);\n };\n\n const skipSpace = (from: number): number => {\n let j = from;\n for (;;) {\n while (j < n && isSpace(code.charCodeAt(j))) j++;\n if (code.startsWith(\"//\", j)) {\n while (j < n && code[j] !== \"\\n\" && code[j] !== \"\\r\") j++;\n } else if (code.startsWith(\"/*\", j)) {\n const end = code.indexOf(\"*/\", j + 2);\n j = end < 0 ? n : end + 2;\n } else return j;\n }\n };\n /** The end (exclusive) of the quoted string starting at `from`. */\n const stringEnd = (from: number): number => {\n const q = code[from];\n let j = from + 1;\n while (j < n && code[j] !== q) {\n if (code[j] === \"\\\\\") {\n j++;\n if (code[j] === \"\\r\" && code[j + 1] === \"\\n\") j++; // a CRLF line continuation\n } else if (code[j] === \"\\n\" || code[j] === \"\\r\") break;\n j++;\n }\n return j + 1;\n };\n /** The string's value, decoding the simple escapes; undefined for anything else. */\n const decode = (raw: string): string | undefined => {\n let out = \"\";\n for (let j = 0; j < raw.length; j++) {\n const c = raw[j] as string;\n if (c !== \"\\\\\") {\n out += c;\n continue;\n }\n const e = raw[++j];\n const hex = (len: number) => {\n const h = raw.slice(j + 1, j + 1 + len);\n if (!new RegExp(`^[0-9a-fA-F]{${len}}$`).test(h)) return undefined;\n j += len;\n return String.fromCharCode(Number.parseInt(h, 16));\n };\n const d =\n e === \"x\"\n ? hex(2)\n : e === \"u\"\n ? hex(4)\n : e === \"'\" || e === '\"' || e === \"\\\\\" || e === \"/\"\n ? e\n : undefined;\n if (d === undefined) return undefined;\n out += d;\n }\n return out;\n };\n /** A string literal (or, for import(), a template without `${`) at `from`, after spaces. */\n const literalAt = (from: number, template: boolean) => {\n const j = skipSpace(from);\n const q = code[j];\n if (q === '\"' || q === \"'\") return { start: j, end: stringEnd(j) };\n if (template && q === \"`\") {\n const end = code.indexOf(\"`\", j + 1);\n if (end < 0) return undefined;\n const raw = code.slice(j + 1, end);\n if (raw.includes(\"${\") || raw.includes(\"\\\\\")) return undefined;\n return { start: j, end: end + 1 };\n }\n return undefined;\n };\n const take = (s: { start: number; end: number } | undefined) => {\n if (!s) return;\n const spec = decode(code.slice(s.start + 1, s.end - 1));\n if (spec === undefined) return;\n const to = resolve(spec);\n if (to !== undefined) edits.push({ start: s.start, end: s.end, text: JSON.stringify(to) });\n };\n /** Scans template text from `from` (just after a backtick, or a `}` closing `${…}`). */\n const templateText = (from: number): number => {\n let j = from;\n while (j < n) {\n const c = code[j];\n if (c === \"\\\\\") j += 2;\n else if (c === \"`\") return j + 1;\n else if (c === \"$\" && code[j + 1] === \"{\") {\n templates.push(depth);\n depth++;\n return j + 2;\n } else j++;\n }\n return n;\n };\n\n let i = 0;\n if (code.startsWith(\"#!\")) while (i < n && code[i] !== \"\\n\") i++; // a hashbang line\n while (i < n) {\n const cc = code.charCodeAt(i);\n const c = code[i] as string;\n if (isSpace(cc)) {\n i++;\n continue;\n }\n if (c === \"/\" && (code[i + 1] === \"/\" || code[i + 1] === \"*\")) {\n i = skipSpace(i);\n continue;\n }\n if (c === '\"' || c === \"'\") {\n i = stringEnd(i);\n prev = \"str\";\n continue;\n }\n if (c === \"`\") {\n i = templateText(i + 1);\n prev = \"str\";\n continue;\n }\n if (c === \"/\" && regexAllowed()) {\n let j = i + 1;\n let inClass = false;\n let closed = false;\n while (j < n && code[j] !== \"\\n\" && code[j] !== \"\\r\") {\n const d = code[j];\n if (d === \"\\\\\") j++;\n else if (d === \"[\") inClass = true;\n else if (d === \"]\") inClass = false;\n else if (d === \"/\" && !inClass) {\n closed = true;\n break;\n }\n j++;\n }\n if (closed) {\n j++;\n while (j < n && isId(code.charCodeAt(j))) j++; // flags\n }\n i = j;\n prev = \"re\";\n continue;\n }\n if (isIdStart(cc)) {\n let j = i + 1;\n while (j < n && isId(code.charCodeAt(j))) j++;\n const word = code.slice(i, j);\n const member = prev === \".\" || prev === \"?.\";\n if (!member && word === \"from\" && (prev === \"}\" || prev === \"*\" || prev === \"id\"))\n take(literalAt(j, false));\n else if (!member && word === \"import\") {\n const k = skipSpace(j);\n if (code[k] === \"(\") {\n // import(x): only a whole literal argument (not \"./a/\" + b).\n const s = literalAt(k + 1, true);\n const after = s && code[skipSpace(s.end)];\n if (after === \")\" || after === \",\") take(s);\n } else take(literalAt(j, false)); // a side-effect import of a bare string\n }\n i = j;\n prev = \"id\";\n prevWord = word;\n continue;\n }\n if (cc >= 48 && cc <= 57) {\n let j = i + 1;\n while (j < n && (isId(code.charCodeAt(j)) || code[j] === \".\")) j++;\n i = j;\n prev = \"num\";\n continue;\n }\n if ((c === \"+\" || c === \"-\") && code[i + 1] === c) {\n // `a++ / b` divides; `x = ++a` has the operator before an operand, which then sets prev.\n prev = c + c;\n i += 2;\n continue;\n }\n if (c === \"?\" && code[i + 1] === \".\" && !/[0-9]/.test(code[i + 2] ?? \"\")) {\n prev = \"?.\";\n i += 2;\n continue;\n }\n if (c === \"(\") {\n parens.push(prev === \"id\" && HEADS.has(prevWord));\n prev = \"(\";\n i++;\n continue;\n }\n if (c === \")\") {\n prev = parens.pop() ? \"head)\" : \")\";\n i++;\n continue;\n }\n if (c === \"{\") depth++;\n else if (c === \"}\") {\n depth--;\n if (templates.length && templates[templates.length - 1] === depth) {\n templates.pop();\n i = templateText(i + 1);\n prev = \"str\";\n continue;\n }\n }\n prev = c;\n i++;\n }\n\n let out = \"\";\n let at = 0;\n for (const e of edits) {\n out += code.slice(at, e.start) + e.text;\n at = e.end;\n }\n return out + code.slice(at);\n}\n"]}
@@ -14,7 +14,7 @@ import * as workersClasses from "./cloudflare-workers.js";
14
14
  import { loadNodeProject, nodeIsolatedLoader, nodeModuleLoader } from "./node-project.js";
15
15
  import { workerScope } from "./worker-scope.js";
16
16
  import * as workersGlobals from "./workers-globals-module.js";
17
- import { createProjectRuntime, loadTimeEnv, populatesProcessEnv, processEnvOf, } from "./wrangler.js";
17
+ import { createProjectRuntime, loadProjectBindings, loadTimeEnv, populatesProcessEnv, processEnvOf, } from "./wrangler.js";
18
18
  /**
19
19
  * Loads a project and runs it in this process.
20
20
  *
@@ -133,6 +133,7 @@ async function runBuilt(built, host) {
133
133
  }
134
134
  }
135
135
  const project = createProjectRuntime(config, module, {
136
+ bindings: await loadProjectBindings(config),
136
137
  loadModules: nodeModuleLoader,
137
138
  isolatedModules: nodeIsolatedLoader(() => host.storage),
138
139
  assetFiles: built.assets,
@@ -1 +1 @@
1
- {"version":3,"file":"node-load.js","sourceRoot":"","sources":["../../src/project/node-load.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `loadProject` on Node (`@statewalker/cellb/node`): one call that reads a project, built or\n * not, and runs it.\n */\nimport { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport type { FilesApi } from \"@statewalker/webrun-files\";\nimport { MemFilesApi } from \"@statewalker/webrun-files-mem\";\nimport { NodeFilesApi } from \"@statewalker/webrun-files-node\";\nimport { nodeSqliteOpener } from \"../adapters/node-sqlite.js\";\nimport type { WorkerModule } from \"../core/runtime.js\";\nimport type { CellStorage } from \"../ports.js\";\nimport {\n BUILD_MANIFEST,\n BUILT_WORKER,\n type BuiltProject,\n filesApiReader,\n isFilesApi,\n type LoadedProject,\n type LoadProjectOptions,\n type ProjectReader,\n type ProjectSource,\n readBuildManifest,\n readBuiltProject,\n urlReader,\n} from \"./built-project.js\";\nimport * as workersClasses from \"./cloudflare-workers.js\";\nimport { loadNodeProject, nodeIsolatedLoader, nodeModuleLoader } from \"./node-project.js\";\nimport { workerScope } from \"./worker-scope.js\";\nimport * as workersGlobals from \"./workers-globals-module.js\";\nimport {\n createProjectRuntime,\n loadTimeEnv,\n type ProjectHost,\n populatesProcessEnv,\n processEnvOf,\n} from \"./wrangler.js\";\n\nexport type NodeLoadProjectOptions = LoadProjectOptions<CellStorage>;\n\n/**\n * Loads a project and runs it in this process.\n *\n * `source`: a folder with `wrangler.json(c)` (its `main` bundled with esbuild, as\n * `loadNodeProject` does), a folder written by `cellb build` (its `worker.js` imported as built),\n * an `http(s):` URL of a built folder, or a FilesApi holding either kind of folder.\n *\n * `options.data`: a directory for the cells' SQLite files and the project's files\n * (`<data>/files`); without it, both are in memory.\n */\nexport async function loadProject(\n source: ProjectSource,\n options: NodeLoadProjectOptions = {},\n): Promise<LoadedProject> {\n const host = nodeHost(options);\n const close = async (runtime: { close(): Promise<void> }, cleanup?: () => void) => {\n await runtime.close();\n cleanup?.();\n };\n // A folder on disk: read where it lies.\n const dir = localDir(source);\n if (dir !== undefined) {\n const reader = fsReader(dir);\n const manifest = await readBuildManifest(reader);\n if (manifest) return runBuilt(await readBuiltProject(reader, manifest), host);\n const { runtime, unsupported, config } = await loadNodeProject(dir, host);\n return {\n config,\n runtime,\n unsupported,\n fetch: (req) => runtime.fetch(req),\n close: () => close(runtime),\n };\n }\n // A FilesApi: a built folder is read from it; a source folder is copied out for esbuild.\n if (isFilesApi(source)) {\n const reader = filesApiReader(source);\n const manifest = await readBuildManifest(reader);\n if (manifest) return runBuilt(await readBuiltProject(reader, manifest), host);\n const tmp = await copyOut(source);\n try {\n const { runtime, unsupported, config } = await loadNodeProject(tmp, host);\n return {\n config,\n runtime,\n unsupported,\n fetch: (req) => runtime.fetch(req),\n close: () => close(runtime, () => rmSync(tmp, { recursive: true, force: true })),\n };\n } catch (err) {\n rmSync(tmp, { recursive: true, force: true });\n throw err;\n }\n }\n // A URL of a built folder.\n const url = folderUrl(source);\n const reader = urlReader(url);\n const manifest = await readBuildManifest(reader);\n if (!manifest)\n throw new Error(`${url} has no ${BUILD_MANIFEST}: load a folder written by \\`cellb build\\``);\n return runBuilt(await readBuiltProject(reader, manifest), host);\n}\n\n/** What `options` become on Node: SQLite files and a FilesApi under `data`, or memory. */\nfunction nodeHost(options: NodeLoadProjectOptions): Omit<ProjectHost, \"loadModules\"> {\n let files: FilesApi;\n if (options.data) {\n const data = resolve(options.data);\n mkdirSync(join(data, \"files\"), { recursive: true });\n files = new NodeFilesApi({ rootDir: join(data, \"files\") });\n } else files = new MemFilesApi();\n return {\n openSql: nodeSqliteOpener(options.data ? resolve(options.data) : undefined),\n files,\n storage: options.bucket,\n ai: options.ai,\n };\n}\n\n/**\n * Runs a built project on Node: `worker.js` was bundled for a browser realm, so it reads the\n * Workers globals and `cloudflare:workers` from the globals this sets, as in a browser worker.\n * (One such project per process: the globals are the process's.)\n */\nasync function runBuilt(\n built: BuiltProject,\n host: Omit<ProjectHost, \"loadModules\">,\n): Promise<LoadedProject> {\n const { config } = built;\n const flags = config.compatibility_flags ?? [];\n const scope = workerScope(loadTimeEnv(config, host.ai));\n const g = globalThis as Record<string, unknown>;\n g.__cellsWorkersModule = workersClasses;\n g.__cellsProjectScope = scope;\n g.__cellsGlobals = {\n ...workersGlobals,\n Request: workersGlobals.CellsRequest,\n Response: workersGlobals.CellsResponse,\n WebSocketPair: flags.includes(\"websocket_standard_binary_type\")\n ? workersGlobals.StandardWebSocketPair\n : workersGlobals.WebSocketPair,\n };\n if (populatesProcessEnv(config)) {\n const env = processEnvOf(config);\n g.__cellsProcessEnv = env;\n for (const [k, v] of Object.entries(env)) process.env[k] ??= v;\n }\n let module: WorkerModule = { default: {} } as WorkerModule;\n if (built.code !== null) {\n const tmp = mkdtempSync(join(tmpdir(), \"cellb-built-\"));\n const file = join(tmp, BUILT_WORKER.replace(/\\.js$/, \".mjs\"));\n writeFileSync(file, built.code);\n try {\n module = (await import(/* @vite-ignore */ pathToFileURL(file).href)) as WorkerModule;\n } finally {\n rmSync(tmp, { recursive: true, force: true });\n }\n }\n const project = createProjectRuntime(config, module, {\n loadModules: nodeModuleLoader,\n isolatedModules: nodeIsolatedLoader(() => host.storage),\n assetFiles: built.assets,\n ...host,\n });\n scope.bind(project.runtime);\n const { runtime, unsupported } = project;\n return {\n config,\n runtime,\n unsupported,\n fetch: (req) => runtime.fetch(req),\n close: () => runtime.close(),\n };\n}\n\n/** The folder a source names on this machine: a path or a `file:` URL. */\nfunction localDir(source: ProjectSource): string | undefined {\n if (typeof source === \"string\") {\n if (/^https?:\\/\\//i.test(source)) return undefined;\n return resolve(source.startsWith(\"file:\") ? fileURLToPath(source) : source);\n }\n if (source instanceof URL && source.protocol === \"file:\") return fileURLToPath(source);\n return undefined;\n}\n\nfunction folderUrl(source: ProjectSource): URL {\n const url = new URL(String(source));\n if (!url.pathname.endsWith(\"/\")) url.pathname += \"/\";\n return url;\n}\n\nfunction fsReader(dir: string): ProjectReader {\n return {\n async bytes(path) {\n const full = join(dir, path);\n return existsSync(full) ? new Uint8Array(readFileSync(full)) : undefined;\n },\n };\n}\n\n/** Copies a FilesApi's files into a temporary folder (esbuild bundles from disk). */\nasync function copyOut(files: FilesApi): Promise<string> {\n const tmp = mkdtempSync(join(tmpdir(), \"cellb-project-\"));\n const reader = filesApiReader(files);\n for (const path of (await reader.list?.(\"/\")) ?? []) {\n const out = join(tmp, path);\n mkdirSync(dirname(out), { recursive: true });\n writeFileSync(out, (await reader.bytes(path)) as Uint8Array);\n }\n return tmp;\n}\n"]}
1
+ {"version":3,"file":"node-load.js","sourceRoot":"","sources":["../../src/project/node-load.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClG,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAG9D,OAAO,EACL,cAAc,EACd,YAAY,EAEZ,cAAc,EACd,UAAU,EAKV,iBAAiB,EACjB,gBAAgB,EAChB,SAAS,GACV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1F,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,cAAc,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,WAAW,EAEX,mBAAmB,EACnB,YAAY,GACb,MAAM,eAAe,CAAC;AAIvB;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAqB,EACrB,OAAO,GAA2B,EAAE;IAEpC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,EAAE,OAAmC,EAAE,OAAoB,EAAE,EAAE;QAChF,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,EAAE,EAAE,CAAC;IACd,CAAC,CAAC;IACF,wCAAwC;IACxC,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACjD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC,MAAM,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9E,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1E,OAAO;YACL,MAAM;YACN,OAAO;YACP,WAAW;YACX,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;YAClC,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;SAC5B,CAAC;IACJ,CAAC;IACD,yFAAyF;IACzF,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACjD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC,MAAM,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9E,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC1E,OAAO;gBACL,MAAM;gBACN,OAAO;gBACP,WAAW;gBACX,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;gBAClC,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;aACjF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IACD,2BAA2B;IAC3B,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACjD,IAAI,CAAC,QAAQ;QACX,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,WAAW,cAAc,4CAA4C,CAAC,CAAC;IAC/F,OAAO,QAAQ,CAAC,MAAM,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;AAClE,CAAC;AAED,0FAA0F;AAC1F,SAAS,QAAQ,CAAC,OAA+B;IAC/C,IAAI,KAAe,CAAC;IACpB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,KAAK,GAAG,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7D,CAAC;;QAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;IACjC,OAAO;QACL,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3E,KAAK;QACL,OAAO,EAAE,OAAO,CAAC,MAAM;QACvB,EAAE,EAAE,OAAO,CAAC,EAAE;KACf,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,QAAQ,CACrB,KAAmB,EACnB,IAAsC;IAEtC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IACzB,MAAM,KAAK,GAAG,MAAM,CAAC,mBAAmB,IAAI,EAAE,CAAC;IAC/C,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACxD,MAAM,CAAC,GAAG,UAAqC,CAAC;IAChD,CAAC,CAAC,oBAAoB,GAAG,cAAc,CAAC;IACxC,CAAC,CAAC,mBAAmB,GAAG,KAAK,CAAC;IAC9B,CAAC,CAAC,cAAc,GAAG;QACjB,GAAG,cAAc;QACjB,OAAO,EAAE,cAAc,CAAC,YAAY;QACpC,QAAQ,EAAE,cAAc,CAAC,aAAa;QACtC,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,gCAAgC,CAAC;YAC7D,CAAC,CAAC,cAAc,CAAC,qBAAqB;YACtC,CAAC,CAAC,cAAc,CAAC,aAAa;KACjC,CAAC;IACF,IAAI,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC,CAAC,iBAAiB,GAAG,GAAG,CAAC;QAC1B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,MAAM,GAAiB,EAAE,OAAO,EAAE,EAAE,EAAkB,CAAC;IAC3D,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QAC9D,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,kBAAkB,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAiB,CAAC;QACvF,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE;QACnD,QAAQ,EAAE,MAAM,mBAAmB,CAAC,MAAM,CAAC;QAC3C,WAAW,EAAE,gBAAgB;QAC7B,eAAe,EAAE,kBAAkB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;QACvD,UAAU,EAAE,KAAK,CAAC,MAAM;QACxB,GAAG,IAAI;KACR,CAAC,CAAC;IACH,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5B,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IACzC,OAAO;QACL,MAAM;QACN,OAAO;QACP,WAAW;QACX,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;QAClC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE;KAC7B,CAAC;AACJ,CAAC;AAED,0EAA0E;AAC1E,SAAS,QAAQ,CAAC,MAAqB;IACrC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,IAAI,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,OAAO,SAAS,CAAC;QACnD,OAAO,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;IACvF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,SAAS,CAAC,MAAqB;IACtC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACpC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC;IACrD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW;IAC3B,OAAO;QACL,KAAK,CAAC,KAAK,CAAC,IAAI;YACd,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC7B,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3E,CAAC;KACF,CAAC;AACJ,CAAC;AAED,qFAAqF;AACrF,KAAK,UAAU,OAAO,CAAC,KAAe;IACpC,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC5B,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,aAAa,CAAC,GAAG,EAAE,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAe,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["/**\n * `loadProject` on Node (`@statewalker/cellb/node`): one call that reads a project, built or\n * not, and runs it.\n */\nimport { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport type { FilesApi } from \"@statewalker/webrun-files\";\nimport { MemFilesApi } from \"@statewalker/webrun-files-mem\";\nimport { NodeFilesApi } from \"@statewalker/webrun-files-node\";\nimport { nodeSqliteOpener } from \"../adapters/node-sqlite.js\";\nimport type { WorkerModule } from \"../core/runtime.js\";\nimport type { CellStorage } from \"../ports.js\";\nimport {\n BUILD_MANIFEST,\n BUILT_WORKER,\n type BuiltProject,\n filesApiReader,\n isFilesApi,\n type LoadedProject,\n type LoadProjectOptions,\n type ProjectReader,\n type ProjectSource,\n readBuildManifest,\n readBuiltProject,\n urlReader,\n} from \"./built-project.js\";\nimport * as workersClasses from \"./cloudflare-workers.js\";\nimport { loadNodeProject, nodeIsolatedLoader, nodeModuleLoader } from \"./node-project.js\";\nimport { workerScope } from \"./worker-scope.js\";\nimport * as workersGlobals from \"./workers-globals-module.js\";\nimport {\n createProjectRuntime,\n loadProjectBindings,\n loadTimeEnv,\n type ProjectHost,\n populatesProcessEnv,\n processEnvOf,\n} from \"./wrangler.js\";\n\nexport type NodeLoadProjectOptions = LoadProjectOptions<CellStorage>;\n\n/**\n * Loads a project and runs it in this process.\n *\n * `source`: a folder with `wrangler.json(c)` (its `main` bundled with esbuild, as\n * `loadNodeProject` does), a folder written by `cellb build` (its `worker.js` imported as built),\n * an `http(s):` URL of a built folder, or a FilesApi holding either kind of folder.\n *\n * `options.data`: a directory for the cells' SQLite files and the project's files\n * (`<data>/files`); without it, both are in memory.\n */\nexport async function loadProject(\n source: ProjectSource,\n options: NodeLoadProjectOptions = {},\n): Promise<LoadedProject> {\n const host = nodeHost(options);\n const close = async (runtime: { close(): Promise<void> }, cleanup?: () => void) => {\n await runtime.close();\n cleanup?.();\n };\n // A folder on disk: read where it lies.\n const dir = localDir(source);\n if (dir !== undefined) {\n const reader = fsReader(dir);\n const manifest = await readBuildManifest(reader);\n if (manifest) return runBuilt(await readBuiltProject(reader, manifest), host);\n const { runtime, unsupported, config } = await loadNodeProject(dir, host);\n return {\n config,\n runtime,\n unsupported,\n fetch: (req) => runtime.fetch(req),\n close: () => close(runtime),\n };\n }\n // A FilesApi: a built folder is read from it; a source folder is copied out for esbuild.\n if (isFilesApi(source)) {\n const reader = filesApiReader(source);\n const manifest = await readBuildManifest(reader);\n if (manifest) return runBuilt(await readBuiltProject(reader, manifest), host);\n const tmp = await copyOut(source);\n try {\n const { runtime, unsupported, config } = await loadNodeProject(tmp, host);\n return {\n config,\n runtime,\n unsupported,\n fetch: (req) => runtime.fetch(req),\n close: () => close(runtime, () => rmSync(tmp, { recursive: true, force: true })),\n };\n } catch (err) {\n rmSync(tmp, { recursive: true, force: true });\n throw err;\n }\n }\n // A URL of a built folder.\n const url = folderUrl(source);\n const reader = urlReader(url);\n const manifest = await readBuildManifest(reader);\n if (!manifest)\n throw new Error(`${url} has no ${BUILD_MANIFEST}: load a folder written by \\`cellb build\\``);\n return runBuilt(await readBuiltProject(reader, manifest), host);\n}\n\n/** What `options` become on Node: SQLite files and a FilesApi under `data`, or memory. */\nfunction nodeHost(options: NodeLoadProjectOptions): Omit<ProjectHost, \"loadModules\"> {\n let files: FilesApi;\n if (options.data) {\n const data = resolve(options.data);\n mkdirSync(join(data, \"files\"), { recursive: true });\n files = new NodeFilesApi({ rootDir: join(data, \"files\") });\n } else files = new MemFilesApi();\n return {\n openSql: nodeSqliteOpener(options.data ? resolve(options.data) : undefined),\n files,\n storage: options.bucket,\n ai: options.ai,\n };\n}\n\n/**\n * Runs a built project on Node: `worker.js` was bundled for a browser realm, so it reads the\n * Workers globals and `cloudflare:workers` from the globals this sets, as in a browser worker.\n * (One such project per process: the globals are the process's.)\n */\nasync function runBuilt(\n built: BuiltProject,\n host: Omit<ProjectHost, \"loadModules\">,\n): Promise<LoadedProject> {\n const { config } = built;\n const flags = config.compatibility_flags ?? [];\n const scope = workerScope(loadTimeEnv(config, host.ai));\n const g = globalThis as Record<string, unknown>;\n g.__cellsWorkersModule = workersClasses;\n g.__cellsProjectScope = scope;\n g.__cellsGlobals = {\n ...workersGlobals,\n Request: workersGlobals.CellsRequest,\n Response: workersGlobals.CellsResponse,\n WebSocketPair: flags.includes(\"websocket_standard_binary_type\")\n ? workersGlobals.StandardWebSocketPair\n : workersGlobals.WebSocketPair,\n };\n if (populatesProcessEnv(config)) {\n const env = processEnvOf(config);\n g.__cellsProcessEnv = env;\n for (const [k, v] of Object.entries(env)) process.env[k] ??= v;\n }\n let module: WorkerModule = { default: {} } as WorkerModule;\n if (built.code !== null) {\n const tmp = mkdtempSync(join(tmpdir(), \"cellb-built-\"));\n const file = join(tmp, BUILT_WORKER.replace(/\\.js$/, \".mjs\"));\n writeFileSync(file, built.code);\n try {\n module = (await import(/* @vite-ignore */ pathToFileURL(file).href)) as WorkerModule;\n } finally {\n rmSync(tmp, { recursive: true, force: true });\n }\n }\n const project = createProjectRuntime(config, module, {\n bindings: await loadProjectBindings(config),\n loadModules: nodeModuleLoader,\n isolatedModules: nodeIsolatedLoader(() => host.storage),\n assetFiles: built.assets,\n ...host,\n });\n scope.bind(project.runtime);\n const { runtime, unsupported } = project;\n return {\n config,\n runtime,\n unsupported,\n fetch: (req) => runtime.fetch(req),\n close: () => runtime.close(),\n };\n}\n\n/** The folder a source names on this machine: a path or a `file:` URL. */\nfunction localDir(source: ProjectSource): string | undefined {\n if (typeof source === \"string\") {\n if (/^https?:\\/\\//i.test(source)) return undefined;\n return resolve(source.startsWith(\"file:\") ? fileURLToPath(source) : source);\n }\n if (source instanceof URL && source.protocol === \"file:\") return fileURLToPath(source);\n return undefined;\n}\n\nfunction folderUrl(source: ProjectSource): URL {\n const url = new URL(String(source));\n if (!url.pathname.endsWith(\"/\")) url.pathname += \"/\";\n return url;\n}\n\nfunction fsReader(dir: string): ProjectReader {\n return {\n async bytes(path) {\n const full = join(dir, path);\n return existsSync(full) ? new Uint8Array(readFileSync(full)) : undefined;\n },\n };\n}\n\n/** Copies a FilesApi's files into a temporary folder (esbuild bundles from disk). */\nasync function copyOut(files: FilesApi): Promise<string> {\n const tmp = mkdtempSync(join(tmpdir(), \"cellb-project-\"));\n const reader = filesApiReader(files);\n for (const path of (await reader.list?.(\"/\")) ?? []) {\n const out = join(tmp, path);\n mkdirSync(dirname(out), { recursive: true });\n writeFileSync(out, (await reader.bytes(path)) as Uint8Array);\n }\n return tmp;\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import { type LogSink, type ModuleLoader } from "../bindings/worker-loader.js";
2
2
  import type { WorkerModule } from "../core/runtime.js";
3
3
  import type { CellStorage } from "../ports.js";
4
+ import { type ModuleRule } from "./module-rules.js";
4
5
  import { type WorkerScope } from "./worker-scope.js";
5
6
  import { type ProjectHost, type ProjectRuntime, type WranglerConfig } from "./wrangler.js";
6
7
  /** Reads `wrangler.jsonc` / `wrangler.json` of a project directory (celld reads the same files). */
@@ -20,6 +21,8 @@ export declare function bundleWorker(entry: {
20
21
  nodeCompat?: boolean;
21
22
  standardBinaryType?: boolean;
22
23
  scope?: WorkerScope;
24
+ /** wrangler `rules` for non-JS imports (the defaults: `.wasm`, `.bin`, `.txt`…, as wrangler). */
25
+ rules?: ModuleRule[];
23
26
  }): Promise<WorkerModule>;
24
27
  /** Worker Loader on Node: compiles `WorkerCode.modules` with esbuild (as celld compiles loaded code). */
25
28
  export declare const nodeModuleLoader: ModuleLoader;