@nimbus-sh/worker 0.10.0 → 0.11.0

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 (260) hide show
  1. package/NOTICE.md +5 -0
  2. package/README.md +10 -0
  3. package/dist/_shared/session-router.d.ts +7 -0
  4. package/dist/_shared/session-router.d.ts.map +1 -1
  5. package/dist/_shared/session-router.js +7 -0
  6. package/dist/bindings/body.d.ts +6 -0
  7. package/dist/bindings/body.d.ts.map +1 -0
  8. package/dist/bindings/body.js +37 -0
  9. package/dist/bindings/kv.d.ts +0 -2
  10. package/dist/bindings/kv.d.ts.map +1 -1
  11. package/dist/bindings/kv.js +3 -42
  12. package/dist/bindings/r2.d.ts +0 -2
  13. package/dist/bindings/r2.d.ts.map +1 -1
  14. package/dist/bindings/r2.js +4 -44
  15. package/dist/esbuild-cli-artifact.generated.d.ts +18 -0
  16. package/dist/esbuild-cli-artifact.generated.d.ts.map +1 -0
  17. package/dist/esbuild-cli-artifact.generated.js +17 -0
  18. package/dist/facets/cirrus-real.d.ts.map +1 -1
  19. package/dist/facets/cirrus-real.js +9 -4
  20. package/dist/facets/compose.d.ts +11 -7
  21. package/dist/facets/compose.d.ts.map +1 -1
  22. package/dist/facets/compose.js +8 -38
  23. package/dist/facets/data-plan.d.ts +79 -0
  24. package/dist/facets/data-plan.d.ts.map +1 -0
  25. package/dist/facets/data-plan.js +477 -0
  26. package/dist/facets/esbuild-transform.d.ts +36 -10
  27. package/dist/facets/esbuild-transform.d.ts.map +1 -1
  28. package/dist/facets/esbuild-transform.js +216 -20
  29. package/dist/facets/exec-telemetry.d.ts +7 -3
  30. package/dist/facets/exec-telemetry.d.ts.map +1 -1
  31. package/dist/facets/manager.d.ts +179 -78
  32. package/dist/facets/manager.d.ts.map +1 -1
  33. package/dist/facets/manager.js +1221 -649
  34. package/dist/facets/opencode-staging.d.ts +0 -2
  35. package/dist/facets/opencode-staging.d.ts.map +1 -1
  36. package/dist/facets/opencode-staging.js +5 -11
  37. package/dist/facets/process.d.ts +4 -0
  38. package/dist/facets/process.d.ts.map +1 -1
  39. package/dist/facets/process.js +3 -0
  40. package/dist/facets/read-profile.d.ts +149 -0
  41. package/dist/facets/read-profile.d.ts.map +1 -0
  42. package/dist/facets/read-profile.js +483 -0
  43. package/dist/facets/resident-identity.d.ts +0 -1
  44. package/dist/facets/resident-identity.d.ts.map +1 -1
  45. package/dist/facets/resident-identity.js +0 -3
  46. package/dist/facets/wasm-swap-registry.d.ts +34 -25
  47. package/dist/facets/wasm-swap-registry.d.ts.map +1 -1
  48. package/dist/facets/wasm-swap-registry.js +62 -56
  49. package/dist/facets/ws-terminal.d.ts +4 -4
  50. package/dist/facets/ws-terminal.d.ts.map +1 -1
  51. package/dist/facets/ws-terminal.js +4 -5
  52. package/dist/git/commands.d.ts +16 -9
  53. package/dist/git/commands.d.ts.map +1 -1
  54. package/dist/git/commands.js +1818 -188
  55. package/dist/git/network-facet.d.ts +10 -2
  56. package/dist/git/network-facet.d.ts.map +1 -1
  57. package/dist/git/network-facet.js +62 -16
  58. package/dist/git/unified-diff.d.ts +74 -0
  59. package/dist/git/unified-diff.d.ts.map +1 -0
  60. package/dist/git/unified-diff.js +676 -0
  61. package/dist/git-bundle.generated.d.ts +7 -11
  62. package/dist/git-bundle.generated.d.ts.map +1 -1
  63. package/dist/git-bundle.generated.js +7 -11
  64. package/dist/hosted/commands.d.ts.map +1 -1
  65. package/dist/hosted/commands.js +62 -243
  66. package/dist/hosted/runtime.d.ts +19 -13
  67. package/dist/hosted/runtime.d.ts.map +1 -1
  68. package/dist/hosted/runtime.js +71 -14
  69. package/dist/hosted/services.d.ts +6 -7
  70. package/dist/hosted/services.d.ts.map +1 -1
  71. package/dist/hosted/services.js +10 -14
  72. package/dist/hosted/session.d.ts +165 -0
  73. package/dist/hosted/session.d.ts.map +1 -0
  74. package/dist/hosted/session.js +132 -0
  75. package/dist/loaders/generated-workers.d.ts +5 -2
  76. package/dist/loaders/generated-workers.d.ts.map +1 -1
  77. package/dist/loaders/generated-workers.js +6 -3
  78. package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -1
  79. package/dist/loaders/npm-resolve-preamble.js +0 -27
  80. package/dist/node-shims-artifact.generated.d.ts +13 -4
  81. package/dist/node-shims-artifact.generated.d.ts.map +1 -1
  82. package/dist/node-shims-artifact.generated.js +16 -7
  83. package/dist/npm/bin-links.d.ts +3 -1
  84. package/dist/npm/bin-links.d.ts.map +1 -1
  85. package/dist/npm/bin-links.js +32 -8
  86. package/dist/npm/cache.d.ts +5 -0
  87. package/dist/npm/cache.d.ts.map +1 -1
  88. package/dist/npm/cache.js +13 -1
  89. package/dist/npm/install-batch-facet.d.ts +2 -2
  90. package/dist/npm/install-batch-facet.js +3 -3
  91. package/dist/npm/installer.d.ts +17 -1
  92. package/dist/npm/installer.d.ts.map +1 -1
  93. package/dist/npm/installer.js +159 -20
  94. package/dist/npm/package-lock.d.ts +32 -0
  95. package/dist/npm/package-lock.d.ts.map +1 -0
  96. package/dist/npm/package-lock.js +65 -0
  97. package/dist/npm/pre-bundle-facet.d.ts +1 -30
  98. package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
  99. package/dist/npm/pre-bundle-facet.js +3 -5
  100. package/dist/npm/r2-cache.d.ts +2 -0
  101. package/dist/npm/r2-cache.d.ts.map +1 -1
  102. package/dist/npm/r2-cache.js +2 -0
  103. package/dist/npm/resolve-one-facet.d.ts.map +1 -1
  104. package/dist/npm/resolve-one-facet.js +14 -3
  105. package/dist/npm/resolver.d.ts +0 -7
  106. package/dist/npm/resolver.d.ts.map +1 -1
  107. package/dist/npm/resolver.js +0 -22
  108. package/dist/opencode-artifact.generated.js +2 -2
  109. package/dist/replica/routing.d.ts +2 -38
  110. package/dist/replica/routing.d.ts.map +1 -1
  111. package/dist/replica/routing.js +3 -55
  112. package/dist/router/index.d.ts.map +1 -1
  113. package/dist/router/index.js +15 -2
  114. package/dist/router/public-directory.d.ts +18 -0
  115. package/dist/router/public-directory.d.ts.map +1 -1
  116. package/dist/router/public-directory.js +1 -1
  117. package/dist/router/remote-api.d.ts +3 -1
  118. package/dist/router/remote-api.d.ts.map +1 -1
  119. package/dist/router/remote-api.js +42 -79
  120. package/dist/runtime/bash-repl.js +2 -2
  121. package/dist/runtime/bun-repl.d.ts.map +1 -1
  122. package/dist/runtime/bun-repl.js +2 -13
  123. package/dist/runtime/esbuild-wasm-bytes.d.ts +17 -5
  124. package/dist/runtime/esbuild-wasm-bytes.d.ts.map +1 -1
  125. package/dist/runtime/esbuild-wasm-bytes.js +43 -94
  126. package/dist/runtime/git-bundle-artifact.d.ts +17 -0
  127. package/dist/runtime/git-bundle-artifact.d.ts.map +1 -0
  128. package/dist/runtime/git-bundle-artifact.js +25 -0
  129. package/dist/runtime/node-repl.d.ts.map +1 -1
  130. package/dist/runtime/node-repl.js +2 -13
  131. package/dist/runtime/node-shims-artifact.d.ts +22 -23
  132. package/dist/runtime/node-shims-artifact.d.ts.map +1 -1
  133. package/dist/runtime/node-shims-artifact.js +48 -78
  134. package/dist/runtime/node-shims.d.ts.map +1 -1
  135. package/dist/runtime/node-shims.js +1567 -864
  136. package/dist/runtime/opencode-artifact.d.ts.map +1 -1
  137. package/dist/runtime/opencode-artifact.js +17 -53
  138. package/dist/runtime/opencode-facet-runner.d.ts +3 -6
  139. package/dist/runtime/opencode-facet-runner.d.ts.map +1 -1
  140. package/dist/runtime/opencode-facet-runner.js +45 -10
  141. package/dist/runtime/opentui-wasm-bytes.d.ts.map +1 -1
  142. package/dist/runtime/opentui-wasm-bytes.js +16 -49
  143. package/dist/runtime/package-manager.d.ts +0 -2
  144. package/dist/runtime/package-manager.d.ts.map +1 -1
  145. package/dist/runtime/package-manager.js +0 -3
  146. package/dist/runtime/python-repl.d.ts.map +1 -1
  147. package/dist/runtime/python-repl.js +2 -2
  148. package/dist/runtime/repl-session.d.ts +10 -0
  149. package/dist/runtime/repl-session.d.ts.map +1 -1
  150. package/dist/runtime/repl-session.js +7 -0
  151. package/dist/runtime/ruby-repl.d.ts.map +1 -1
  152. package/dist/runtime/ruby-repl.js +2 -2
  153. package/dist/runtime/ruby-resident.d.ts.map +1 -1
  154. package/dist/runtime/ruby-resident.js +36 -35
  155. package/dist/runtime/runtime-catalog.d.ts +10 -3
  156. package/dist/runtime/runtime-catalog.d.ts.map +1 -1
  157. package/dist/runtime/runtime-catalog.js +125 -15
  158. package/dist/runtime/sqlite-wasm-bytes.d.ts +4 -4
  159. package/dist/runtime/sqlite-wasm-bytes.d.ts.map +1 -1
  160. package/dist/runtime/sqlite-wasm-bytes.js +21 -57
  161. package/dist/runtime/staged-source.d.ts +67 -0
  162. package/dist/runtime/staged-source.d.ts.map +1 -0
  163. package/dist/runtime/staged-source.js +113 -0
  164. package/dist/runtime/wasi/preamble.d.ts.map +1 -1
  165. package/dist/runtime/wasi/preamble.js +0 -24
  166. package/dist/runtime-catalog.generated.js +1 -1
  167. package/dist/session/agent.d.ts +14 -2
  168. package/dist/session/agent.d.ts.map +1 -1
  169. package/dist/session/agent.js +57 -19
  170. package/dist/session/ai.d.ts +0 -11
  171. package/dist/session/ai.d.ts.map +1 -1
  172. package/dist/session/ai.js +0 -4
  173. package/dist/session/fs-watch.d.ts +0 -11
  174. package/dist/session/fs-watch.d.ts.map +1 -1
  175. package/dist/session/fs-watch.js +0 -21
  176. package/dist/session/hibernation.d.ts +34 -11
  177. package/dist/session/hibernation.d.ts.map +1 -1
  178. package/dist/session/hibernation.js +46 -29
  179. package/dist/session/init-phases.d.ts +1 -2
  180. package/dist/session/init-phases.d.ts.map +1 -1
  181. package/dist/session/init-phases.js +1 -2
  182. package/dist/session/init.d.ts.map +1 -1
  183. package/dist/session/init.js +7 -20
  184. package/dist/session/keys.d.ts +0 -3
  185. package/dist/session/keys.d.ts.map +1 -1
  186. package/dist/session/keys.js +0 -3
  187. package/dist/session/legacy-reset.d.ts +11 -0
  188. package/dist/session/legacy-reset.d.ts.map +1 -0
  189. package/dist/session/legacy-reset.js +16 -0
  190. package/dist/session/nimbus-session.d.ts +41 -15
  191. package/dist/session/nimbus-session.d.ts.map +1 -1
  192. package/dist/session/nimbus-session.js +64 -70
  193. package/dist/session/npm-install-port.d.ts.map +1 -1
  194. package/dist/session/npm-install-port.js +1 -0
  195. package/dist/session/programmatic.d.ts +13 -18
  196. package/dist/session/programmatic.d.ts.map +1 -1
  197. package/dist/session/programmatic.js +53 -39
  198. package/dist/session/replica-routes.d.ts +2 -3
  199. package/dist/session/replica-routes.d.ts.map +1 -1
  200. package/dist/session/replica-routes.js +3 -10
  201. package/dist/session/routes.d.ts.map +1 -1
  202. package/dist/session/routes.js +7 -10
  203. package/dist/session/rpc.d.ts +104 -20
  204. package/dist/session/rpc.d.ts.map +1 -1
  205. package/dist/session/rpc.js +184 -37
  206. package/dist/session/start-real-vite.js +2 -2
  207. package/dist/session/state-store.d.ts +1 -17
  208. package/dist/session/state-store.d.ts.map +1 -1
  209. package/dist/session/state-store.js +3 -53
  210. package/dist/session/supervisor-op.d.ts +7 -0
  211. package/dist/session/supervisor-op.d.ts.map +1 -1
  212. package/dist/session/supervisor-op.js +6 -1
  213. package/dist/session/supervisor-rpc.d.ts +104 -15
  214. package/dist/session/supervisor-rpc.d.ts.map +1 -1
  215. package/dist/session/supervisor-rpc.js +188 -71
  216. package/dist/session/vite-command.d.ts.map +1 -1
  217. package/dist/session/vite-command.js +17 -14
  218. package/dist/session/ws.d.ts.map +1 -1
  219. package/dist/session/ws.js +20 -8
  220. package/dist/shell/npm-bin-entrypoints.d.ts.map +1 -1
  221. package/dist/shell/npm-bin-entrypoints.js +30 -5
  222. package/dist/vfs/facet-resident-limits.d.ts +33 -0
  223. package/dist/vfs/facet-resident-limits.d.ts.map +1 -0
  224. package/dist/vfs/facet-resident-limits.js +33 -0
  225. package/dist/vfs/facet-resident-store.d.ts +2 -10
  226. package/dist/vfs/facet-resident-store.d.ts.map +1 -1
  227. package/dist/vfs/facet-resident-store.js +1594 -219
  228. package/dist/workspace-host.d.ts +2 -0
  229. package/dist/workspace-host.d.ts.map +1 -1
  230. package/dist/workspace-host.js +2 -0
  231. package/dist/wrangler/nimbus-wrangler.d.ts +0 -2
  232. package/dist/wrangler/nimbus-wrangler.d.ts.map +1 -1
  233. package/dist/wrangler/nimbus-wrangler.js +5 -22
  234. package/package.json +8 -7
  235. package/public/_assets/opencode/1.16.2/index-attach.js +2 -2
  236. package/public/_assets/runtime/esbuild-cli-c4fda380d52befc1.js +6892 -0
  237. package/public/_assets/runtime/git-de3e60c9f3ff006a.js +103 -0
  238. package/public/_assets/runtime/{node-shims-7b4dd7a76d95d21e.js → node-shims-06565b121555c194.js} +2089 -861
  239. package/public/_assets/runtime/resident-store-6ffb1939c53d982f.js +2264 -0
  240. package/public/_assets/runtime/vfs-write-ledger-e501e8fc793bc2c1.js +889 -0
  241. package/scripts/build-opencode-attach-entry.mjs +51 -1
  242. package/scripts/bundle-facet-workers.mjs +114 -3
  243. package/scripts/bundle-git.mjs +88 -27
  244. package/scripts/bundle-node-shims.mjs +72 -46
  245. package/scripts/bundle-runtime.mjs +18 -421
  246. package/scripts/cf-git-patch.mjs +137 -0
  247. package/scripts/patch-install-deps.mjs +49 -96
  248. package/scripts/runtime-specs.mjs +435 -0
  249. package/vendor/git-http.generated.d.ts +82 -0
  250. package/vendor/git-upstream.generated.d.ts +4378 -0
  251. package/vendor/git.LICENSE +7 -0
  252. package/vendor/git.generated.d.mts +21 -0
  253. package/vendor/git.generated.mjs +103 -0
  254. package/dist/replica/suspension.d.ts +0 -36
  255. package/dist/replica/suspension.d.ts.map +0 -1
  256. package/dist/replica/suspension.js +0 -49
  257. package/dist/runtime/static-server.d.ts +0 -3
  258. package/dist/runtime/static-server.d.ts.map +0 -1
  259. package/dist/runtime/static-server.js +0 -133
  260. package/scripts/clean-dist.mjs +0 -7
@@ -110,6 +110,56 @@ function stripEmbeddedModelsCatalog(pack) {
110
110
  return pack;
111
111
  }
112
112
 
113
+ const unicodeEscape = (code) => '\\u' + code.toString(16).padStart(4, '0');
114
+
115
+ /** One regex literal with every non-ASCII code unit written as `\uXXXX`; `\…` is an identity escape of `…`. */
116
+ function escapeRegexLiteral(literal) {
117
+ let out = '';
118
+ for (let i = 0; i < literal.length; i++) {
119
+ const code = literal.charCodeAt(i);
120
+ if (code === 0x5c && i + 1 < literal.length) {
121
+ const next = literal.charCodeAt(i + 1);
122
+ out += next > 0x7f ? unicodeEscape(next) : literal.slice(i, i + 2);
123
+ i++;
124
+ } else {
125
+ out += code > 0x7f ? unicodeEscape(code) : literal[i];
126
+ }
127
+ }
128
+ return out;
129
+ }
130
+
131
+ /**
132
+ * Make the attach entry pure ASCII. esbuild's default ASCII charset escapes
133
+ * every literal except regular expressions, so opencode's typographic-quote
134
+ * regexes (`/[‘’‚‛]/g`, `/…/g`) survive, and one character above U+00FF makes
135
+ * V8 hold the whole 14 MB source as a two-byte string: 29 MB in the session
136
+ * that assembles the facet's module map and again in the facet that runs it.
137
+ * Fails loud if non-ASCII remains anywhere else.
138
+ */
139
+ function asciiOnlyAttachEntry(src) {
140
+ const acorn = require('acorn');
141
+ const parts = [];
142
+ let last = 0;
143
+ for (const token of acorn.tokenizer(src, { ecmaVersion: 'latest', sourceType: 'module' })) {
144
+ if (token.type !== acorn.tokTypes.regexp) continue;
145
+ const literal = src.slice(token.start, token.end);
146
+ if (!/[^\x00-\x7f]/.test(literal)) continue;
147
+ parts.push(src.slice(last, token.start), escapeRegexLiteral(literal));
148
+ last = token.end;
149
+ }
150
+ parts.push(src.slice(last));
151
+ const out = parts.join('');
152
+ const residual = out.search(/[^\x00-\x7f]/);
153
+ if (residual >= 0) {
154
+ throw new Error(
155
+ '[build-opencode-attach-entry] non-ASCII outside a regex literal at offset ' +
156
+ `${residual} (${JSON.stringify(out.slice(Math.max(0, residual - 40), residual + 10))}) — ` +
157
+ 'escape it here, or the attach source is held as a two-byte string',
158
+ );
159
+ }
160
+ return out;
161
+ }
162
+
113
163
  /**
114
164
  * Build the attach entry text from in-memory sources.
115
165
  * @param entry index.js source text.
@@ -178,7 +228,7 @@ export async function buildOpencodeAttachEntryFromSources(entry, packInput) {
178
228
  },
179
229
  ],
180
230
  });
181
- const out = result.outputFiles[0].text;
231
+ const out = asciiOnlyAttachEntry(result.outputFiles[0].text);
182
232
  const residual = [...out.matchAll(/import\(\s*["'](?:\.\/)?(chunk-[a-z0-9]+\.js)["']\s*\)/g)];
183
233
  if (residual.length > 0) {
184
234
  throw new Error(
@@ -39,18 +39,26 @@
39
39
  * WASI_INSTANCE_BODY_SRC: string
40
40
  * @nimbus-sh/core src/runtime/bash-runner.generated.ts — exports
41
41
  * BASH_RUNNER_BODY_SRC: string
42
+ * public/_assets/runtime/esbuild-cli-<buildId>.js — the `esbuild` command's
43
+ * runner, which only the session's esbuild facet evaluates. Staged as an
44
+ * asset rather than a string in the Worker bundle, like the esbuild
45
+ * adapter and the node shims; src/esbuild-cli-artifact.generated.ts
46
+ * exports ESBUILD_CLI_ASSET_PATH, ESBUILD_CLI_BUILD_ID, ESBUILD_CLI_SHA256.
42
47
  *
43
48
  * Runs as a postinstall + predev + predeploy step via package.json.
44
49
  */
45
50
 
46
51
  import { build } from 'esbuild';
47
- import { writeFileSync, mkdirSync } from 'node:fs';
52
+ import { createHash } from 'node:crypto';
53
+ import { readFileSync, writeFileSync, mkdirSync, readdirSync, unlinkSync } from 'node:fs';
48
54
  import { dirname, join } from 'node:path';
49
55
  import { fileURLToPath, pathToFileURL } from 'node:url';
50
56
  // core's own parser dependency, reached through the workspace hoist; the
51
57
  // script runs under plain node at postinstall, so nothing here is TypeScript.
52
58
  import { parse } from 'acorn';
53
59
 
60
+ import { resolvePackageDir } from './resolve-package-dir.mjs';
61
+
54
62
  const __dirname = dirname(fileURLToPath(import.meta.url));
55
63
  const root = join(__dirname, '..');
56
64
  const coreRoot = join(root, '..', 'core');
@@ -298,6 +306,87 @@ async function bundleBashRunner() {
298
306
  return src;
299
307
  }
300
308
 
309
+ /**
310
+ * The `esbuild` command's runner: Go's own js/wasm glue from the installed
311
+ * esbuild-wasm (the package whose esbuild.wasm is staged to ASSETS, so the glue
312
+ * always matches the binary), wrapped so each run hands it its own global and
313
+ * `fs`, followed by the typed runner as an IIFE that installs
314
+ * globalThis.__esbuildCliRun. wasm_exec.js is spliced in verbatim, license
315
+ * header included.
316
+ */
317
+ async function bundleEsbuildCli() {
318
+ const result = await build({
319
+ entryPoints: [join(coreRoot, 'src', 'runtime', 'esbuild-cli', 'preamble.ts')],
320
+ bundle: true,
321
+ format: 'iife',
322
+ target: 'esnext',
323
+ platform: 'neutral',
324
+ absWorkingDir: root,
325
+ write: false,
326
+ logLevel: 'warning',
327
+ legalComments: 'none',
328
+ });
329
+ if (!result.outputFiles || result.outputFiles.length === 0) {
330
+ throw new Error('[bundle-facet-workers/esbuild-cli] esbuild produced no output');
331
+ }
332
+ const runner = withoutComments(result.outputFiles[0].text);
333
+ if (!/^\s*globalThis\.__esbuildCliRun\s*=/m.test(runner)) {
334
+ throw new Error(
335
+ '[bundle-facet-workers/esbuild-cli] the bundle no longer assigns globalThis.__esbuildCliRun — ' +
336
+ 'every esbuild command would fail inside the esbuild facet',
337
+ );
338
+ }
339
+ if (/^\s*(?:import|export)\b/m.test(runner)) {
340
+ throw new Error('[bundle-facet-workers/esbuild-cli] an import/export survived bundling');
341
+ }
342
+ const glue = readFileSync(join(resolvePackageDir('esbuild-wasm', { start: root }), 'wasm_exec.js'), 'utf8');
343
+ if (!/globalThis\.Go\s*=\s*class\b/.test(glue)) {
344
+ throw new Error('[bundle-facet-workers/esbuild-cli] esbuild-wasm/wasm_exec.js no longer defines globalThis.Go');
345
+ }
346
+ return `const __esbuildGoRuntime = function (globalThis, fs) {\n${glue}\nreturn globalThis.Go;\n};\n${runner}`;
347
+ }
348
+
349
+ /**
350
+ * Stage the esbuild CLI runner under public/_assets/runtime/, named by a
351
+ * prefix of its own digest so no cache layer can serve another build's bytes
352
+ * under its name, and pin it in src/esbuild-cli-artifact.generated.ts.
353
+ */
354
+ function stageEsbuildCli(src) {
355
+ const sha256 = createHash('sha256').update(src, 'utf8').digest('hex');
356
+ const buildId = sha256.slice(0, 16);
357
+ const assetDir = join(root, 'public', '_assets', 'runtime');
358
+ const assetName = `esbuild-cli-${buildId}.js`;
359
+ mkdirSync(assetDir, { recursive: true });
360
+ for (const entry of readdirSync(assetDir)) {
361
+ if (entry.startsWith('esbuild-cli-') && entry !== assetName) unlinkSync(join(assetDir, entry));
362
+ }
363
+ writeFileSync(join(assetDir, assetName), src, 'utf8');
364
+ const assetPath = `/_assets/runtime/${assetName}`;
365
+ const generatedPath = join(root, 'src', 'esbuild-cli-artifact.generated.ts');
366
+ writeFileSync(generatedPath, [
367
+ '/**',
368
+ ' * esbuild-cli-artifact.generated.ts — AUTO-GENERATED by',
369
+ ' * scripts/bundle-facet-workers.mjs. DO NOT EDIT.',
370
+ ' *',
371
+ ' * Pins the staged runner of the `esbuild` command: esbuild-wasm/wasm_exec.js',
372
+ ' * (Go js/wasm glue, as __esbuildGoRuntime) followed by @nimbus-sh/core',
373
+ ' * src/runtime/esbuild-cli/preamble.ts as an IIFE. Only the session\'s esbuild',
374
+ ' * facet evaluates it, so src/runtime/esbuild-wasm-bytes.ts fetches it from',
375
+ ' * ASSETS when that facet is built, instead of the Worker bundle carrying it.',
376
+ ' * ESBUILD_CLI_BUILD_ID is a content-hash prefix, ESBUILD_CLI_SHA256 the',
377
+ ' * digest every fetch is verified against.',
378
+ ' *',
379
+ ` * Size: ${(src.length / 1024).toFixed(2)} KiB`,
380
+ ' */',
381
+ '',
382
+ `export const ESBUILD_CLI_ASSET_PATH: string = ${JSON.stringify(assetPath)};`,
383
+ `export const ESBUILD_CLI_BUILD_ID: string = ${JSON.stringify(buildId)};`,
384
+ `export const ESBUILD_CLI_SHA256: string = ${JSON.stringify(sha256)};`,
385
+ '',
386
+ ].join('\n'));
387
+ return { assetPath, generatedPath };
388
+ }
389
+
301
390
  async function main() {
302
391
  // 1. Tar-parser preamble (existing W2.5/W4 hot-path helpers).
303
392
  const tarStripped = await bundleAsPreamble(
@@ -317,6 +406,17 @@ async function main() {
317
406
  'w7-frame',
318
407
  );
319
408
 
409
+ // 3. Node's ESM resolver, which the node shims embed as source (their
410
+ // process's import() loader). One compile of it, here, so the shims'
411
+ // copy is the same text whatever toolchain later evaluates the shims.
412
+ const esmResolver = await bundleAsPreamble(
413
+ join(coreRoot, 'src', '_shared', 'esm-resolver.ts'),
414
+ 'esm-resolver',
415
+ );
416
+ if (!/^function createEsmResolver\(/m.test(esmResolver)) {
417
+ throw new Error('[bundle-facet-workers/esm-resolver] the bundle no longer declares function createEsmResolver');
418
+ }
419
+
320
420
  const tarEncoded = JSON.stringify(tarStripped);
321
421
  const w7Encoded = JSON.stringify(w7Stripped);
322
422
  const outPath = join(root, 'src', 'loaders', 'generated-workers.ts');
@@ -328,8 +428,9 @@ async function main() {
328
428
  ' * Produced by scripts/bundle-facet-workers.mjs from:',
329
429
  ' * - @nimbus-sh/core src/_shared/tarball-stream.ts (streaming tar primitives)',
330
430
  ' * - @nimbus-sh/platform src/w7-frame.ts (W7 streaming bulk-write encoder)',
431
+ ' * - @nimbus-sh/core src/_shared/esm-resolver.ts (Node\'s ESM resolver, for the node shims)',
331
432
  ' *',
332
- ' * Consumed by src/loaders/loader-pool.ts callers via the `preamble`',
433
+ ' * Consumed by fabric/isolate-pool.ts callers via the `preamble`',
333
434
  ' * option. The preamble is injected at the top of every generated',
334
435
  ' * worker module so user functions can reference the exported',
335
436
  ' * helpers by name.',
@@ -347,6 +448,9 @@ async function main() {
347
448
  '',
348
449
  `export const W7_FRAME_PREAMBLE: string = ${w7Encoded};`,
349
450
  '',
451
+ '/** Declares `function createEsmResolver(host)`; the node shims call it. */',
452
+ `export const ESM_RESOLVER_PREAMBLE: string = ${JSON.stringify(esmResolver)};`,
453
+ '',
350
454
  ].join('\n');
351
455
 
352
456
  mkdirSync(dirname(outPath), { recursive: true });
@@ -418,6 +522,9 @@ async function main() {
418
522
  '',
419
523
  ].join('\n'));
420
524
 
525
+ const esbuildCliSrc = await bundleEsbuildCli();
526
+ const esbuildCli = stageEsbuildCli(esbuildCliSrc);
527
+
421
528
  console.log(
422
529
  `[bundle-facet-workers] wrote ${kernelOutPath} ` +
423
530
  `(kernel=${(kernelSrc.length / 1024).toFixed(2)} KiB)`,
@@ -430,13 +537,17 @@ async function main() {
430
537
  `[bundle-facet-workers] wrote ${bashOutPath} ` +
431
538
  `(bash=${(bashSrc.length / 1024).toFixed(2)} KiB)`,
432
539
  );
540
+ console.log(
541
+ `[bundle-facet-workers] staged ${esbuildCli.assetPath} and wrote ${esbuildCli.generatedPath} ` +
542
+ `(esbuild-cli=${(esbuildCliSrc.length / 1024).toFixed(2)} KiB)`,
543
+ );
433
544
  }
434
545
 
435
546
  // The bundle functions are exported so the parity test can re-derive the
436
547
  // generated files from source and compare, rather than restating the esbuild
437
548
  // settings — a second copy of those settings is exactly the drift such a test
438
549
  // exists to catch. main() therefore runs only when this file is the entry point.
439
- export { bundleWasiInstance, bundleBashRunner };
550
+ export { bundleWasiInstance, bundleBashRunner, bundleEsbuildCli };
440
551
 
441
552
  if (process.argv[1] && pathToFileURL(process.argv[1]).href === import.meta.url) {
442
553
  main().catch((e) => {
@@ -1,30 +1,37 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * bundle-git.mjs — Pre-bundle isomorphic-git for the git-network-facet.
3
+ * bundle-git.mjs — Build the patched git module for hosts and network facets.
4
4
  *
5
5
  * WHY this exists:
6
6
  * The git-network-facet runs inside a dynamic worker loaded via
7
7
  * env.LOADER.load(). Dynamic workers have NO access to node_modules —
8
8
  * they only see modules explicitly passed in the `modules` object.
9
9
  *
10
- * The main Worker's bundler (wrangler) inlines isomorphic-git into the
11
- * supervisor, but that bundle is unreachable from the facet isolate.
10
+ * Hosts import the executable module shipped in vendor/. Consumers never
11
+ * depend on Nimbus' repository postinstall having patched their dependencies.
12
12
  *
13
13
  * This script bundles isomorphic-git + isomorphic-git/http/web into ONE
14
- * ESM string that we can pass as a module to LOADER.load(). The facet
15
- * imports it via `import('./isomorphic-git.js')`.
14
+ * ESM module. The same bytes are staged as the asset the facet's
15
+ * LOADER.load() receives as `git-bundle.js`.
16
16
  *
17
17
  * Output:
18
- * src/git-bundle.generated.ts — exports GIT_BUNDLE_CODE: string
18
+ * vendor/git.generated.mjs + self-contained declarations
19
+ * public/_assets/runtime/git-<buildId>.js — byte-identical staged copy
20
+ * src/git-bundle.generated.ts — GIT_BUNDLE_ENTRY / _BUILD_ID / _SHA256 pins
19
21
  *
20
22
  * Runs as a postinstall step AND on every `bun run dev` / `bun run deploy`
21
23
  * via the "bundle:git" npm script.
22
24
  */
23
25
 
24
26
  import { build } from 'esbuild';
25
- import { writeFileSync, mkdirSync, existsSync } from 'node:fs';
27
+ import { createHash } from 'node:crypto';
28
+ import { writeFileSync, readFileSync, readdirSync, mkdirSync, existsSync, unlinkSync } from 'node:fs';
26
29
  import { dirname, join } from 'node:path';
27
30
  import { fileURLToPath } from 'node:url';
31
+ import ts from 'typescript';
32
+
33
+ import { assertCfGitPatched } from './cf-git-patch.mjs';
34
+ import { resolvePackageDir } from './resolve-package-dir.mjs';
28
35
 
29
36
  const __dirname = dirname(fileURLToPath(import.meta.url));
30
37
  const root = join(__dirname, '..');
@@ -37,7 +44,43 @@ const ENTRY_CONTENTS = [
37
44
 
38
45
  const ENTRY_FILE = join(root, '.git-bundle-entry.js');
39
46
 
47
+ // Upstream declarations are copied mechanically; only the tracked patch's
48
+ // public signature changes live here. No consumer dependency on the build input.
49
+ const GIT_TYPES = `import type * as Upstream from './git-upstream.generated.js';
50
+ type Add = Parameters<typeof Upstream.add>[0];
51
+ type Remove = Parameters<typeof Upstream.remove>[0];
52
+ type Commit = Parameters<typeof Upstream.commit>[0];
53
+ type Matrix = Parameters<typeof Upstream.statusMatrix>[0];
54
+ type Checkout = Parameters<typeof Upstream.checkout>[0];
55
+ export declare const git: Omit<typeof Upstream, 'add' | 'remove' | 'commit' | 'statusMatrix'> & {
56
+ add(options: Omit<Add, 'filepath'> & { filepath: string | string[] }): ReturnType<typeof Upstream.add>;
57
+ remove(options: Omit<Remove, 'filepath'> & { filepath: string | string[] }): ReturnType<typeof Upstream.remove>;
58
+ commit(options: Commit & { rawMessage?: boolean }): ReturnType<typeof Upstream.commit>;
59
+ statusMatrix(options: Matrix & { deferRefresh?: boolean }): ReturnType<typeof Upstream.statusMatrix>;
60
+ stage(options: Pick<Add, 'fs' | 'dir' | 'gitdir' | 'cache' | 'force' | 'parallel'> & {
61
+ add?: string[]; remove?: string[];
62
+ }): Promise<void>;
63
+ checkoutFreshChunk(options: Pick<Checkout, 'fs' | 'dir' | 'gitdir' | 'ref' | 'cache' | 'onProgress'> & {
64
+ cursor?: object | null; maxEntries: number; maxDecodedBytes: number; maxWallMs: number;
65
+ deferIndexFragmentCleanup?: boolean;
66
+ }): Promise<{ nextCursor: object | null; files: number; decodedBytes: number; treeEntriesVisited: number; indexEntries: number }>;
67
+ };
68
+ export * as gitHttp from './git-http.generated.js';
69
+ `;
70
+
71
+ function declaration(source, destination) {
72
+ const text = readFileSync(source, 'utf8');
73
+ if (ts.preProcessFile(text).importedFiles.length) {
74
+ throw new Error('Git declarations acquired imports; bundle their types before publishing: ' + source);
75
+ }
76
+ writeFileSync(destination, '// Generated by scripts/bundle-git.mjs from the pinned cf-git declarations.\n' + text);
77
+ }
78
+
40
79
  async function main() {
80
+ // A copy patched by another revision of the tracked patch would bundle
81
+ // without its fixes, and nothing downstream would notice: refuse instead.
82
+ const gitDir = resolvePackageDir('isomorphic-git', { start: root });
83
+ assertCfGitPatched(join(root, '..', '..'), [gitDir]);
41
84
  try {
42
85
  writeFileSync(ENTRY_FILE, ENTRY_CONTENTS);
43
86
 
@@ -59,6 +102,12 @@ async function main() {
59
102
  'node:*',
60
103
  'cloudflare:workers',
61
104
  ],
105
+ // The module ships inside the supervisor Worker, which has a size budget
106
+ // (tests/behavioral/assets-fetch/new/worker-bundle-size.mjs), and as a
107
+ // staged asset. Whitespace and syntax minification take ~200 KB off it;
108
+ // identifiers are kept, so stack traces still name cf-git's functions.
109
+ minifyWhitespace: true,
110
+ minifySyntax: true,
62
111
  write: false,
63
112
  logLevel: 'warning',
64
113
  });
@@ -69,43 +118,55 @@ async function main() {
69
118
 
70
119
  const code = result.outputFiles[0].text;
71
120
 
72
- // Emit as a TS module that exports the bundle as a string constant.
73
- // Using String.raw-equivalent: JSON-encode to preserve backticks/$/etc.
74
- const outPath = join(root, 'src', 'git-bundle.generated.ts');
121
+ const vendor = join(root, 'vendor');
122
+ mkdirSync(vendor, { recursive: true });
123
+ writeFileSync(join(vendor, 'git.generated.mjs'), code);
124
+ writeFileSync(join(vendor, 'git.LICENSE'), readFileSync(join(gitDir, 'LICENSE.md')));
125
+ declaration(join(gitDir, 'index.d.ts'), join(vendor, 'git-upstream.generated.d.ts'));
126
+ declaration(join(gitDir, 'http', 'web', 'index.d.ts'), join(vendor, 'git-http.generated.d.ts'));
127
+ writeFileSync(join(vendor, 'git.generated.d.mts'), '// Generated by scripts/bundle-git.mjs.\n' + GIT_TYPES);
75
128
 
76
- // We JSON.stringify the code to produce a valid JS string literal.
77
- // Then wrap in a TS const export. The supervisor imports this at build.
78
- const encoded = JSON.stringify(code);
129
+ // The facet's copy is a staged asset, not a string in the Worker bundle:
130
+ // the Worker already carries the executable module above, and a second
131
+ // inlined copy cost ~310 KB of the bundle's size gate
132
+ // (tests/behavioral/assets-fetch/new/worker-bundle-size.mjs). Same
133
+ // mechanism as scripts/bundle-node-shims.mjs; src/runtime/git-bundle-artifact.ts
134
+ // fetches it sha-verified.
135
+ const sha256 = createHash('sha256').update(code, 'utf8').digest('hex');
136
+ const buildId = sha256.slice(0, 16);
137
+ const assetName = `git-${buildId}.js`;
138
+ const assetDir = join(root, 'public', '_assets', 'runtime');
139
+ mkdirSync(assetDir, { recursive: true });
140
+ // Exactly one staged copy: the entry constant pins which one a deploy serves.
141
+ for (const file of readdirSync(assetDir)) {
142
+ if (/^git-[0-9a-f]{16}\.js$/.test(file) && file !== assetName) unlinkSync(join(assetDir, file));
143
+ }
144
+ writeFileSync(join(assetDir, assetName), code);
79
145
 
146
+ const outPath = join(root, 'src', 'git-bundle.generated.ts');
80
147
  const tsWrapper = [
81
148
  '/**',
82
- ' * git-bundle.generated.ts — AUTO-GENERATED. DO NOT EDIT.',
83
- ' *',
84
- ' * Produced by scripts/bundle-git.mjs from:',
85
- " * - isomorphic-git (github:AshishKumar4/cf-git)",
86
- " * - isomorphic-git/http/web",
149
+ ' * git-bundle.generated.ts — AUTO-GENERATED by scripts/bundle-git.mjs. DO NOT EDIT.',
87
150
  ' *',
88
- ' * Consumed by git-network-facet.ts: passed to LOADER.load()\'s',
89
- ' * `modules` record so the facet can `import` isomorphic-git.',
90
- ' *',
91
- ` * Size: ${(code.length / 1024).toFixed(1)} KiB`,
151
+ ' * Pins the staged copy of vendor/git.generated.mjs (isomorphic-git from',
152
+ ' * github:AshishKumar4/cf-git + isomorphic-git/http/web) that the git network',
153
+ " * facet imports as `git-bundle.js`. GIT_BUNDLE_SHA256 is verified at fetch time.",
92
154
  ' */',
93
155
  '',
94
- `export const GIT_BUNDLE_CODE: string = ${encoded};`,
95
- '',
96
- `export const GIT_BUNDLE_SIZE = ${code.length};`,
156
+ `export const GIT_BUNDLE_ENTRY: string = ${JSON.stringify(`/_assets/runtime/${assetName}`)};`,
157
+ `export const GIT_BUNDLE_BUILD_ID: string = ${JSON.stringify(buildId)};`,
158
+ `export const GIT_BUNDLE_SHA256: string = ${JSON.stringify(sha256)};`,
97
159
  '',
98
160
  ].join('\n');
99
161
 
100
162
  mkdirSync(dirname(outPath), { recursive: true });
101
163
  writeFileSync(outPath, tsWrapper);
102
164
 
103
- console.log(`[bundle-git] wrote ${outPath} (${(code.length / 1024).toFixed(1)} KiB bundled)`);
165
+ console.log(`[bundle-git] staged ${assetName} (${(code.length / 1024).toFixed(1)} KiB) and wrote ${outPath}`);
104
166
  } finally {
105
167
  // Clean up the temp entry file
106
168
  try {
107
169
  if (existsSync(ENTRY_FILE)) {
108
- const { unlinkSync } = await import('node:fs');
109
170
  unlinkSync(ENTRY_FILE);
110
171
  }
111
172
  } catch {}
@@ -1,31 +1,37 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * bundle-node-shims.mjs — stage the node-compat shim source as a static asset.
3
+ * bundle-node-shims.mjs — stage the node-compat layer's sources as static assets.
4
4
  *
5
5
  * Why this exists
6
6
  * ───────────────
7
- * `generateShimsCode()` (src/runtime/node-shims.ts) produces the ~230 KiB
8
- * node-compat shim source that every node facet's generated worker text
9
- * interpolates (`${SHIMS}` in facets/manager.ts entrypoint codegen and the
10
- * opencode facet runner). Keeping that template inside the worker bundle
11
- * pushed the main bundle over the ≤6 MiB gate
12
- * (tests/behavioral/assets-fetch/new/worker-bundle-size.mjs), whose intended
13
- * fix is exactly this promote: large facet-runner source strings belong in
14
- * the static-assets layer, not the supervisor bundle.
7
+ * Every node facet's generated worker text splices three sources that only
8
+ * ever run inside the facet:
9
+ * - `generateShimsCode()` (src/runtime/node-shims.ts), the ~230 KiB
10
+ * node-compat shims;
11
+ * - `VFS_WRITE_LEDGER_SOURCE` (@nimbus-sh/core _shared/vfs-write-ledger.ts),
12
+ * the write ledger the shims' filesystem writes go through;
13
+ * - `FACET_RESIDENT_STORE_SOURCE` (src/vfs/facet-resident-store.ts), a
14
+ * resident facet's SQLite-backed resident set the shims read from.
15
+ * Keeping them inside the worker bundle pushed the main bundle over its size
16
+ * gate (tests/behavioral/assets-fetch/new/worker-bundle-size.mjs), whose
17
+ * intended fix is exactly this promote: large facet-runner source strings
18
+ * belong in the static-assets layer, not the supervisor bundle. Nothing the
19
+ * Worker bundle imports reaches the three modules any more.
15
20
  *
16
- * This script evaluates the COMMITTED dist's generateShimsCode() — dist is
17
- * the deployable truth (package "main" points at dist; apps bundle from it),
18
- * so the staged asset always matches what a deploy would have shipped inline.
19
- * Drift between src and the staged asset is caught by
20
- * tests/unit/node-shims-artifact-parity.mjs (asserts asset bytes equal the
21
- * CURRENT src generateShimsCode() output).
21
+ * This script evaluates the COMMITTED dist — dist is the deployable truth
22
+ * (package "main" points at dist; apps bundle from it), so each staged asset
23
+ * matches what a deploy would have shipped inline. Drift between src and the
24
+ * staged assets is caught by tests/unit/node-shims-artifact-parity.mjs
25
+ * (asserts each asset's bytes equal the CURRENT src output).
22
26
  *
23
27
  * Output:
24
- * public/_assets/runtime/node-shims-<buildId>.js (the shim source)
25
- * src/node-shims-artifact.generated.ts
26
- * export const NODE_SHIMS_ENTRY: string; // asset path
27
- * export const NODE_SHIMS_BUILD_ID: string; // content-hash prefix
28
- * export const NODE_SHIMS_SHA256: string; // full digest
28
+ * public/_assets/runtime/node-shims-<buildId>.js
29
+ * public/_assets/runtime/vfs-write-ledger-<buildId>.js
30
+ * public/_assets/runtime/resident-store-<buildId>.js
31
+ * src/node-shims-artifact.generated.ts, per source:
32
+ * export const <NAME>_ENTRY: string; // asset path
33
+ * export const <NAME>_BUILD_ID: string; // content-hash prefix
34
+ * export const <NAME>_SHA256: string; // full digest
29
35
  *
30
36
  * Fetched at runtime by src/runtime/node-shims-artifact.ts (L2 + ASSETS,
31
37
  * sha-verified, memoized per isolate).
@@ -42,9 +48,9 @@ import { fileURLToPath } from 'node:url';
42
48
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
43
49
  const ROOT = path.resolve(__dirname, '..');
44
50
 
45
- const { generateShimsCode } = await import(
46
- path.join(ROOT, 'dist/runtime/node-shims.js')
47
- );
51
+ const { generateShimsCode } = await import(path.join(ROOT, 'dist/runtime/node-shims.js'));
52
+ const { FACET_RESIDENT_STORE_SOURCE } = await import(path.join(ROOT, 'dist/vfs/facet-resident-store.js'));
53
+ const { VFS_WRITE_LEDGER_SOURCE } = await import('@nimbus-sh/core/_shared/vfs-write-ledger.js');
48
54
 
49
55
  const shims = generateShimsCode();
50
56
  if (typeof shims !== 'string' || shims.length < 100_000) {
@@ -55,38 +61,58 @@ if (typeof shims !== 'string' || shims.length < 100_000) {
55
61
  );
56
62
  }
57
63
 
58
- const sha256 = createHash('sha256').update(shims, 'utf8').digest('hex');
59
- const buildId = sha256.slice(0, 16);
60
- const assetDir = path.join(ROOT, 'public/_assets/runtime');
61
- const assetName = `node-shims-${buildId}.js`;
62
- const entry = `/_assets/runtime/${assetName}`;
64
+ const SOURCES = [
65
+ { name: 'NODE_SHIMS', family: 'node-shims', source: shims, from: 'dist/runtime/node-shims.js generateShimsCode()' },
66
+ {
67
+ name: 'VFS_WRITE_LEDGER',
68
+ family: 'vfs-write-ledger',
69
+ source: VFS_WRITE_LEDGER_SOURCE,
70
+ from: '@nimbus-sh/core dist/_shared/vfs-write-ledger.js VFS_WRITE_LEDGER_SOURCE',
71
+ },
72
+ {
73
+ name: 'RESIDENT_STORE',
74
+ family: 'resident-store',
75
+ source: FACET_RESIDENT_STORE_SOURCE,
76
+ from: 'dist/vfs/facet-resident-store.js FACET_RESIDENT_STORE_SOURCE',
77
+ },
78
+ ];
63
79
 
80
+ const assetDir = path.join(ROOT, 'public/_assets/runtime');
64
81
  await fs.mkdir(assetDir, { recursive: true });
65
- // Remove stale same-family assets so the directory carries exactly one
66
- // node-shims blob (the entry constant pins which one a deploy serves).
67
- for (const f of await fs.readdir(assetDir)) {
68
- if (f.startsWith('node-shims-') && f !== assetName) {
69
- await fs.unlink(path.join(assetDir, f));
82
+ const existing = await fs.readdir(assetDir);
83
+ const pins = [];
84
+ for (const { name, family, source, from } of SOURCES) {
85
+ if (typeof source !== 'string' || source.length === 0) {
86
+ throw new Error(`[bundle-node-shims] ${from} is ${typeof source === 'string' ? 'empty' : typeof source}, not the source to stage`);
87
+ }
88
+ const sha256 = createHash('sha256').update(source, 'utf8').digest('hex');
89
+ const buildId = sha256.slice(0, 16);
90
+ const assetName = `${family}-${buildId}.js`;
91
+ // Remove stale same-family assets so the directory carries exactly one blob
92
+ // per family (the entry constant pins which one a deploy serves).
93
+ for (const f of existing) {
94
+ if (f.startsWith(`${family}-`) && f !== assetName) await fs.unlink(path.join(assetDir, f));
70
95
  }
96
+ await fs.writeFile(path.join(assetDir, assetName), source, 'utf8');
97
+ pins.push(
98
+ `/** ${from} */`,
99
+ `export const ${name}_ENTRY: string = ${JSON.stringify(`/_assets/runtime/${assetName}`)};`,
100
+ `export const ${name}_BUILD_ID: string = ${JSON.stringify(buildId)};`,
101
+ `export const ${name}_SHA256: string = ${JSON.stringify(sha256)};`,
102
+ '',
103
+ );
104
+ console.log(`[bundle-node-shims] staged ${assetName} (${(source.length / 1024).toFixed(1)} KiB, sha ${buildId}…)`);
71
105
  }
72
- await fs.writeFile(path.join(assetDir, assetName), shims, 'utf8');
73
106
 
74
107
  const generated = `/**
75
108
  * node-shims-artifact.generated.ts — AUTO-GENERATED by
76
109
  * scripts/bundle-node-shims.mjs. DO NOT EDIT.
77
110
  *
78
- * Pins the staged node-compat shim asset (the generateShimsCode() output
79
- * promoted out of the worker bundle). NODE_SHIMS_BUILD_ID is a content-hash
80
- * prefix so cache layers never serve stale bytes after a rebuild;
81
- * NODE_SHIMS_SHA256 is the full digest verified at fetch time.
111
+ * Pins the staged sources of the node-compat layer, promoted out of the worker
112
+ * bundle: the shims, the VFS write ledger and the resident store. Each
113
+ * <NAME>_BUILD_ID is a content-hash prefix so cache layers never serve stale
114
+ * bytes after a rebuild; <NAME>_SHA256 is the full digest verified at fetch time.
82
115
  */
83
116
 
84
- export const NODE_SHIMS_ENTRY: string = ${JSON.stringify(entry)};
85
- export const NODE_SHIMS_BUILD_ID: string = ${JSON.stringify(buildId)};
86
- export const NODE_SHIMS_SHA256: string = ${JSON.stringify(sha256)};
87
- `;
117
+ ${pins.join('\n')}`;
88
118
  await fs.writeFile(path.join(ROOT, 'src/node-shims-artifact.generated.ts'), generated, 'utf8');
89
-
90
- console.log(
91
- `[bundle-node-shims] staged ${assetName} (${(shims.length / 1024).toFixed(1)} KiB, sha ${buildId}…)`,
92
- );