@nimbus-sh/worker 0.9.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 (286) 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/esbuild-wasm-bundle.generated.d.ts +24 -24
  19. package/dist/esbuild-wasm-bundle.generated.d.ts.map +1 -1
  20. package/dist/esbuild-wasm-bundle.generated.js +24 -24
  21. package/dist/facets/cirrus-real.d.ts.map +1 -1
  22. package/dist/facets/cirrus-real.js +11 -6
  23. package/dist/facets/compose.d.ts +11 -7
  24. package/dist/facets/compose.d.ts.map +1 -1
  25. package/dist/facets/compose.js +8 -31
  26. package/dist/facets/data-plan.d.ts +79 -0
  27. package/dist/facets/data-plan.d.ts.map +1 -0
  28. package/dist/facets/data-plan.js +477 -0
  29. package/dist/facets/esbuild-bundle-pool.d.ts +1 -1
  30. package/dist/facets/esbuild-bundle-pool.js +3 -3
  31. package/dist/facets/esbuild-transform.d.ts +38 -8
  32. package/dist/facets/esbuild-transform.d.ts.map +1 -1
  33. package/dist/facets/esbuild-transform.js +219 -19
  34. package/dist/facets/exec-telemetry.d.ts +7 -3
  35. package/dist/facets/exec-telemetry.d.ts.map +1 -1
  36. package/dist/facets/manager.d.ts +198 -69
  37. package/dist/facets/manager.d.ts.map +1 -1
  38. package/dist/facets/manager.js +1276 -652
  39. package/dist/facets/opencode-staging.d.ts +0 -2
  40. package/dist/facets/opencode-staging.d.ts.map +1 -1
  41. package/dist/facets/opencode-staging.js +5 -11
  42. package/dist/facets/process.d.ts +4 -0
  43. package/dist/facets/process.d.ts.map +1 -1
  44. package/dist/facets/process.js +3 -0
  45. package/dist/facets/read-profile.d.ts +149 -0
  46. package/dist/facets/read-profile.d.ts.map +1 -0
  47. package/dist/facets/read-profile.js +483 -0
  48. package/dist/facets/real-vite-hmr.d.ts +2 -0
  49. package/dist/facets/real-vite-hmr.d.ts.map +1 -1
  50. package/dist/facets/real-vite-hmr.js +3 -2
  51. package/dist/facets/resident-identity.d.ts +0 -1
  52. package/dist/facets/resident-identity.d.ts.map +1 -1
  53. package/dist/facets/resident-identity.js +0 -3
  54. package/dist/facets/wasm-swap-registry.d.ts +34 -25
  55. package/dist/facets/wasm-swap-registry.d.ts.map +1 -1
  56. package/dist/facets/wasm-swap-registry.js +62 -56
  57. package/dist/facets/ws-terminal.d.ts +4 -4
  58. package/dist/facets/ws-terminal.d.ts.map +1 -1
  59. package/dist/facets/ws-terminal.js +4 -5
  60. package/dist/git/commands.d.ts +33 -10
  61. package/dist/git/commands.d.ts.map +1 -1
  62. package/dist/git/commands.js +1891 -197
  63. package/dist/git/network-facet.d.ts +12 -2
  64. package/dist/git/network-facet.d.ts.map +1 -1
  65. package/dist/git/network-facet.js +69 -18
  66. package/dist/git/unified-diff.d.ts +74 -0
  67. package/dist/git/unified-diff.d.ts.map +1 -0
  68. package/dist/git/unified-diff.js +676 -0
  69. package/dist/git-bundle.generated.d.ts +7 -11
  70. package/dist/git-bundle.generated.d.ts.map +1 -1
  71. package/dist/git-bundle.generated.js +7 -11
  72. package/dist/hosted/commands.d.ts.map +1 -1
  73. package/dist/hosted/commands.js +64 -245
  74. package/dist/hosted/runtime.d.ts +22 -15
  75. package/dist/hosted/runtime.d.ts.map +1 -1
  76. package/dist/hosted/runtime.js +72 -14
  77. package/dist/hosted/services.d.ts +8 -1
  78. package/dist/hosted/services.d.ts.map +1 -1
  79. package/dist/hosted/services.js +12 -13
  80. package/dist/hosted/session.d.ts +165 -0
  81. package/dist/hosted/session.d.ts.map +1 -0
  82. package/dist/hosted/session.js +132 -0
  83. package/dist/loaders/generated-workers.d.ts +6 -3
  84. package/dist/loaders/generated-workers.d.ts.map +1 -1
  85. package/dist/loaders/generated-workers.js +8 -5
  86. package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -1
  87. package/dist/loaders/npm-resolve-preamble.js +0 -27
  88. package/dist/loaders/pre-bundle-preamble.d.ts +6 -3
  89. package/dist/loaders/pre-bundle-preamble.d.ts.map +1 -1
  90. package/dist/loaders/pre-bundle-preamble.js +13 -8
  91. package/dist/node-shims-artifact.generated.d.ts +13 -4
  92. package/dist/node-shims-artifact.generated.d.ts.map +1 -1
  93. package/dist/node-shims-artifact.generated.js +16 -7
  94. package/dist/npm/bin-links.d.ts +3 -1
  95. package/dist/npm/bin-links.d.ts.map +1 -1
  96. package/dist/npm/bin-links.js +32 -8
  97. package/dist/npm/cache.d.ts +11 -1
  98. package/dist/npm/cache.d.ts.map +1 -1
  99. package/dist/npm/cache.js +21 -7
  100. package/dist/npm/install-batch-facet.d.ts +4 -2
  101. package/dist/npm/install-batch-facet.d.ts.map +1 -1
  102. package/dist/npm/install-batch-facet.js +32 -18
  103. package/dist/npm/installer.d.ts +23 -3
  104. package/dist/npm/installer.d.ts.map +1 -1
  105. package/dist/npm/installer.js +330 -131
  106. package/dist/npm/npx-install.d.ts +3 -1
  107. package/dist/npm/npx-install.d.ts.map +1 -1
  108. package/dist/npm/npx-install.js +4 -1
  109. package/dist/npm/package-lock.d.ts +32 -0
  110. package/dist/npm/package-lock.d.ts.map +1 -0
  111. package/dist/npm/package-lock.js +65 -0
  112. package/dist/npm/placement.d.ts +16 -0
  113. package/dist/npm/placement.d.ts.map +1 -0
  114. package/dist/npm/placement.js +33 -0
  115. package/dist/npm/pre-bundle-facet.d.ts +1 -30
  116. package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
  117. package/dist/npm/pre-bundle-facet.js +3 -5
  118. package/dist/npm/r2-cache.d.ts +12 -6
  119. package/dist/npm/r2-cache.d.ts.map +1 -1
  120. package/dist/npm/r2-cache.js +34 -16
  121. package/dist/npm/resolve-one-facet.d.ts +3 -0
  122. package/dist/npm/resolve-one-facet.d.ts.map +1 -1
  123. package/dist/npm/resolve-one-facet.js +15 -3
  124. package/dist/npm/resolver.d.ts +11 -13
  125. package/dist/npm/resolver.d.ts.map +1 -1
  126. package/dist/npm/resolver.js +12 -25
  127. package/dist/opencode-artifact.generated.js +2 -2
  128. package/dist/replica/routing.d.ts +2 -38
  129. package/dist/replica/routing.d.ts.map +1 -1
  130. package/dist/replica/routing.js +3 -55
  131. package/dist/router/index.d.ts.map +1 -1
  132. package/dist/router/index.js +15 -2
  133. package/dist/router/public-directory.d.ts +18 -0
  134. package/dist/router/public-directory.d.ts.map +1 -1
  135. package/dist/router/public-directory.js +1 -1
  136. package/dist/router/remote-api.d.ts +3 -1
  137. package/dist/router/remote-api.d.ts.map +1 -1
  138. package/dist/router/remote-api.js +42 -79
  139. package/dist/runtime/bash-repl.js +2 -2
  140. package/dist/runtime/bun-repl.d.ts.map +1 -1
  141. package/dist/runtime/bun-repl.js +2 -13
  142. package/dist/runtime/cpython-resident.d.ts.map +1 -1
  143. package/dist/runtime/cpython-resident.js +2 -10
  144. package/dist/runtime/esbuild-wasm-bytes.d.ts +37 -18
  145. package/dist/runtime/esbuild-wasm-bytes.d.ts.map +1 -1
  146. package/dist/runtime/esbuild-wasm-bytes.js +66 -92
  147. package/dist/runtime/facet-loader-host.d.ts.map +1 -1
  148. package/dist/runtime/facet-loader-host.js +0 -7
  149. package/dist/runtime/git-bundle-artifact.d.ts +17 -0
  150. package/dist/runtime/git-bundle-artifact.d.ts.map +1 -0
  151. package/dist/runtime/git-bundle-artifact.js +25 -0
  152. package/dist/runtime/node-repl.d.ts.map +1 -1
  153. package/dist/runtime/node-repl.js +2 -13
  154. package/dist/runtime/node-shims-artifact.d.ts +22 -23
  155. package/dist/runtime/node-shims-artifact.d.ts.map +1 -1
  156. package/dist/runtime/node-shims-artifact.js +48 -78
  157. package/dist/runtime/node-shims.d.ts.map +1 -1
  158. package/dist/runtime/node-shims.js +2358 -996
  159. package/dist/runtime/opencode-artifact.d.ts.map +1 -1
  160. package/dist/runtime/opencode-artifact.js +17 -53
  161. package/dist/runtime/opencode-facet-runner.d.ts +3 -6
  162. package/dist/runtime/opencode-facet-runner.d.ts.map +1 -1
  163. package/dist/runtime/opencode-facet-runner.js +45 -10
  164. package/dist/runtime/opentui-wasm-bytes.d.ts.map +1 -1
  165. package/dist/runtime/opentui-wasm-bytes.js +16 -49
  166. package/dist/runtime/package-manager.d.ts +0 -2
  167. package/dist/runtime/package-manager.d.ts.map +1 -1
  168. package/dist/runtime/package-manager.js +0 -3
  169. package/dist/runtime/python-repl.d.ts.map +1 -1
  170. package/dist/runtime/python-repl.js +4 -35
  171. package/dist/runtime/repl-session.d.ts +10 -0
  172. package/dist/runtime/repl-session.d.ts.map +1 -1
  173. package/dist/runtime/repl-session.js +7 -0
  174. package/dist/runtime/ruby-repl.d.ts.map +1 -1
  175. package/dist/runtime/ruby-repl.js +2 -2
  176. package/dist/runtime/ruby-resident.d.ts.map +1 -1
  177. package/dist/runtime/ruby-resident.js +41 -51
  178. package/dist/runtime/runtime-catalog.d.ts +10 -3
  179. package/dist/runtime/runtime-catalog.d.ts.map +1 -1
  180. package/dist/runtime/runtime-catalog.js +125 -15
  181. package/dist/runtime/sqlite-wasm-bytes.d.ts +4 -4
  182. package/dist/runtime/sqlite-wasm-bytes.d.ts.map +1 -1
  183. package/dist/runtime/sqlite-wasm-bytes.js +21 -57
  184. package/dist/runtime/staged-source.d.ts +67 -0
  185. package/dist/runtime/staged-source.d.ts.map +1 -0
  186. package/dist/runtime/staged-source.js +113 -0
  187. package/dist/runtime/wasi/preamble.d.ts +0 -22
  188. package/dist/runtime/wasi/preamble.d.ts.map +1 -1
  189. package/dist/runtime/wasi/preamble.js +98 -1425
  190. package/dist/runtime-catalog.generated.js +1 -1
  191. package/dist/session/agent.d.ts +14 -2
  192. package/dist/session/agent.d.ts.map +1 -1
  193. package/dist/session/agent.js +57 -19
  194. package/dist/session/ai.d.ts +0 -11
  195. package/dist/session/ai.d.ts.map +1 -1
  196. package/dist/session/ai.js +0 -4
  197. package/dist/session/fs-watch.d.ts +0 -11
  198. package/dist/session/fs-watch.d.ts.map +1 -1
  199. package/dist/session/fs-watch.js +0 -21
  200. package/dist/session/hibernation.d.ts +68 -2
  201. package/dist/session/hibernation.d.ts.map +1 -1
  202. package/dist/session/hibernation.js +95 -1
  203. package/dist/session/init-phases.d.ts +1 -2
  204. package/dist/session/init-phases.d.ts.map +1 -1
  205. package/dist/session/init-phases.js +1 -2
  206. package/dist/session/init.d.ts.map +1 -1
  207. package/dist/session/init.js +7 -20
  208. package/dist/session/keys.d.ts +0 -3
  209. package/dist/session/keys.d.ts.map +1 -1
  210. package/dist/session/keys.js +0 -3
  211. package/dist/session/legacy-reset.d.ts +11 -0
  212. package/dist/session/legacy-reset.d.ts.map +1 -0
  213. package/dist/session/legacy-reset.js +16 -0
  214. package/dist/session/nimbus-session.d.ts +50 -16
  215. package/dist/session/nimbus-session.d.ts.map +1 -1
  216. package/dist/session/nimbus-session.js +77 -71
  217. package/dist/session/npm-install-port.d.ts.map +1 -1
  218. package/dist/session/npm-install-port.js +2 -0
  219. package/dist/session/programmatic.d.ts +13 -18
  220. package/dist/session/programmatic.d.ts.map +1 -1
  221. package/dist/session/programmatic.js +53 -39
  222. package/dist/session/replica-routes.d.ts +2 -3
  223. package/dist/session/replica-routes.d.ts.map +1 -1
  224. package/dist/session/replica-routes.js +3 -10
  225. package/dist/session/routes.d.ts.map +1 -1
  226. package/dist/session/routes.js +11 -12
  227. package/dist/session/rpc.d.ts +108 -21
  228. package/dist/session/rpc.d.ts.map +1 -1
  229. package/dist/session/rpc.js +194 -39
  230. package/dist/session/start-real-vite.js +2 -2
  231. package/dist/session/state-store.d.ts +1 -17
  232. package/dist/session/state-store.d.ts.map +1 -1
  233. package/dist/session/state-store.js +3 -53
  234. package/dist/session/supervisor-op.d.ts +7 -0
  235. package/dist/session/supervisor-op.d.ts.map +1 -1
  236. package/dist/session/supervisor-op.js +6 -1
  237. package/dist/session/supervisor-rpc.d.ts +116 -19
  238. package/dist/session/supervisor-rpc.d.ts.map +1 -1
  239. package/dist/session/supervisor-rpc.js +194 -84
  240. package/dist/session/vite-command.d.ts.map +1 -1
  241. package/dist/session/vite-command.js +17 -14
  242. package/dist/session/ws.d.ts.map +1 -1
  243. package/dist/session/ws.js +20 -8
  244. package/dist/shell/npm-bin-entrypoints.d.ts.map +1 -1
  245. package/dist/shell/npm-bin-entrypoints.js +30 -5
  246. package/dist/vfs/facet-resident-limits.d.ts +33 -0
  247. package/dist/vfs/facet-resident-limits.d.ts.map +1 -0
  248. package/dist/vfs/facet-resident-limits.js +33 -0
  249. package/dist/vfs/facet-resident-store.d.ts +2 -10
  250. package/dist/vfs/facet-resident-store.d.ts.map +1 -1
  251. package/dist/vfs/facet-resident-store.js +1594 -219
  252. package/dist/workspace-host.d.ts +3 -1
  253. package/dist/workspace-host.d.ts.map +1 -1
  254. package/dist/workspace-host.js +2 -0
  255. package/dist/wrangler/nimbus-wrangler.d.ts +0 -2
  256. package/dist/wrangler/nimbus-wrangler.d.ts.map +1 -1
  257. package/dist/wrangler/nimbus-wrangler.js +8 -22
  258. package/package.json +34 -7
  259. package/public/_assets/esbuild-0.24.2.js +2380 -0
  260. package/public/_assets/opencode/1.16.2/index-attach.js +2 -2
  261. package/public/_assets/runtime/esbuild-cli-c4fda380d52befc1.js +6892 -0
  262. package/public/_assets/runtime/git-de3e60c9f3ff006a.js +103 -0
  263. package/public/_assets/runtime/{node-shims-acaa037e6d26ec0d.js → node-shims-06565b121555c194.js} +2879 -992
  264. package/public/_assets/runtime/resident-store-6ffb1939c53d982f.js +2264 -0
  265. package/public/_assets/runtime/vfs-write-ledger-e501e8fc793bc2c1.js +889 -0
  266. package/scripts/build-opencode-attach-entry.mjs +51 -1
  267. package/scripts/bundle-esbuild-wasm.mjs +55 -39
  268. package/scripts/bundle-facet-workers.mjs +159 -10
  269. package/scripts/bundle-git.mjs +88 -27
  270. package/scripts/bundle-node-shims.mjs +72 -46
  271. package/scripts/bundle-runtime.mjs +18 -421
  272. package/scripts/cf-git-patch.mjs +137 -0
  273. package/scripts/patch-install-deps.mjs +49 -96
  274. package/scripts/runtime-specs.mjs +435 -0
  275. package/vendor/git-http.generated.d.ts +82 -0
  276. package/vendor/git-upstream.generated.d.ts +4378 -0
  277. package/vendor/git.LICENSE +7 -0
  278. package/vendor/git.generated.d.mts +21 -0
  279. package/vendor/git.generated.mjs +103 -0
  280. package/dist/replica/suspension.d.ts +0 -36
  281. package/dist/replica/suspension.d.ts.map +0 -1
  282. package/dist/replica/suspension.js +0 -49
  283. package/dist/runtime/static-server.d.ts +0 -3
  284. package/dist/runtime/static-server.d.ts.map +0 -1
  285. package/dist/runtime/static-server.js +0 -133
  286. package/scripts/clean-dist.mjs +0 -7
@@ -4,8 +4,9 @@
4
4
  * Produced by scripts/bundle-facet-workers.mjs from:
5
5
  * - @nimbus-sh/core src/_shared/tarball-stream.ts (streaming tar primitives)
6
6
  * - @nimbus-sh/platform src/w7-frame.ts (W7 streaming bulk-write encoder)
7
+ * - @nimbus-sh/core src/_shared/esm-resolver.ts (Node's ESM resolver, for the node shims)
7
8
  *
8
- * Consumed by src/loaders/loader-pool.ts callers via the `preamble`
9
+ * Consumed by fabric/isolate-pool.ts callers via the `preamble`
9
10
  * option. The preamble is injected at the top of every generated
10
11
  * worker module so user functions can reference the exported
11
12
  * helpers by name.
@@ -15,8 +16,10 @@
15
16
  * W7-frame symbols: encodeWriteBatchStream, decodeWriteBatchStream,
16
17
  * W7_MAGIC, W7_MAX_RECORD_BYTES.
17
18
  *
18
- * Tar size: 4.62 KiB
19
- * W7 size: 29.55 KiB
19
+ * Tar size: 4.58 KiB
20
+ * W7 size: 30.14 KiB
20
21
  */
21
- export const TAR_STREAM_PREAMBLE = "// ../core/src/_shared/tarball-stream.ts\nvar MAX_FILE_BYTES = 2e7;\nfunction canonicalTarName(name) {\n const out = [];\n for (const seg of name.split(\"/\")) {\n if (seg === \"..\") {\n if (out.length === 0) return \"\";\n out.pop();\n } else if (seg !== \"\" && seg !== \".\") {\n out.push(seg);\n }\n }\n return out.join(\"/\");\n}\nfunction parseTarHeader(block) {\n if (block[0] === 0) return null;\n let name = \"\";\n for (let i = 0; i < 100 && block[i] !== 0; i++) {\n name += String.fromCharCode(block[i]);\n }\n let prefix = \"\";\n for (let i = 345; i < 500 && block[i] !== 0; i++) {\n prefix += String.fromCharCode(block[i]);\n }\n if (prefix) name = prefix + \"/\" + name;\n name = canonicalTarName(name);\n let sizeStr = \"\";\n for (let i = 124; i < 136 && block[i] !== 0; i++) {\n sizeStr += String.fromCharCode(block[i]);\n }\n const size = parseInt(sizeStr.trim(), 8) || 0;\n const typeFlag = block[156];\n return { name, size, typeFlag };\n}\nasync function* readableStreamToAsyncIterable(rs) {\n const reader = rs.getReader();\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) return;\n if (value && value.length > 0) yield value;\n }\n } finally {\n try {\n reader.releaseLock();\n } catch {\n }\n }\n}\nasync function* streamTarEntries(source, onSkip) {\n let carry = new Uint8Array(0);\n let state = { kind: \"header\" };\n function concat(a, b) {\n if (a.length === 0) return b;\n if (b.length === 0) return a;\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n }\n for await (const chunkRaw of source) {\n let buf = concat(carry, chunkRaw);\n let cursor = 0;\n while (true) {\n if (state.kind === \"header\") {\n if (buf.length - cursor < 512) break;\n const header = buf.subarray(cursor, cursor + 512);\n const parsed = parseTarHeader(header);\n cursor += 512;\n if (!parsed) return;\n const { name, size, typeFlag } = parsed;\n const pad = size === 0 ? 0 : (512 - size % 512) % 512;\n const isRegularFile = typeFlag === 48 || typeFlag === 0;\n if (size === 0) {\n if (isRegularFile && name) {\n yield { name, data: new Uint8Array(0) };\n }\n state = { kind: \"header\" };\n continue;\n }\n if (!isRegularFile || !name || size > MAX_FILE_BYTES) {\n if (onSkip) {\n const reason = !isRegularFile ? \"non-regular\" : !name ? \"no-name\" : \"too-large\";\n try {\n onSkip(name, size, reason);\n } catch {\n }\n }\n state = { kind: \"skip\", remaining: size + pad };\n continue;\n }\n state = {\n kind: \"file\",\n name,\n remaining: size,\n fileBuf: new Uint8Array(size),\n fileOffset: 0,\n pad,\n skip: false\n };\n continue;\n }\n if (state.kind === \"file\") {\n const avail2 = buf.length - cursor;\n if (avail2 === 0) break;\n if (state.remaining > 0) {\n const take2 = Math.min(state.remaining, avail2);\n state.fileBuf.set(buf.subarray(cursor, cursor + take2), state.fileOffset);\n state.fileOffset += take2;\n state.remaining -= take2;\n cursor += take2;\n if (state.remaining > 0) break;\n }\n if (state.pad > 0) {\n const avail22 = buf.length - cursor;\n if (avail22 === 0) break;\n const take2 = Math.min(state.pad, avail22);\n state.pad -= take2;\n cursor += take2;\n if (state.pad > 0) break;\n }\n yield { name: state.name, data: state.fileBuf };\n state = { kind: \"header\" };\n continue;\n }\n const avail = buf.length - cursor;\n if (avail === 0) break;\n const take = Math.min(state.remaining, avail);\n cursor += take;\n state.remaining -= take;\n if (state.remaining > 0) break;\n state = { kind: \"header\" };\n }\n if (cursor >= buf.length) {\n carry = new Uint8Array(0);\n } else if (cursor === 0) {\n carry = buf;\n } else {\n carry = buf.slice(cursor);\n }\n }\n}\nasync function* streamPackageEntries(source, onSkip) {\n let prefix = null;\n for await (const entry of streamTarEntries(source, onSkip)) {\n if (prefix === null) {\n prefix = entry.name.split(\"/\", 1)[0];\n }\n if (entry.name === prefix) continue;\n if (!entry.name.startsWith(prefix + \"/\")) {\n throw new Error(\n `package tarball is not single-rooted: entry \"${entry.name}\" sits outside \"${prefix}/\"`\n );\n }\n yield { name: entry.name.slice(prefix.length + 1), data: entry.data };\n }\n}";
22
- export const W7_FRAME_PREAMBLE = "// ../platform/src/limits.ts\nvar CHUNK_SIZE = 65536;\nvar MAX_TX_BLOB_BYTES = 1 * 1024 * 1024;\nvar SQLITE_MAX_STATEMENT_BYTES = 100 * 1024;\nvar MAX_RPC_SAFE_PAYLOAD_BYTES = 28 * 1024 * 1024;\nvar SUPERVISOR_HEAP_CEILING_BYTES = 64 * 1024 * 1024;\nvar SUPERVISOR_IN_FLIGHT_ALLOCATION_BUDGET_BYTES = 40 * 1024 * 1024;\nvar SUPERVISOR_READ_RESERVE_BYTES = 1024 * 1024;\nvar MAX_GLOBAL_WRITE_STREAM_CREDIT_BYTES = 8 * 1024 * 1024;\n\n// ../platform/src/w7-frame.ts\nvar W7_MAGIC = new Uint8Array([78, 87, 55, 3]);\nvar ENCODER_QUEUE_HWM = 0;\nvar MAX_METADATA_BYTES = 64 * 1024;\nvar MAX_PATH_BYTES = 64 * 1024;\nvar MAX_BATCH_ID_BYTES = 128;\nvar MAX_CONTENT_ID_BYTES = 256;\nvar W7_MAX_PATHS_PER_BATCH = 128;\nvar W7_MAX_OWNED_PATH_BYTES = 64 * 1024;\nvar W7_MAX_RECORD_BYTES = 5 + 4 + MAX_CONTENT_ID_BYTES + 8 + CHUNK_SIZE;\nvar MODE = \"path-atomic-committed-prefix\";\nfunction encodeWriteBatchStream(payload) {\n const batchId = crypto.randomUUID();\n const { deletes, directories, files } = preparePayload(payload, batchId);\n const iterator = encodeRecords(batchId, deletes, directories, files);\n let closed = false;\n let magicEmitted = false;\n const source = {\n type: \"bytes\",\n pull(controller) {\n if (closed) return;\n try {\n if (!magicEmitted) {\n magicEmitted = true;\n controller.enqueue(W7_MAGIC.slice());\n return;\n }\n const next = iterator.next();\n if (next.done) {\n closed = true;\n controller.close();\n return;\n }\n for (const part of next.value) controller.enqueue(part);\n } catch (error) {\n closed = true;\n controller.error(error);\n }\n },\n cancel() {\n closed = true;\n iterator.return?.(void 0);\n }\n };\n return new ReadableStream(source, {\n highWaterMark: ENCODER_QUEUE_HWM\n });\n}\nasync function decodeWriteBatchStream(stream, options = {}) {\n let reader;\n try {\n reader = stream.getReader({ mode: \"byob\" });\n } catch {\n throw new Error(\"w7-frame: stream must be a byte-oriented ReadableStream\");\n }\n const buffer = new ExactByteReader(reader, options.signal);\n let handedOff = false;\n try {\n throwIfAborted(options.signal);\n const magic = await buffer.readExact(W7_MAGIC.length, \"magic\");\n if (!bytesEqual(magic, W7_MAGIC)) {\n const version = magic.length === 4 && magic[0] === 78 && magic[1] === 87 && magic[2] === 55 ? magic[3] : null;\n if (version !== null) {\n throw new Error(`w7-frame: unsupported protocol version ${version}; expected 3`);\n }\n throw new Error(`w7-frame: bad magic, expected NW7\\\\x03, got ${hex(magic)}`);\n }\n const beginEnvelope = await readEnvelope(buffer, \"batch-begin\");\n if (beginEnvelope.tag !== 1 /* BatchBegin */) {\n throw new Error(`w7-frame: first record must be batch-begin, got tag ${beginEnvelope.tag}`);\n }\n if (beginEnvelope.length > MAX_METADATA_BYTES) {\n throw new Error(\n `w7-frame: batch-begin length ${beginEnvelope.length} exceeds ${MAX_METADATA_BYTES}`\n );\n }\n const beginPayload = await buffer.readExact(beginEnvelope.length, \"batch-begin payload\");\n const begin = parseBatchBegin(beginPayload);\n const initialCheck = updateRecordCheck(CRC_SEED, beginEnvelope.header, beginPayload);\n handedOff = true;\n return {\n batchId: begin.id,\n mode: begin.mode,\n records: decodeRecords(stream, reader, buffer, options, initialCheck)\n };\n } catch (error) {\n if (!handedOff) await cancelReader(reader, error);\n throw error;\n }\n}\nasync function* decodeRecords(stream, reader, buffer, options, initialCheck) {\n const ownedPaths = new PathOwnership();\n const contentIds = /* @__PURE__ */ new Set();\n let active = null;\n let batchCheck = initialCheck;\n const summary = {\n recordCount: 1,\n pathCount: 0,\n deleteCount: 0,\n directoryCount: 0,\n fileCount: 0,\n chunkCount: 0,\n byteCount: 0\n };\n let completed = false;\n let failure = new DOMException(\"W7 consumer cancelled\", \"AbortError\");\n try {\n while (true) {\n throwIfAborted(options.signal);\n const envelope = await readEnvelope(buffer, \"record\");\n if (active && envelope.tag !== 5 /* FileChunk */ && envelope.tag !== 6 /* FileEnd */) {\n throw new Error(`w7-frame: file ${active.inode.path} ended without file-end`);\n }\n if (envelope.tag === 5 /* FileChunk */) {\n if (!active) throw new Error(\"w7-frame: file-chunk without active file\");\n const prefixLength = Math.min(envelope.length, 4 + MAX_CONTENT_ID_BYTES + 8);\n const idLengthBytes = await buffer.readExact(4, \"file-chunk content-id length\");\n const idLength = readU32LE(idLengthBytes, 0);\n if (idLength === 0 || idLength > MAX_CONTENT_ID_BYTES) {\n throw new Error(`w7-frame: invalid file-chunk content-id length ${idLength}`);\n }\n const remainingPrefixLength = idLength + 8;\n if (4 + remainingPrefixLength > prefixLength || 4 + remainingPrefixLength > envelope.length) {\n throw new Error(\"w7-frame: malformed file-chunk record length\");\n }\n const rest = await buffer.readExact(remainingPrefixLength, \"file-chunk header\");\n const contentId = decodeText(rest.subarray(0, idLength), \"file-chunk content id\");\n const chunkId = readU32LE(rest, idLength);\n const dataLength = readU32LE(rest, idLength + 4);\n if (envelope.length !== 4 + idLength + 8 + dataLength) {\n throw new Error(\"w7-frame: file-chunk payload length mismatch\");\n }\n if (contentId !== active.metadata.contentId) {\n throw new Error(`w7-frame: file-chunk content id ${contentId} does not own ${active.inode.path}`);\n }\n if (chunkId !== active.nextChunkId) {\n throw new Error(\n `w7-frame: ${active.inode.path}: expected chunk ${active.nextChunkId}, got ${chunkId}`\n );\n }\n if (chunkId >= active.inode.chunkCount) {\n throw new Error(`w7-frame: ${active.inode.path}: chunk ${chunkId} is out of range`);\n }\n const expectedBytes = Math.min(\n CHUNK_SIZE,\n active.inode.size - chunkId * CHUNK_SIZE\n );\n if (dataLength !== expectedBytes || dataLength > CHUNK_SIZE) {\n throw new Error(\n `w7-frame: ${active.inode.path}: chunk ${chunkId} has ${dataLength} bytes; expected ${expectedBytes}`\n );\n }\n const headerPayload = concatBytes(idLengthBytes, rest);\n let retention = null;\n try {\n retention = options.retainChunk ? await options.retainChunk(dataLength, options.signal) : noopRetention(dataLength);\n throwIfAborted(options.signal);\n const data = await buffer.readExact(dataLength, \"file-chunk data\");\n batchCheck = updateRecordCheck(batchCheck, envelope.header, headerPayload, data);\n active.check = crc32Update(active.check, data);\n active.nextChunkId++;\n active.receivedBytes += dataLength;\n summary.recordCount++;\n summary.chunkCount++;\n summary.byteCount += dataLength;\n const record = {\n type: \"file-chunk\",\n streamContentId: contentId,\n path: active.inode.path,\n chunkId,\n data,\n retention\n };\n retention = null;\n yield record;\n } finally {\n retention?.release();\n }\n continue;\n }\n if (envelope.length > MAX_METADATA_BYTES) {\n throw new Error(`w7-frame: metadata record length ${envelope.length} exceeds ${MAX_METADATA_BYTES}`);\n }\n const payload = await buffer.readExact(envelope.length, \"record payload\");\n if (envelope.tag !== 7 /* BatchEnd */) {\n batchCheck = updateRecordCheck(batchCheck, envelope.header, payload);\n summary.recordCount++;\n }\n switch (envelope.tag) {\n case 2 /* Delete */: {\n const metadata = parseDelete(payload);\n claimPath(ownedPaths, metadata.path);\n summary.pathCount++;\n summary.deleteCount++;\n yield { type: \"delete\", path: metadata.path };\n break;\n }\n case 3 /* Directory */: {\n const metadata = parseDirectory(payload);\n claimPath(ownedPaths, metadata.path);\n summary.pathCount++;\n summary.directoryCount++;\n yield { type: \"directory\", inode: directoryInode(metadata) };\n break;\n }\n case 4 /* FileBegin */: {\n const metadata = parseFileBegin(payload);\n claimPath(ownedPaths, metadata.path);\n if (contentIds.has(metadata.contentId)) {\n throw new Error(`w7-frame: duplicate stream content id ${metadata.contentId}`);\n }\n contentIds.add(metadata.contentId);\n const inode = fileInode(metadata);\n summary.pathCount++;\n summary.fileCount++;\n active = {\n metadata,\n inode,\n nextChunkId: 0,\n receivedBytes: 0,\n check: CRC_SEED\n };\n yield { type: \"file-begin\", streamContentId: metadata.contentId, inode };\n break;\n }\n case 6 /* FileEnd */: {\n if (!active) throw new Error(\"w7-frame: file-end without active file\");\n const metadata = parseFileEnd(payload);\n const actualCheck = crc32Finish(active.check);\n if (metadata.contentId !== active.metadata.contentId) {\n throw new Error(`w7-frame: file-end content id mismatch for ${active.inode.path}`);\n }\n if (metadata.size !== active.receivedBytes || metadata.size !== active.inode.size) {\n throw new Error(`w7-frame: file-end byte total mismatch for ${active.inode.path}`);\n }\n if (metadata.chunkCount !== active.nextChunkId || metadata.chunkCount !== active.inode.chunkCount) {\n throw new Error(`w7-frame: file-end chunk count mismatch for ${active.inode.path}`);\n }\n if (metadata.check !== actualCheck) {\n throw new Error(`w7-frame: file-end check mismatch for ${active.inode.path}`);\n }\n const record = {\n type: \"file-end\",\n streamContentId: metadata.contentId,\n path: active.inode.path,\n size: metadata.size,\n chunkCount: metadata.chunkCount,\n check: metadata.check\n };\n active = null;\n yield record;\n break;\n }\n case 7 /* BatchEnd */: {\n if (active) throw new Error(`w7-frame: batch-end while file ${active.inode.path} is active`);\n const actual = parseBatchEnd(payload);\n const expected = { ...summary, check: crc32Finish(batchCheck) };\n if (!sameSummary(actual, expected)) {\n throw new Error(\n `w7-frame: batch-end summary mismatch; expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`\n );\n }\n await buffer.ensureEof(stream);\n completed = true;\n yield { type: \"batch-end\", summary: actual };\n return;\n }\n case 1 /* BatchBegin */:\n throw new Error(\"w7-frame: duplicate batch-begin\");\n default:\n throw new Error(`w7-frame: unknown record tag ${envelope.tag}`);\n }\n }\n } catch (error) {\n failure = error;\n throw error;\n } finally {\n if (completed) {\n try {\n reader.releaseLock();\n } catch {\n }\n } else {\n await cancelReader(reader, failure);\n }\n }\n}\nfunction* encodeRecords(batchId, deletes, directories, files) {\n const state = {\n batchCheck: CRC_SEED,\n summary: {\n recordCount: 0,\n pathCount: 0,\n deleteCount: 0,\n directoryCount: 0,\n fileCount: 0,\n chunkCount: 0,\n byteCount: 0\n }\n };\n yield encodeMetadataRecord(1 /* BatchBegin */, { id: batchId, mode: MODE }, state);\n for (const path of deletes) {\n state.summary.pathCount++;\n state.summary.deleteCount++;\n yield encodeMetadataRecord(2 /* Delete */, { path }, state);\n }\n for (const inode of directories) {\n state.summary.pathCount++;\n state.summary.directoryCount++;\n yield encodeMetadataRecord(3 /* Directory */, {\n ...inodeMetadata(inode),\n kind: inode.kind\n }, state);\n }\n for (const file of files) {\n state.summary.pathCount++;\n state.summary.fileCount++;\n yield encodeMetadataRecord(4 /* FileBegin */, {\n ...inodeMetadata(file.inode),\n kind: file.inode.kind,\n contentId: file.contentId,\n size: file.inode.size,\n chunkCount: file.inode.chunkCount\n }, state);\n let fileCheck = CRC_SEED;\n for (const chunk of file.chunks) {\n const data = chunk.data;\n const contentBytes = new TextEncoder().encode(file.contentId);\n const prefix = new Uint8Array(4 + contentBytes.length + 8);\n writeU32LE(prefix, 0, contentBytes.length);\n prefix.set(contentBytes, 4);\n writeU32LE(prefix, 4 + contentBytes.length, chunk.chunkId);\n writeU32LE(prefix, 8 + contentBytes.length, data.byteLength);\n const header = recordHeader(5 /* FileChunk */, prefix.byteLength + data.byteLength);\n state.batchCheck = updateRecordCheck(state.batchCheck, header, prefix, data);\n state.summary.recordCount++;\n state.summary.chunkCount++;\n state.summary.byteCount += data.byteLength;\n fileCheck = crc32Update(fileCheck, data);\n yield [concatBytes(header, prefix), data];\n }\n yield encodeMetadataRecord(6 /* FileEnd */, {\n contentId: file.contentId,\n size: file.inode.size,\n chunkCount: file.inode.chunkCount,\n check: crc32Finish(fileCheck)\n }, state);\n }\n const end = {\n ...state.summary,\n check: crc32Finish(state.batchCheck)\n };\n yield encodeMetadataRecord(7 /* BatchEnd */, end);\n}\nfunction encodeMetadataRecord(tag, value, state) {\n const payload = new TextEncoder().encode(JSON.stringify(value));\n if (payload.byteLength > MAX_METADATA_BYTES) {\n throw new Error(`w7-frame: metadata record exceeds ${MAX_METADATA_BYTES} bytes`);\n }\n const header = recordHeader(tag, payload.byteLength);\n if (state && tag !== 7 /* BatchEnd */) {\n state.batchCheck = updateRecordCheck(state.batchCheck, header, payload);\n state.summary.recordCount++;\n }\n return [concatBytes(header, payload)];\n}\nfunction preparePayload(payload, batchId) {\n if (!payload || !Array.isArray(payload.inodes) || !Array.isArray(payload.chunks)) {\n throw new Error(\"w7-frame: payload must contain inode and chunk arrays\");\n }\n const ownedPaths = new PathOwnership();\n const deletes = [...payload.deletePaths ?? []];\n for (const path of deletes) claimPath(ownedPaths, canonicalPath(path, \"delete path\"));\n const chunksByPath = /* @__PURE__ */ new Map();\n for (const chunk of payload.chunks) {\n const path = canonicalPath(chunk.path, \"chunk path\");\n const list = chunksByPath.get(path);\n if (list) list.push(chunk);\n else chunksByPath.set(path, [chunk]);\n }\n const directories = [];\n const files = [];\n let fileIndex = 0;\n for (const inode of payload.inodes) {\n const path = canonicalPath(inode.path, \"inode path\");\n if (path !== inode.path) throw new Error(`w7-frame: noncanonical inode path ${inode.path}`);\n claimPath(ownedPaths, path);\n const normalizedInode = normalizeInode(inode);\n const fileChunks = chunksByPath.get(path) ?? [];\n if (normalizedInode.kind === \"directory\") {\n if (fileChunks.length > 0) throw new Error(`w7-frame: directory ${path} has chunks`);\n directories.push(normalizedInode);\n } else {\n validateChunks(normalizedInode, fileChunks);\n files.push({\n inode: normalizedInode,\n contentId: `${batchId}:${fileIndex++}`,\n chunks: fileChunks\n });\n }\n chunksByPath.delete(path);\n }\n if (chunksByPath.size > 0) {\n throw new Error(`w7-frame: chunk has no inode: ${chunksByPath.keys().next().value}`);\n }\n return { deletes, directories, files };\n}\nfunction parseBatchBegin(bytes) {\n const value = parseObject(bytes, \"batch-begin\", [\"id\", \"mode\"]);\n const id = boundedString(value.id, \"batch id\", MAX_BATCH_ID_BYTES);\n if (value.mode !== MODE) throw new Error(`w7-frame: unsupported batch mode ${String(value.mode)}`);\n return { id, mode: MODE };\n}\nfunction parseDelete(bytes) {\n const value = parseObject(bytes, \"delete\", [\"path\"]);\n return { path: canonicalPath(value.path, \"delete path\") };\n}\nfunction parseDirectory(bytes) {\n const value = parseObject(bytes, \"directory\", [\"path\", \"kind\", \"mtime\", \"mode\"], [\"atime\"]);\n if (value.kind !== \"directory\") {\n throw new Error(`w7-frame: unsupported directory kind ${String(value.kind)}`);\n }\n return { ...parseInodeMetadata(value, \"directory\"), kind: \"directory\" };\n}\nfunction parseFileBegin(bytes) {\n const value = parseObject(\n bytes,\n \"file-begin\",\n [\"path\", \"kind\", \"contentId\", \"size\", \"chunkCount\", \"mtime\", \"mode\"],\n [\"atime\"]\n );\n const base = parseInodeMetadata(value, \"file-begin\");\n if (value.kind !== \"file\" && value.kind !== \"symlink\") {\n throw new Error(`w7-frame: unsupported file-begin kind ${String(value.kind)}`);\n }\n const contentId = boundedString(value.contentId, \"stream content id\", MAX_CONTENT_ID_BYTES);\n if (!/^[A-Za-z0-9._:-]+$/.test(contentId)) {\n throw new Error(`w7-frame: invalid stream content id ${contentId}`);\n }\n const size = safeInteger(value.size, \"file size\");\n const chunkCount = u32(value.chunkCount, \"file chunk count\");\n const expected = size === 0 ? 0 : Math.ceil(size / CHUNK_SIZE);\n if (chunkCount !== expected) {\n throw new Error(`w7-frame: ${base.path}: expected ${expected} chunks, got ${chunkCount}`);\n }\n return { ...base, kind: value.kind, contentId, size, chunkCount };\n}\nfunction parseFileEnd(bytes) {\n const value = parseObject(bytes, \"file-end\", [\"contentId\", \"size\", \"chunkCount\", \"check\"]);\n return {\n contentId: boundedString(value.contentId, \"stream content id\", MAX_CONTENT_ID_BYTES),\n size: safeInteger(value.size, \"file-end size\"),\n chunkCount: u32(value.chunkCount, \"file-end chunk count\"),\n check: u32(value.check, \"file-end check\")\n };\n}\nfunction parseBatchEnd(bytes) {\n const keys = [\n \"recordCount\",\n \"pathCount\",\n \"deleteCount\",\n \"directoryCount\",\n \"fileCount\",\n \"chunkCount\",\n \"byteCount\",\n \"check\"\n ];\n const value = parseObject(bytes, \"batch-end\", keys);\n return {\n recordCount: safeInteger(value.recordCount, \"batch record count\"),\n pathCount: safeInteger(value.pathCount, \"batch path count\"),\n deleteCount: safeInteger(value.deleteCount, \"batch delete count\"),\n directoryCount: safeInteger(value.directoryCount, \"batch directory count\"),\n fileCount: safeInteger(value.fileCount, \"batch file count\"),\n chunkCount: safeInteger(value.chunkCount, \"batch chunk count\"),\n byteCount: safeInteger(value.byteCount, \"batch byte count\"),\n check: u32(value.check, \"batch check\")\n };\n}\nfunction parseInodeMetadata(value, label) {\n return {\n path: canonicalPath(value.path, `${label} path`),\n ...value.atime === void 0 ? {} : { atime: safeInteger(value.atime, `${label} atime`) },\n mtime: safeInteger(value.mtime, `${label} mtime`),\n mode: u32(value.mode, `${label} mode`)\n };\n}\nfunction parseObject(bytes, label, required, optional = []) {\n let value;\n try {\n value = JSON.parse(decodeText(bytes, label));\n } catch (error) {\n if (error instanceof Error && error.message.startsWith(\"w7-frame:\")) throw error;\n throw new Error(`w7-frame: invalid ${label} JSON: ${errorMessage(error)}`);\n }\n if (!isObject(value) || Array.isArray(value)) throw new Error(`w7-frame: ${label} must be an object`);\n const allowed = /* @__PURE__ */ new Set([...required, ...optional]);\n for (const key of required) {\n if (!Object.hasOwn(value, key)) throw new Error(`w7-frame: ${label} missing ${key}`);\n }\n for (const key of Object.keys(value)) {\n if (!allowed.has(key)) throw new Error(`w7-frame: ${label} has unknown field ${key}`);\n }\n return value;\n}\nfunction normalizeInode(inode) {\n canonicalPath(inode.path, \"inode path\");\n if (inode.parentPath !== parentPath(inode.path)) {\n throw new Error(`w7-frame: ${inode.path}: noncanonical parent path ${inode.parentPath}`);\n }\n safeInteger(inode.size, `${inode.path} size`);\n u32(inode.chunkCount, `${inode.path} chunk count`);\n safeInteger(inode.mtime, `${inode.path} mtime`);\n if (inode.atime !== void 0) safeInteger(inode.atime, `${inode.path} atime`);\n u32(inode.mode, `${inode.path} mode`);\n const rawKind = inode.kind ?? (inode.isDir ? \"directory\" : \"file\");\n if (rawKind !== \"file\" && rawKind !== \"directory\" && rawKind !== \"symlink\") {\n throw new Error(`w7-frame: unsupported inode kind ${String(rawKind)}`);\n }\n const kind = rawKind;\n if (kind === \"directory\" && !inode.isDir) {\n throw new Error(`w7-frame: directory inode ${inode.path} must be a directory`);\n }\n if (kind !== \"directory\" && inode.isDir) {\n throw new Error(`w7-frame: ${kind} inode ${inode.path} cannot be a directory`);\n }\n if (kind === \"directory\" && (inode.size !== 0 || inode.chunkCount !== 0)) {\n throw new Error(`w7-frame: directory ${inode.path} must have zero size and chunks`);\n }\n if (kind !== \"directory\") {\n const expected = inode.size === 0 ? 0 : Math.ceil(inode.size / CHUNK_SIZE);\n if (inode.chunkCount !== expected) {\n throw new Error(`w7-frame: ${inode.path}: expected ${expected} chunks, got ${inode.chunkCount}`);\n }\n return { ...inode, kind, isDir: false };\n }\n return { ...inode, kind, isDir: true };\n}\nfunction validateChunks(inode, chunks) {\n if (chunks.length !== inode.chunkCount) {\n throw new Error(`w7-frame: ${inode.path}: expected ${inode.chunkCount} chunks, got ${chunks.length}`);\n }\n chunks.sort((left, right) => left.chunkId - right.chunkId);\n for (let index = 0; index < chunks.length; index++) {\n const chunk = chunks[index];\n if (chunk.chunkId !== index) {\n throw new Error(`w7-frame: ${inode.path}: expected chunk ${index}, got ${chunk.chunkId}`);\n }\n const expected = Math.min(CHUNK_SIZE, inode.size - index * CHUNK_SIZE);\n if (!(chunk.data instanceof Uint8Array) || chunk.data.byteLength !== expected) {\n throw new Error(`w7-frame: ${inode.path}: chunk ${index} must contain ${expected} bytes`);\n }\n }\n}\nfunction directoryInode(metadata) {\n return {\n path: metadata.path,\n parentPath: parentPath(metadata.path),\n kind: metadata.kind,\n isDir: true,\n size: 0,\n atime: metadata.atime,\n mtime: metadata.mtime,\n mode: metadata.mode,\n chunkCount: 0\n };\n}\nfunction fileInode(metadata) {\n return {\n path: metadata.path,\n parentPath: parentPath(metadata.path),\n kind: metadata.kind,\n isDir: false,\n size: metadata.size,\n atime: metadata.atime,\n mtime: metadata.mtime,\n mode: metadata.mode,\n chunkCount: metadata.chunkCount\n };\n}\nfunction inodeMetadata(inode) {\n return {\n path: inode.path,\n ...inode.atime === void 0 ? {} : { atime: inode.atime },\n mtime: inode.mtime,\n mode: inode.mode\n };\n}\nfunction canonicalPath(value, label) {\n const path = boundedString(value, label, MAX_PATH_BYTES);\n if (path.includes(\"\\0\")) throw new Error(`w7-frame: ${label} contains NUL`);\n const normalized = normalizePath(path);\n if (!path || normalized !== path) throw new Error(`w7-frame: noncanonical ${label}: ${path}`);\n return path;\n}\nvar PathOwnership = class {\n paths = /* @__PURE__ */ new Set();\n pathBytes = 0;\n claim(path) {\n if (this.paths.has(path)) throw new Error(`w7-frame: duplicate path ownership: ${path}`);\n if (this.paths.size >= W7_MAX_PATHS_PER_BATCH) {\n throw new Error(`w7-frame: batch exceeds ${W7_MAX_PATHS_PER_BATCH} owned paths`);\n }\n const nextPathBytes = this.pathBytes + new TextEncoder().encode(path).byteLength;\n if (nextPathBytes > W7_MAX_OWNED_PATH_BYTES) {\n throw new Error(\n `w7-frame: owned path bytes exceed ${W7_MAX_OWNED_PATH_BYTES}`\n );\n }\n this.paths.add(path);\n this.pathBytes = nextPathBytes;\n }\n};\nfunction claimPath(paths, path) {\n paths.claim(path);\n}\nfunction normalizePath(path) {\n const out = [];\n for (const segment of path.split(\"/\")) {\n if (segment === \"..\") {\n if (out.length > 0) out.pop();\n } else if (segment !== \"\" && segment !== \".\") {\n out.push(segment);\n }\n }\n return out.join(\"/\");\n}\nfunction parentPath(path) {\n const index = path.lastIndexOf(\"/\");\n return index < 0 ? \"\" : path.slice(0, index);\n}\nfunction boundedString(value, label, maxBytes) {\n if (typeof value !== \"string\" || value.length === 0) {\n throw new Error(`w7-frame: ${label} must be a non-empty string`);\n }\n const length = new TextEncoder().encode(value).byteLength;\n if (length > maxBytes) throw new Error(`w7-frame: ${label} exceeds ${maxBytes} bytes`);\n return value;\n}\nfunction safeInteger(value, label) {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new Error(`w7-frame: ${label} must be a non-negative safe integer`);\n }\n return value;\n}\nfunction u32(value, label) {\n const integer = safeInteger(value, label);\n if (integer > 4294967295) throw new Error(`w7-frame: ${label} exceeds uint32`);\n return integer;\n}\nfunction sameSummary(left, right) {\n return left.recordCount === right.recordCount && left.pathCount === right.pathCount && left.deleteCount === right.deleteCount && left.directoryCount === right.directoryCount && left.fileCount === right.fileCount && left.chunkCount === right.chunkCount && left.byteCount === right.byteCount && left.check === right.check;\n}\nasync function readEnvelope(buffer, label) {\n const header = await buffer.readExact(5, `${label} header`);\n return { tag: header[0], length: readU32LE(header, 1), header };\n}\nfunction recordHeader(tag, length) {\n const header = new Uint8Array(5);\n header[0] = tag;\n writeU32LE(header, 1, length);\n return header;\n}\nfunction writeU32LE(out, offset, value) {\n out[offset] = value & 255;\n out[offset + 1] = value >>> 8 & 255;\n out[offset + 2] = value >>> 16 & 255;\n out[offset + 3] = value >>> 24 & 255;\n}\nfunction readU32LE(bytes, offset) {\n return (bytes[offset] | bytes[offset + 1] << 8 | bytes[offset + 2] << 16 | bytes[offset + 3] << 24) >>> 0;\n}\nfunction updateRecordCheck(seed, ...parts) {\n let check = seed;\n for (const part of parts) check = crc32Update(check, part);\n return check;\n}\nvar CRC_SEED = 4294967295;\nvar crcTable = null;\nfunction crc32Update(check, bytes) {\n crcTable ??= createCrcTable();\n const table = crcTable;\n let value = check;\n for (const byte of bytes) value = table[(value ^ byte) & 255] ^ value >>> 8;\n return value >>> 0;\n}\nfunction crc32Finish(check) {\n return (check ^ 4294967295) >>> 0;\n}\nfunction createCrcTable() {\n const table = new Uint32Array(256);\n for (let index = 0; index < table.length; index++) {\n let value = index;\n for (let bit = 0; bit < 8; bit++) {\n value = (value & 1) !== 0 ? 3988292384 ^ value >>> 1 : value >>> 1;\n }\n table[index] = value >>> 0;\n }\n return table;\n}\nfunction noopRetention(bytes) {\n return { bytes, release() {\n } };\n}\nfunction decodeText(bytes, label) {\n try {\n return new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: false }).decode(bytes);\n } catch (error) {\n throw new Error(`w7-frame: invalid UTF-8 in ${label}: ${errorMessage(error)}`);\n }\n}\nfunction concatBytes(...parts) {\n const output = new Uint8Array(parts.reduce((total, part) => total + part.byteLength, 0));\n let offset = 0;\n for (const part of parts) {\n output.set(part, offset);\n offset += part.byteLength;\n }\n return output;\n}\nfunction bytesEqual(left, right) {\n return left.length === right.length && left.every((byte, index) => byte === right[index]);\n}\nfunction hex(bytes) {\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\" \");\n}\nfunction isObject(value) {\n return typeof value === \"object\" && value !== null;\n}\nfunction errorMessage(error) {\n return error instanceof Error ? error.message : String(error);\n}\nfunction throwIfAborted(signal) {\n if (!signal?.aborted) return;\n throw new DOMException(\n signal.reason instanceof Error ? signal.reason.message : String(signal.reason ?? \"Aborted\"),\n \"AbortError\"\n );\n}\nasync function cancelReader(reader, reason) {\n try {\n await reader.cancel(reason);\n } catch {\n }\n try {\n reader.releaseLock();\n } catch {\n }\n}\nvar ExactByteReader = class {\n constructor(reader, signal) {\n this.reader = reader;\n this.signal = signal;\n }\n reader;\n signal;\n done = false;\n async read(read, cancel) {\n throwIfAborted(this.signal);\n const abort = () => {\n void cancel().catch(() => {\n });\n };\n this.signal?.addEventListener(\"abort\", abort, { once: true });\n try {\n const result = await read();\n throwIfAborted(this.signal);\n return result;\n } finally {\n this.signal?.removeEventListener(\"abort\", abort);\n }\n }\n async readExact(length, label) {\n if (length === 0) return new Uint8Array(0);\n const output = new Uint8Array(length);\n let offset = 0;\n while (offset < length) {\n if (this.done) {\n throw new Error(\n `w7-frame: stream ended ${offset} bytes into expected ${length}-byte ${label}`\n );\n }\n const next = await this.read(\n () => this.reader.read(new Uint8Array(length - offset)),\n () => this.reader.cancel(this.signal?.reason)\n );\n if (next.done) this.done = true;\n else if (next.value.byteLength > 0) {\n output.set(next.value, offset);\n offset += next.value.byteLength;\n }\n }\n return output;\n }\n async ensureEof(stream) {\n if (this.done) return;\n this.reader.releaseLock();\n const reader = stream.getReader();\n try {\n const next = await this.read(() => reader.read(), () => reader.cancel(this.signal?.reason));\n if (!next.done && next.value.byteLength > 0) {\n await reader.cancel(new Error(\"w7-frame: trailing bytes after batch-end\"));\n throw new Error(\"w7-frame: trailing bytes after batch-end\");\n }\n this.done = true;\n } finally {\n try {\n reader.releaseLock();\n } catch {\n }\n }\n }\n};";
22
+ export const TAR_STREAM_PREAMBLE = "var MAX_FILE_BYTES = 2e7;\nfunction canonicalTarName(name) {\n const out = [];\n for (const seg of name.split(\"/\")) {\n if (seg === \"..\") {\n if (out.length === 0) return \"\";\n out.pop();\n } else if (seg !== \"\" && seg !== \".\") {\n out.push(seg);\n }\n }\n return out.join(\"/\");\n}\nfunction parseTarHeader(block) {\n if (block[0] === 0) return null;\n let name = \"\";\n for (let i = 0; i < 100 && block[i] !== 0; i++) {\n name += String.fromCharCode(block[i]);\n }\n let prefix = \"\";\n for (let i = 345; i < 500 && block[i] !== 0; i++) {\n prefix += String.fromCharCode(block[i]);\n }\n if (prefix) name = prefix + \"/\" + name;\n name = canonicalTarName(name);\n let sizeStr = \"\";\n for (let i = 124; i < 136 && block[i] !== 0; i++) {\n sizeStr += String.fromCharCode(block[i]);\n }\n const size = parseInt(sizeStr.trim(), 8) || 0;\n const typeFlag = block[156];\n return { name, size, typeFlag };\n}\nasync function* readableStreamToAsyncIterable(rs) {\n const reader = rs.getReader();\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) return;\n if (value && value.length > 0) yield value;\n }\n } finally {\n try {\n reader.releaseLock();\n } catch {\n }\n }\n}\nasync function* streamTarEntries(source, onSkip) {\n let carry = new Uint8Array(0);\n let state = { kind: \"header\" };\n function concat(a, b) {\n if (a.length === 0) return b;\n if (b.length === 0) return a;\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n }\n for await (const chunkRaw of source) {\n let buf = concat(carry, chunkRaw);\n let cursor = 0;\n while (true) {\n if (state.kind === \"header\") {\n if (buf.length - cursor < 512) break;\n const header = buf.subarray(cursor, cursor + 512);\n const parsed = parseTarHeader(header);\n cursor += 512;\n if (!parsed) return;\n const { name, size, typeFlag } = parsed;\n const pad = size === 0 ? 0 : (512 - size % 512) % 512;\n const isRegularFile = typeFlag === 48 || typeFlag === 0;\n if (size === 0) {\n if (isRegularFile && name) {\n yield { name, data: new Uint8Array(0) };\n }\n state = { kind: \"header\" };\n continue;\n }\n if (!isRegularFile || !name || size > MAX_FILE_BYTES) {\n if (onSkip) {\n const reason = !isRegularFile ? \"non-regular\" : !name ? \"no-name\" : \"too-large\";\n try {\n onSkip(name, size, reason);\n } catch {\n }\n }\n state = { kind: \"skip\", remaining: size + pad };\n continue;\n }\n state = {\n kind: \"file\",\n name,\n remaining: size,\n fileBuf: new Uint8Array(size),\n fileOffset: 0,\n pad,\n skip: false\n };\n continue;\n }\n if (state.kind === \"file\") {\n const avail2 = buf.length - cursor;\n if (avail2 === 0) break;\n if (state.remaining > 0) {\n const take2 = Math.min(state.remaining, avail2);\n state.fileBuf.set(buf.subarray(cursor, cursor + take2), state.fileOffset);\n state.fileOffset += take2;\n state.remaining -= take2;\n cursor += take2;\n if (state.remaining > 0) break;\n }\n if (state.pad > 0) {\n const avail22 = buf.length - cursor;\n if (avail22 === 0) break;\n const take2 = Math.min(state.pad, avail22);\n state.pad -= take2;\n cursor += take2;\n if (state.pad > 0) break;\n }\n yield { name: state.name, data: state.fileBuf };\n state = { kind: \"header\" };\n continue;\n }\n const avail = buf.length - cursor;\n if (avail === 0) break;\n const take = Math.min(state.remaining, avail);\n cursor += take;\n state.remaining -= take;\n if (state.remaining > 0) break;\n state = { kind: \"header\" };\n }\n if (cursor >= buf.length) {\n carry = new Uint8Array(0);\n } else if (cursor === 0) {\n carry = buf;\n } else {\n carry = buf.slice(cursor);\n }\n }\n}\nasync function* streamPackageEntries(source, onSkip) {\n let prefix = null;\n for await (const entry of streamTarEntries(source, onSkip)) {\n if (prefix === null) {\n prefix = entry.name.split(\"/\", 1)[0];\n }\n if (entry.name === prefix) continue;\n if (!entry.name.startsWith(prefix + \"/\")) {\n throw new Error(\n `package tarball is not single-rooted: entry \"${entry.name}\" sits outside \"${prefix}/\"`\n );\n }\n yield { name: entry.name.slice(prefix.length + 1), data: entry.data };\n }\n}";
23
+ export const W7_FRAME_PREAMBLE = "var CRC_NATIVE_MIN_BYTES = 128;\nvar nativeCrc32 = (() => {\n try {\n const crc322 = globalThis.process?.getBuiltinModule?.(\"node:zlib\")?.crc32;\n return typeof crc322 === \"function\" ? crc322 : null;\n } catch {\n return null;\n }\n})();\nvar crcTables = null;\nfunction createCrcTables() {\n const table = new Uint32Array(256 * 8);\n for (let index = 0; index < 256; index++) {\n let value = index;\n for (let bit = 0; bit < 8; bit++) value = (value & 1) !== 0 ? 3988292384 ^ value >>> 1 : value >>> 1;\n table[index] = value;\n }\n for (let index = 0; index < 256; index++) {\n let value = table[index];\n for (let k = 1; k < 8; k++) {\n value = table[value & 255] ^ value >>> 8;\n table[k * 256 + index] = value;\n }\n }\n return table;\n}\nfunction crc32(bytes, previous = 0) {\n if (nativeCrc32 !== null && bytes.length >= CRC_NATIVE_MIN_BYTES) return nativeCrc32(bytes, previous) >>> 0;\n const t = crcTables ??= createCrcTables();\n let value = ~previous;\n const length = bytes.length;\n const whole = length - (length & 7);\n let i = 0;\n for (; i < whole; i += 8) {\n const low = value ^ (bytes[i] | bytes[i + 1] << 8 | bytes[i + 2] << 16 | bytes[i + 3] << 24);\n const high = bytes[i + 4] | bytes[i + 5] << 8 | bytes[i + 6] << 16 | bytes[i + 7] << 24;\n value = t[1792 + (low & 255)] ^ t[1536 + (low >>> 8 & 255)] ^ t[1280 + (low >>> 16 & 255)] ^ t[1024 + (low >>> 24)] ^ t[768 + (high & 255)] ^ t[512 + (high >>> 8 & 255)] ^ t[256 + (high >>> 16 & 255)] ^ t[high >>> 24];\n }\n for (; i < length; i++) value = t[(value ^ bytes[i]) & 255] ^ value >>> 8;\n return ~value >>> 0;\n}\n\nvar CHUNK_SIZE = 65536;\nvar MAX_TX_BLOB_BYTES = 1 * 1024 * 1024;\nvar SQLITE_MAX_STATEMENT_BYTES = 100 * 1024;\nvar MAX_RPC_SAFE_PAYLOAD_BYTES = 28 * 1024 * 1024;\nvar ONE_SHOT_MODULE_MAP_MAX_BYTES = 18 * 1024 * 1024;\nvar SUPERVISOR_HEAP_CEILING_BYTES = 64 * 1024 * 1024;\nvar FACET_OWN_WRITE_MEMORY_BYTES = 32 * 1024 * 1024;\nvar SUPERVISOR_IN_FLIGHT_ALLOCATION_BUDGET_BYTES = 40 * 1024 * 1024;\nvar SUPERVISOR_READ_RESERVE_BYTES = 1024 * 1024;\nvar MAX_GLOBAL_WRITE_STREAM_CREDIT_BYTES = 8 * 1024 * 1024;\n\nvar W7_MAGIC = new Uint8Array([78, 87, 55, 3]);\nvar ENCODER_QUEUE_HWM = 0;\nvar MAX_METADATA_BYTES = 64 * 1024;\nvar MAX_PATH_BYTES = 64 * 1024;\nvar MAX_BATCH_ID_BYTES = 128;\nvar MAX_CONTENT_ID_BYTES = 256;\nvar W7_MAX_PATHS_PER_BATCH = 128;\nvar W7_MAX_OWNED_PATH_BYTES = 64 * 1024;\nvar W7_MAX_RECORD_BYTES = 5 + 4 + MAX_CONTENT_ID_BYTES + 8 + CHUNK_SIZE;\nvar MODE = \"path-atomic-committed-prefix\";\nfunction encodeWriteBatchStream(payload) {\n const batchId = crypto.randomUUID();\n const { deletes, directories, files } = preparePayload(payload, batchId);\n const iterator = encodeRecords(batchId, deletes, directories, files);\n let closed = false;\n let magicEmitted = false;\n const source = {\n type: \"bytes\",\n pull(controller) {\n if (closed) return;\n try {\n if (!magicEmitted) {\n magicEmitted = true;\n controller.enqueue(W7_MAGIC.slice());\n return;\n }\n const next = iterator.next();\n if (next.done) {\n closed = true;\n controller.close();\n return;\n }\n for (const part of next.value) controller.enqueue(part);\n } catch (error) {\n closed = true;\n controller.error(error);\n }\n },\n cancel() {\n closed = true;\n iterator.return?.(void 0);\n }\n };\n return new ReadableStream(source, {\n highWaterMark: ENCODER_QUEUE_HWM\n });\n}\nasync function decodeWriteBatchStream(stream, options = {}) {\n let reader;\n try {\n reader = stream.getReader({ mode: \"byob\" });\n } catch {\n throw new Error(\"w7-frame: stream must be a byte-oriented ReadableStream\");\n }\n const buffer = new ExactByteReader(reader, options.signal);\n let handedOff = false;\n try {\n throwIfAborted(options.signal);\n const magic = await buffer.readExact(W7_MAGIC.length, \"magic\");\n if (!bytesEqual(magic, W7_MAGIC)) {\n const version = magic.length === 4 && magic[0] === 78 && magic[1] === 87 && magic[2] === 55 ? magic[3] : null;\n if (version !== null) {\n throw new Error(`w7-frame: unsupported protocol version ${version}; expected 3`);\n }\n throw new Error(`w7-frame: bad magic, expected NW7\\\\x03, got ${hex(magic)}`);\n }\n const beginEnvelope = await readEnvelope(buffer, \"batch-begin\");\n if (beginEnvelope.tag !== 1 ) {\n throw new Error(`w7-frame: first record must be batch-begin, got tag ${beginEnvelope.tag}`);\n }\n if (beginEnvelope.length > MAX_METADATA_BYTES) {\n throw new Error(\n `w7-frame: batch-begin length ${beginEnvelope.length} exceeds ${MAX_METADATA_BYTES}`\n );\n }\n const beginPayload = await buffer.readExact(beginEnvelope.length, \"batch-begin payload\");\n const begin = parseBatchBegin(beginPayload);\n const initialCheck = updateRecordCheck(0, beginEnvelope.header, beginPayload);\n handedOff = true;\n return {\n batchId: begin.id,\n mode: begin.mode,\n records: decodeRecords(stream, reader, buffer, options, initialCheck)\n };\n } catch (error) {\n if (!handedOff) await cancelReader(reader, error);\n throw error;\n }\n}\nasync function* decodeRecords(stream, reader, buffer, options, initialCheck) {\n const ownedPaths = new PathOwnership();\n const contentIds = new Set();\n let active = null;\n let batchCheck = initialCheck;\n const summary = {\n recordCount: 1,\n pathCount: 0,\n deleteCount: 0,\n directoryCount: 0,\n fileCount: 0,\n chunkCount: 0,\n byteCount: 0\n };\n let completed = false;\n let failure = new DOMException(\"W7 consumer cancelled\", \"AbortError\");\n try {\n while (true) {\n throwIfAborted(options.signal);\n const envelope = await readEnvelope(buffer, \"record\");\n if (active && envelope.tag !== 5 && envelope.tag !== 6 ) {\n throw new Error(`w7-frame: file ${active.inode.path} ended without file-end`);\n }\n if (envelope.tag === 5 ) {\n if (!active) throw new Error(\"w7-frame: file-chunk without active file\");\n const prefixLength = Math.min(envelope.length, 4 + MAX_CONTENT_ID_BYTES + 8);\n const idLengthBytes = await buffer.readExact(4, \"file-chunk content-id length\");\n const idLength = readU32LE(idLengthBytes, 0);\n if (idLength === 0 || idLength > MAX_CONTENT_ID_BYTES) {\n throw new Error(`w7-frame: invalid file-chunk content-id length ${idLength}`);\n }\n const remainingPrefixLength = idLength + 8;\n if (4 + remainingPrefixLength > prefixLength || 4 + remainingPrefixLength > envelope.length) {\n throw new Error(\"w7-frame: malformed file-chunk record length\");\n }\n const rest = await buffer.readExact(remainingPrefixLength, \"file-chunk header\");\n const contentId = decodeText(rest.subarray(0, idLength), \"file-chunk content id\");\n const chunkId = readU32LE(rest, idLength);\n const dataLength = readU32LE(rest, idLength + 4);\n if (envelope.length !== 4 + idLength + 8 + dataLength) {\n throw new Error(\"w7-frame: file-chunk payload length mismatch\");\n }\n if (contentId !== active.metadata.contentId) {\n throw new Error(`w7-frame: file-chunk content id ${contentId} does not own ${active.inode.path}`);\n }\n if (chunkId !== active.nextChunkId) {\n throw new Error(\n `w7-frame: ${active.inode.path}: expected chunk ${active.nextChunkId}, got ${chunkId}`\n );\n }\n if (chunkId >= active.inode.chunkCount) {\n throw new Error(`w7-frame: ${active.inode.path}: chunk ${chunkId} is out of range`);\n }\n const expectedBytes = Math.min(\n CHUNK_SIZE,\n active.inode.size - chunkId * CHUNK_SIZE\n );\n if (dataLength !== expectedBytes || dataLength > CHUNK_SIZE) {\n throw new Error(\n `w7-frame: ${active.inode.path}: chunk ${chunkId} has ${dataLength} bytes; expected ${expectedBytes}`\n );\n }\n const headerPayload = concatBytes(idLengthBytes, rest);\n let retention = null;\n try {\n retention = options.retainChunk ? await options.retainChunk(dataLength, options.signal) : noopRetention(dataLength);\n throwIfAborted(options.signal);\n const data = await buffer.readExact(dataLength, \"file-chunk data\");\n batchCheck = updateRecordCheck(batchCheck, envelope.header, headerPayload, data);\n active.check = crc32(data, active.check);\n active.nextChunkId++;\n active.receivedBytes += dataLength;\n summary.recordCount++;\n summary.chunkCount++;\n summary.byteCount += dataLength;\n const record = {\n type: \"file-chunk\",\n streamContentId: contentId,\n path: active.inode.path,\n chunkId,\n data,\n retention\n };\n retention = null;\n yield record;\n } finally {\n retention?.release();\n }\n continue;\n }\n if (envelope.length > MAX_METADATA_BYTES) {\n throw new Error(`w7-frame: metadata record length ${envelope.length} exceeds ${MAX_METADATA_BYTES}`);\n }\n const payload = await buffer.readExact(envelope.length, \"record payload\");\n if (envelope.tag !== 7 ) {\n batchCheck = updateRecordCheck(batchCheck, envelope.header, payload);\n summary.recordCount++;\n }\n switch (envelope.tag) {\n case 2 : {\n const metadata = parseDelete(payload);\n claimPath(ownedPaths, metadata.path);\n summary.pathCount++;\n summary.deleteCount++;\n yield { type: \"delete\", path: metadata.path };\n break;\n }\n case 3 : {\n const metadata = parseDirectory(payload);\n claimPath(ownedPaths, metadata.path);\n summary.pathCount++;\n summary.directoryCount++;\n yield { type: \"directory\", inode: directoryInode(metadata) };\n break;\n }\n case 4 : {\n const metadata = parseFileBegin(payload);\n claimPath(ownedPaths, metadata.path);\n if (contentIds.has(metadata.contentId)) {\n throw new Error(`w7-frame: duplicate stream content id ${metadata.contentId}`);\n }\n contentIds.add(metadata.contentId);\n const inode = fileInode(metadata);\n summary.pathCount++;\n summary.fileCount++;\n active = {\n metadata,\n inode,\n nextChunkId: 0,\n receivedBytes: 0,\n check: 0\n };\n yield { type: \"file-begin\", streamContentId: metadata.contentId, inode };\n break;\n }\n case 6 : {\n if (!active) throw new Error(\"w7-frame: file-end without active file\");\n const metadata = parseFileEnd(payload);\n const actualCheck = active.check;\n if (metadata.contentId !== active.metadata.contentId) {\n throw new Error(`w7-frame: file-end content id mismatch for ${active.inode.path}`);\n }\n if (metadata.size !== active.receivedBytes || metadata.size !== active.inode.size) {\n throw new Error(`w7-frame: file-end byte total mismatch for ${active.inode.path}`);\n }\n if (metadata.chunkCount !== active.nextChunkId || metadata.chunkCount !== active.inode.chunkCount) {\n throw new Error(`w7-frame: file-end chunk count mismatch for ${active.inode.path}`);\n }\n if (metadata.check !== actualCheck) {\n throw new Error(`w7-frame: file-end check mismatch for ${active.inode.path}`);\n }\n const record = {\n type: \"file-end\",\n streamContentId: metadata.contentId,\n path: active.inode.path,\n size: metadata.size,\n chunkCount: metadata.chunkCount,\n check: metadata.check\n };\n active = null;\n yield record;\n break;\n }\n case 7 : {\n if (active) throw new Error(`w7-frame: batch-end while file ${active.inode.path} is active`);\n const actual = parseBatchEnd(payload);\n const expected = { ...summary, check: batchCheck };\n if (!sameSummary(actual, expected)) {\n throw new Error(\n `w7-frame: batch-end summary mismatch; expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`\n );\n }\n await buffer.ensureEof(stream);\n completed = true;\n yield { type: \"batch-end\", summary: actual };\n return;\n }\n case 1 :\n throw new Error(\"w7-frame: duplicate batch-begin\");\n default:\n throw new Error(`w7-frame: unknown record tag ${envelope.tag}`);\n }\n }\n } catch (error) {\n failure = error;\n throw error;\n } finally {\n if (completed) {\n try {\n reader.releaseLock();\n } catch {\n }\n } else {\n await cancelReader(reader, failure);\n }\n }\n}\nfunction* encodeRecords(batchId, deletes, directories, files) {\n const state = {\n batchCheck: 0,\n summary: {\n recordCount: 0,\n pathCount: 0,\n deleteCount: 0,\n directoryCount: 0,\n fileCount: 0,\n chunkCount: 0,\n byteCount: 0\n }\n };\n yield encodeMetadataRecord(1 , { id: batchId, mode: MODE }, state);\n for (const path of deletes) {\n state.summary.pathCount++;\n state.summary.deleteCount++;\n yield encodeMetadataRecord(2 , { path }, state);\n }\n for (const inode of directories) {\n state.summary.pathCount++;\n state.summary.directoryCount++;\n yield encodeMetadataRecord(3 , {\n ...inodeMetadata(inode),\n kind: inode.kind\n }, state);\n }\n for (const file of files) {\n state.summary.pathCount++;\n state.summary.fileCount++;\n yield encodeMetadataRecord(4 , {\n ...inodeMetadata(file.inode),\n kind: file.inode.kind,\n contentId: file.contentId,\n size: file.inode.size,\n chunkCount: file.inode.chunkCount\n }, state);\n let fileCheck = 0;\n for (const chunk of file.chunks) {\n const data = chunk.data;\n const contentBytes = new TextEncoder().encode(file.contentId);\n const prefix = new Uint8Array(4 + contentBytes.length + 8);\n writeU32LE(prefix, 0, contentBytes.length);\n prefix.set(contentBytes, 4);\n writeU32LE(prefix, 4 + contentBytes.length, chunk.chunkId);\n writeU32LE(prefix, 8 + contentBytes.length, data.byteLength);\n const header = recordHeader(5 , prefix.byteLength + data.byteLength);\n state.batchCheck = updateRecordCheck(state.batchCheck, header, prefix, data);\n state.summary.recordCount++;\n state.summary.chunkCount++;\n state.summary.byteCount += data.byteLength;\n fileCheck = crc32(data, fileCheck);\n yield [concatBytes(header, prefix), data];\n }\n yield encodeMetadataRecord(6 , {\n contentId: file.contentId,\n size: file.inode.size,\n chunkCount: file.inode.chunkCount,\n check: fileCheck\n }, state);\n }\n const end = {\n ...state.summary,\n check: state.batchCheck\n };\n yield encodeMetadataRecord(7 , end);\n}\nfunction encodeMetadataRecord(tag, value, state) {\n const payload = new TextEncoder().encode(JSON.stringify(value));\n if (payload.byteLength > MAX_METADATA_BYTES) {\n throw new Error(`w7-frame: metadata record exceeds ${MAX_METADATA_BYTES} bytes`);\n }\n const header = recordHeader(tag, payload.byteLength);\n if (state && tag !== 7 ) {\n state.batchCheck = updateRecordCheck(state.batchCheck, header, payload);\n state.summary.recordCount++;\n }\n return [concatBytes(header, payload)];\n}\nfunction preparePayload(payload, batchId) {\n if (!payload || !Array.isArray(payload.inodes) || !Array.isArray(payload.chunks)) {\n throw new Error(\"w7-frame: payload must contain inode and chunk arrays\");\n }\n const ownedPaths = new PathOwnership();\n const deletes = [...payload.deletePaths ?? []];\n for (const path of deletes) claimPath(ownedPaths, canonicalPath(path, \"delete path\"));\n const chunksByPath = new Map();\n for (const chunk of payload.chunks) {\n const path = canonicalPath(chunk.path, \"chunk path\");\n const list = chunksByPath.get(path);\n if (list) list.push(chunk);\n else chunksByPath.set(path, [chunk]);\n }\n const directories = [];\n const files = [];\n let fileIndex = 0;\n for (const inode of payload.inodes) {\n const path = canonicalPath(inode.path, \"inode path\");\n if (path !== inode.path) throw new Error(`w7-frame: noncanonical inode path ${inode.path}`);\n claimPath(ownedPaths, path);\n const normalizedInode = normalizeInode(inode);\n const fileChunks = chunksByPath.get(path) ?? [];\n if (normalizedInode.kind === \"directory\") {\n if (fileChunks.length > 0) throw new Error(`w7-frame: directory ${path} has chunks`);\n directories.push(normalizedInode);\n } else {\n validateChunks(normalizedInode, fileChunks);\n files.push({\n inode: normalizedInode,\n contentId: `${batchId}:${fileIndex++}`,\n chunks: fileChunks\n });\n }\n chunksByPath.delete(path);\n }\n if (chunksByPath.size > 0) {\n throw new Error(`w7-frame: chunk has no inode: ${chunksByPath.keys().next().value}`);\n }\n return { deletes, directories, files };\n}\nfunction parseBatchBegin(bytes) {\n const value = parseObject(bytes, \"batch-begin\", [\"id\", \"mode\"]);\n const id = boundedString(value.id, \"batch id\", MAX_BATCH_ID_BYTES);\n if (value.mode !== MODE) throw new Error(`w7-frame: unsupported batch mode ${String(value.mode)}`);\n return { id, mode: MODE };\n}\nfunction parseDelete(bytes) {\n const value = parseObject(bytes, \"delete\", [\"path\"]);\n return { path: canonicalPath(value.path, \"delete path\") };\n}\nfunction parseDirectory(bytes) {\n const value = parseObject(bytes, \"directory\", [\"path\", \"kind\", \"mtime\", \"mode\"], [\"atime\"]);\n if (value.kind !== \"directory\") {\n throw new Error(`w7-frame: unsupported directory kind ${String(value.kind)}`);\n }\n return { ...parseInodeMetadata(value, \"directory\"), kind: \"directory\" };\n}\nfunction parseFileBegin(bytes) {\n const value = parseObject(\n bytes,\n \"file-begin\",\n [\"path\", \"kind\", \"contentId\", \"size\", \"chunkCount\", \"mtime\", \"mode\"],\n [\"atime\"]\n );\n const base = parseInodeMetadata(value, \"file-begin\");\n if (value.kind !== \"file\" && value.kind !== \"symlink\") {\n throw new Error(`w7-frame: unsupported file-begin kind ${String(value.kind)}`);\n }\n const contentId = boundedString(value.contentId, \"stream content id\", MAX_CONTENT_ID_BYTES);\n if (!/^[A-Za-z0-9._:-]+$/.test(contentId)) {\n throw new Error(`w7-frame: invalid stream content id ${contentId}`);\n }\n const size = safeInteger(value.size, \"file size\");\n const chunkCount = u32(value.chunkCount, \"file chunk count\");\n const expected = size === 0 ? 0 : Math.ceil(size / CHUNK_SIZE);\n if (chunkCount !== expected) {\n throw new Error(`w7-frame: ${base.path}: expected ${expected} chunks, got ${chunkCount}`);\n }\n return { ...base, kind: value.kind, contentId, size, chunkCount };\n}\nfunction parseFileEnd(bytes) {\n const value = parseObject(bytes, \"file-end\", [\"contentId\", \"size\", \"chunkCount\", \"check\"]);\n return {\n contentId: boundedString(value.contentId, \"stream content id\", MAX_CONTENT_ID_BYTES),\n size: safeInteger(value.size, \"file-end size\"),\n chunkCount: u32(value.chunkCount, \"file-end chunk count\"),\n check: u32(value.check, \"file-end check\")\n };\n}\nfunction parseBatchEnd(bytes) {\n const keys = [\n \"recordCount\",\n \"pathCount\",\n \"deleteCount\",\n \"directoryCount\",\n \"fileCount\",\n \"chunkCount\",\n \"byteCount\",\n \"check\"\n ];\n const value = parseObject(bytes, \"batch-end\", keys);\n return {\n recordCount: safeInteger(value.recordCount, \"batch record count\"),\n pathCount: safeInteger(value.pathCount, \"batch path count\"),\n deleteCount: safeInteger(value.deleteCount, \"batch delete count\"),\n directoryCount: safeInteger(value.directoryCount, \"batch directory count\"),\n fileCount: safeInteger(value.fileCount, \"batch file count\"),\n chunkCount: safeInteger(value.chunkCount, \"batch chunk count\"),\n byteCount: safeInteger(value.byteCount, \"batch byte count\"),\n check: u32(value.check, \"batch check\")\n };\n}\nfunction parseInodeMetadata(value, label) {\n return {\n path: canonicalPath(value.path, `${label} path`),\n ...value.atime === void 0 ? {} : { atime: safeInteger(value.atime, `${label} atime`) },\n mtime: safeInteger(value.mtime, `${label} mtime`),\n mode: u32(value.mode, `${label} mode`)\n };\n}\nfunction parseObject(bytes, label, required, optional = []) {\n let value;\n try {\n value = JSON.parse(decodeText(bytes, label));\n } catch (error) {\n if (error instanceof Error && error.message.startsWith(\"w7-frame:\")) throw error;\n throw new Error(`w7-frame: invalid ${label} JSON: ${errorMessage(error)}`);\n }\n if (!isObject(value) || Array.isArray(value)) throw new Error(`w7-frame: ${label} must be an object`);\n const allowed = new Set([...required, ...optional]);\n for (const key of required) {\n if (!Object.hasOwn(value, key)) throw new Error(`w7-frame: ${label} missing ${key}`);\n }\n for (const key of Object.keys(value)) {\n if (!allowed.has(key)) throw new Error(`w7-frame: ${label} has unknown field ${key}`);\n }\n return value;\n}\nfunction normalizeInode(inode) {\n canonicalPath(inode.path, \"inode path\");\n if (inode.parentPath !== parentPath(inode.path)) {\n throw new Error(`w7-frame: ${inode.path}: noncanonical parent path ${inode.parentPath}`);\n }\n safeInteger(inode.size, `${inode.path} size`);\n u32(inode.chunkCount, `${inode.path} chunk count`);\n safeInteger(inode.mtime, `${inode.path} mtime`);\n if (inode.atime !== void 0) safeInteger(inode.atime, `${inode.path} atime`);\n u32(inode.mode, `${inode.path} mode`);\n const rawKind = inode.kind ?? (inode.isDir ? \"directory\" : \"file\");\n if (rawKind !== \"file\" && rawKind !== \"directory\" && rawKind !== \"symlink\") {\n throw new Error(`w7-frame: unsupported inode kind ${String(rawKind)}`);\n }\n const kind = rawKind;\n if (kind === \"directory\" && !inode.isDir) {\n throw new Error(`w7-frame: directory inode ${inode.path} must be a directory`);\n }\n if (kind !== \"directory\" && inode.isDir) {\n throw new Error(`w7-frame: ${kind} inode ${inode.path} cannot be a directory`);\n }\n if (kind === \"directory\" && (inode.size !== 0 || inode.chunkCount !== 0)) {\n throw new Error(`w7-frame: directory ${inode.path} must have zero size and chunks`);\n }\n if (kind !== \"directory\") {\n const expected = inode.size === 0 ? 0 : Math.ceil(inode.size / CHUNK_SIZE);\n if (inode.chunkCount !== expected) {\n throw new Error(`w7-frame: ${inode.path}: expected ${expected} chunks, got ${inode.chunkCount}`);\n }\n return { ...inode, kind, isDir: false };\n }\n return { ...inode, kind, isDir: true };\n}\nfunction validateChunks(inode, chunks) {\n if (chunks.length !== inode.chunkCount) {\n throw new Error(`w7-frame: ${inode.path}: expected ${inode.chunkCount} chunks, got ${chunks.length}`);\n }\n chunks.sort((left, right) => left.chunkId - right.chunkId);\n for (let index = 0; index < chunks.length; index++) {\n const chunk = chunks[index];\n if (chunk.chunkId !== index) {\n throw new Error(`w7-frame: ${inode.path}: expected chunk ${index}, got ${chunk.chunkId}`);\n }\n const expected = Math.min(CHUNK_SIZE, inode.size - index * CHUNK_SIZE);\n if (!(chunk.data instanceof Uint8Array) || chunk.data.byteLength !== expected) {\n throw new Error(`w7-frame: ${inode.path}: chunk ${index} must contain ${expected} bytes`);\n }\n }\n}\nfunction directoryInode(metadata) {\n return {\n path: metadata.path,\n parentPath: parentPath(metadata.path),\n kind: metadata.kind,\n isDir: true,\n size: 0,\n atime: metadata.atime,\n mtime: metadata.mtime,\n mode: metadata.mode,\n chunkCount: 0\n };\n}\nfunction fileInode(metadata) {\n return {\n path: metadata.path,\n parentPath: parentPath(metadata.path),\n kind: metadata.kind,\n isDir: false,\n size: metadata.size,\n atime: metadata.atime,\n mtime: metadata.mtime,\n mode: metadata.mode,\n chunkCount: metadata.chunkCount\n };\n}\nfunction inodeMetadata(inode) {\n return {\n path: inode.path,\n ...inode.atime === void 0 ? {} : { atime: inode.atime },\n mtime: inode.mtime,\n mode: inode.mode\n };\n}\nfunction canonicalPath(value, label) {\n const path = boundedString(value, label, MAX_PATH_BYTES);\n if (path.includes(\"\\0\")) throw new Error(`w7-frame: ${label} contains NUL`);\n const normalized = normalizePath(path);\n if (!path || normalized !== path) throw new Error(`w7-frame: noncanonical ${label}: ${path}`);\n return path;\n}\nvar PathOwnership = class {\n paths = new Set();\n pathBytes = 0;\n claim(path) {\n if (this.paths.has(path)) throw new Error(`w7-frame: duplicate path ownership: ${path}`);\n if (this.paths.size >= W7_MAX_PATHS_PER_BATCH) {\n throw new Error(`w7-frame: batch exceeds ${W7_MAX_PATHS_PER_BATCH} owned paths`);\n }\n const nextPathBytes = this.pathBytes + new TextEncoder().encode(path).byteLength;\n if (nextPathBytes > W7_MAX_OWNED_PATH_BYTES) {\n throw new Error(\n `w7-frame: owned path bytes exceed ${W7_MAX_OWNED_PATH_BYTES}`\n );\n }\n this.paths.add(path);\n this.pathBytes = nextPathBytes;\n }\n};\nfunction claimPath(paths, path) {\n paths.claim(path);\n}\nfunction normalizePath(path) {\n const out = [];\n for (const segment of path.split(\"/\")) {\n if (segment === \"..\") {\n if (out.length > 0) out.pop();\n } else if (segment !== \"\" && segment !== \".\") {\n out.push(segment);\n }\n }\n return out.join(\"/\");\n}\nfunction parentPath(path) {\n const index = path.lastIndexOf(\"/\");\n return index < 0 ? \"\" : path.slice(0, index);\n}\nfunction boundedString(value, label, maxBytes) {\n if (typeof value !== \"string\" || value.length === 0) {\n throw new Error(`w7-frame: ${label} must be a non-empty string`);\n }\n const length = new TextEncoder().encode(value).byteLength;\n if (length > maxBytes) throw new Error(`w7-frame: ${label} exceeds ${maxBytes} bytes`);\n return value;\n}\nfunction safeInteger(value, label) {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new Error(`w7-frame: ${label} must be a non-negative safe integer`);\n }\n return value;\n}\nfunction u32(value, label) {\n const integer = safeInteger(value, label);\n if (integer > 4294967295) throw new Error(`w7-frame: ${label} exceeds uint32`);\n return integer;\n}\nfunction sameSummary(left, right) {\n return left.recordCount === right.recordCount && left.pathCount === right.pathCount && left.deleteCount === right.deleteCount && left.directoryCount === right.directoryCount && left.fileCount === right.fileCount && left.chunkCount === right.chunkCount && left.byteCount === right.byteCount && left.check === right.check;\n}\nasync function readEnvelope(buffer, label) {\n const header = await buffer.readExact(5, `${label} header`);\n return { tag: header[0], length: readU32LE(header, 1), header };\n}\nfunction recordHeader(tag, length) {\n const header = new Uint8Array(5);\n header[0] = tag;\n writeU32LE(header, 1, length);\n return header;\n}\nfunction writeU32LE(out, offset, value) {\n out[offset] = value & 255;\n out[offset + 1] = value >>> 8 & 255;\n out[offset + 2] = value >>> 16 & 255;\n out[offset + 3] = value >>> 24 & 255;\n}\nfunction readU32LE(bytes, offset) {\n return (bytes[offset] | bytes[offset + 1] << 8 | bytes[offset + 2] << 16 | bytes[offset + 3] << 24) >>> 0;\n}\nfunction updateRecordCheck(seed, ...parts) {\n let check = seed;\n for (const part of parts) check = crc32(part, check);\n return check;\n}\nfunction noopRetention(bytes) {\n return { bytes, release() {\n } };\n}\nfunction decodeText(bytes, label) {\n try {\n return new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: false }).decode(bytes);\n } catch (error) {\n throw new Error(`w7-frame: invalid UTF-8 in ${label}: ${errorMessage(error)}`);\n }\n}\nfunction concatBytes(...parts) {\n const output = new Uint8Array(parts.reduce((total, part) => total + part.byteLength, 0));\n let offset = 0;\n for (const part of parts) {\n output.set(part, offset);\n offset += part.byteLength;\n }\n return output;\n}\nfunction bytesEqual(left, right) {\n return left.length === right.length && left.every((byte, index) => byte === right[index]);\n}\nfunction hex(bytes) {\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\" \");\n}\nfunction isObject(value) {\n return typeof value === \"object\" && value !== null;\n}\nfunction errorMessage(error) {\n return error instanceof Error ? error.message : String(error);\n}\nfunction throwIfAborted(signal) {\n if (!signal?.aborted) return;\n throw new DOMException(\n signal.reason instanceof Error ? signal.reason.message : String(signal.reason ?? \"Aborted\"),\n \"AbortError\"\n );\n}\nasync function cancelReader(reader, reason) {\n try {\n await reader.cancel(reason);\n } catch {\n }\n try {\n reader.releaseLock();\n } catch {\n }\n}\nvar ExactByteReader = class {\n constructor(reader, signal) {\n this.reader = reader;\n this.signal = signal;\n }\n reader;\n signal;\n done = false;\n async read(read, cancel) {\n throwIfAborted(this.signal);\n const abort = () => {\n void cancel().catch(() => {\n });\n };\n this.signal?.addEventListener(\"abort\", abort, { once: true });\n try {\n const result = await read();\n throwIfAborted(this.signal);\n return result;\n } finally {\n this.signal?.removeEventListener(\"abort\", abort);\n }\n }\n async readExact(length, label) {\n if (length === 0) return new Uint8Array(0);\n const output = new Uint8Array(length);\n let offset = 0;\n while (offset < length) {\n if (this.done) {\n throw new Error(\n `w7-frame: stream ended ${offset} bytes into expected ${length}-byte ${label}`\n );\n }\n const next = await this.read(\n () => this.reader.read(new Uint8Array(length - offset)),\n () => this.reader.cancel(this.signal?.reason)\n );\n if (next.done) this.done = true;\n else if (next.value.byteLength > 0) {\n output.set(next.value, offset);\n offset += next.value.byteLength;\n }\n }\n return output;\n }\n async ensureEof(stream) {\n if (this.done) return;\n this.reader.releaseLock();\n const reader = stream.getReader();\n try {\n const next = await this.read(() => reader.read(), () => reader.cancel(this.signal?.reason));\n if (!next.done && next.value.byteLength > 0) {\n await reader.cancel(new Error(\"w7-frame: trailing bytes after batch-end\"));\n throw new Error(\"w7-frame: trailing bytes after batch-end\");\n }\n this.done = true;\n } finally {\n try {\n reader.releaseLock();\n } catch {\n }\n }\n }\n};";
24
+ /** Declares `function createEsmResolver(host)`; the node shims call it. */
25
+ export const ESM_RESOLVER_PREAMBLE = "function createEsmResolver(host) {\n const conditions = new Set([\"node\", \"import\", \"module-sync\"]);\n const ask = {\n *kind(path) {\n const kind = yield host.kind(path);\n return kind === \"file\" || kind === \"directory\" ? kind : null;\n },\n *readText(path) {\n const text = yield host.readText(path);\n return typeof text === \"string\" ? text : null;\n },\n *realpath(path) {\n const real = yield host.realpath(path);\n return typeof real === \"string\" ? real : path;\n },\n *cjsResolve(specifier, parentPath) {\n const found = yield host.cjsResolve(specifier, parentPath);\n return typeof found === \"string\" ? found : null;\n }\n };\n function codedError(Ctor, code, message) {\n return Object.assign(new Ctor(message), { code });\n }\n const codeOf = (error) => error !== null && typeof error === \"object\" && \"code\" in error ? error.code : void 0;\n const filePath = (url) => decodeURIComponent(new URL(String(url)).pathname);\n const fileUrl = (path) => {\n const url = new URL(\"file://\");\n url.pathname = path;\n return url;\n };\n function isRelativeSpecifier(specifier) {\n if (specifier[0] !== \".\") return false;\n if (specifier.length === 1 || specifier[1] === \"/\") return true;\n return specifier[1] === \".\" && (specifier.length === 2 || specifier[2] === \"/\");\n }\n const isRelativeOrAbsolute = (specifier) => specifier !== \"\" && (specifier[0] === \"/\" || isRelativeSpecifier(specifier));\n function* readPackageConfig(pjsonPath, specifier, base) {\n const text = (yield* ask.kind(pjsonPath)) === \"file\" ? yield* ask.readText(pjsonPath) : null;\n if (text === null) return { exists: false, pjsonPath, type: \"none\" };\n let parsed;\n try {\n parsed = JSON.parse(text);\n } catch {\n throw codedError(\n Error,\n \"ERR_INVALID_PACKAGE_CONFIG\",\n `Invalid package config ${pjsonPath}` + (base ? ` while importing ${JSON.stringify(specifier)} from ${base}` : \"\") + \".\"\n );\n }\n const config = { exists: true, pjsonPath, type: \"none\" };\n if (parsed === null || typeof parsed !== \"object\") return config;\n if (typeof parsed.name === \"string\") config.name = parsed.name;\n if (typeof parsed.main === \"string\") config.main = parsed.main;\n if (\"exports\" in parsed) config.exports = parsed.exports;\n if (parsed.imports !== null && typeof parsed.imports === \"object\") config.imports = parsed.imports;\n if (parsed.type === \"module\" || parsed.type === \"commonjs\") config.type = parsed.type;\n return config;\n }\n function* packageScopeConfig(resolved) {\n let pjsonUrl = new URL(\"./package.json\", resolved);\n while (true) {\n if (pjsonUrl.pathname.endsWith(\"node_modules/package.json\")) break;\n const config = yield* readPackageConfig(filePath(pjsonUrl), resolved.href, void 0);\n if (config.exists) return config;\n const last = pjsonUrl;\n pjsonUrl = new URL(\"../package.json\", pjsonUrl);\n if (pjsonUrl.pathname === last.pathname) break;\n }\n return { exists: false, pjsonPath: filePath(pjsonUrl), type: \"none\" };\n }\n function invalidPackageTarget(key, target, pjsonUrl, internal, base) {\n const text = typeof target === \"object\" && target !== null ? JSON.stringify(target, null, \"\") : `${target}`;\n const pkgPath = filePath(new URL(\".\", pjsonUrl));\n const related = !internal && text.length > 0 && !text.startsWith(\"./\");\n const tail = `in the package config ${pkgPath}package.json imported from ${base}${related ? '; targets must start with \"./\"' : \"\"}`;\n return codedError(\n Error,\n \"ERR_INVALID_PACKAGE_TARGET\",\n key === \".\" ? `Invalid \"exports\" main target ${JSON.stringify(text)} defined ${tail}` : `Invalid \"${internal ? \"imports\" : \"exports\"}\" target ${JSON.stringify(text)} defined for '${key}' ${tail}`\n );\n }\n const invalidSegment = /(^|\\\\|\\/)((\\.|%2e)(\\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))?(\\\\|\\/|$)/i;\n const deprecatedInvalidSegment = /(^|\\\\|\\/)((\\.|%2e)(\\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))(\\\\|\\/|$)/i;\n function* resolveTargetString(target, subpath, match, pjsonUrl, base, pattern, internal, isPathMap) {\n if (subpath !== \"\" && !pattern && target[target.length - 1] !== \"/\") {\n throw invalidPackageTarget(match, target, pjsonUrl, internal, base);\n }\n if (!target.startsWith(\"./\")) {\n if (internal && !target.startsWith(\"../\") && !target.startsWith(\"/\")) {\n let isUrl = false;\n try {\n new URL(target);\n isUrl = true;\n } catch {\n }\n if (!isUrl) {\n const exportTarget = pattern ? target.replace(/\\*/g, () => subpath) : target + subpath;\n return yield* packageResolve(exportTarget, pjsonUrl.href);\n }\n }\n throw invalidPackageTarget(match, target, pjsonUrl, internal, base);\n }\n if (invalidSegment.test(target.slice(2)) && deprecatedInvalidSegment.test(target.slice(2))) {\n throw invalidPackageTarget(match, target, pjsonUrl, internal, base);\n }\n const resolved = new URL(target, pjsonUrl);\n if (!resolved.pathname.startsWith(new URL(\".\", pjsonUrl).pathname)) {\n throw invalidPackageTarget(match, target, pjsonUrl, internal, base);\n }\n if (subpath === \"\") return resolved;\n if (invalidSegment.test(subpath) && deprecatedInvalidSegment.test(subpath) && !isPathMap) {\n const request = pattern ? match.replace(\"*\", () => subpath) : match + subpath;\n throw codedError(\n TypeError,\n \"ERR_INVALID_MODULE_SPECIFIER\",\n `Invalid module \"${request}\" request is not a valid match in pattern \"${match}\" for the \"${internal ? \"imports\" : \"exports\"}\" resolution of ${filePath(pjsonUrl)} imported from ${base}`\n );\n }\n if (pattern) return new URL(resolved.href.replace(/\\*/g, () => subpath));\n return new URL(subpath, resolved);\n }\n function* resolveTarget(pjsonUrl, target, subpath, key, base, pattern, internal, isPathMap) {\n if (typeof target === \"string\") {\n return yield* resolveTargetString(target, subpath, key, pjsonUrl, base, pattern, internal, isPathMap);\n }\n if (Array.isArray(target)) {\n if (target.length === 0) return null;\n let lastException;\n for (const item of target) {\n let result;\n try {\n result = yield* resolveTarget(pjsonUrl, item, subpath, key, base, pattern, internal, isPathMap);\n } catch (error) {\n lastException = error;\n if (codeOf(error) === \"ERR_INVALID_PACKAGE_TARGET\") continue;\n throw error;\n }\n if (result === void 0) continue;\n if (result === null) {\n lastException = null;\n continue;\n }\n return result;\n }\n if (lastException === void 0 || lastException === null) return lastException;\n throw lastException;\n }\n if (typeof target === \"object\" && target !== null) {\n const keys = Object.getOwnPropertyNames(target);\n for (const condition of keys) {\n if (/^\\d+$/.test(condition) && String(Number(condition)) === condition && Number(condition) < 4294967295) {\n throw codedError(\n Error,\n \"ERR_INVALID_PACKAGE_CONFIG\",\n `Invalid package config ${filePath(pjsonUrl)} while importing ${fileUrl(base).href}. \"exports\" cannot contain numeric property keys.`\n );\n }\n }\n for (const condition of keys) {\n if (condition !== \"default\" && !conditions.has(condition)) continue;\n const result = yield* resolveTarget(\n pjsonUrl,\n Reflect.get(target, condition),\n subpath,\n key,\n base,\n pattern,\n internal,\n isPathMap\n );\n if (result === void 0) continue;\n return result;\n }\n return void 0;\n }\n if (target === null) return null;\n throw invalidPackageTarget(key, target, pjsonUrl, internal, base);\n }\n function patternKeyCompare(a, b) {\n const aStar = a.indexOf(\"*\");\n const bStar = b.indexOf(\"*\");\n const baseA = aStar === -1 ? a.length : aStar + 1;\n const baseB = bStar === -1 ? b.length : bStar + 1;\n if (baseA > baseB) return -1;\n if (baseB > baseA) return 1;\n if (aStar === -1) return 1;\n if (bStar === -1) return -1;\n if (a.length > b.length) return -1;\n if (b.length > a.length) return 1;\n return 0;\n }\n function bestPattern(map, name) {\n let best = \"\";\n let bestSubpath = \"\";\n for (const key of Object.getOwnPropertyNames(map)) {\n const star = key.indexOf(\"*\");\n if (star === -1 || !name.startsWith(key.slice(0, star))) continue;\n const trailer = key.slice(star + 1);\n if (name.length >= key.length && name.endsWith(trailer) && patternKeyCompare(best, key) === 1 && key.lastIndexOf(\"*\") === star) {\n best = key;\n bestSubpath = name.slice(star, name.length - trailer.length);\n }\n }\n return best ? { key: best, subpath: bestSubpath } : null;\n }\n function exportsNotFound(subpath, pjsonUrl, base) {\n const pkgPath = filePath(new URL(\".\", pjsonUrl));\n return codedError(\n Error,\n \"ERR_PACKAGE_PATH_NOT_EXPORTED\",\n subpath === \".\" ? `No \"exports\" main defined in ${pkgPath}package.json imported from ${base}` : `Package subpath '${subpath}' is not defined by \"exports\" in ${pkgPath}package.json imported from ${base}`\n );\n }\n function* packageExportsResolve(pjsonUrl, subpath, config, base) {\n let exports = config.exports;\n const isSugar = (() => {\n if (typeof exports === \"string\" || Array.isArray(exports)) return true;\n if (typeof exports !== \"object\" || exports === null) return false;\n let sugar = false;\n let i = 0;\n for (const key of Object.getOwnPropertyNames(exports)) {\n const current = key === \"\" || key[0] !== \".\";\n if (i++ === 0) sugar = current;\n else if (sugar !== current) {\n throw codedError(\n Error,\n \"ERR_INVALID_PACKAGE_CONFIG\",\n `Invalid package config ${filePath(pjsonUrl)} while importing ${fileUrl(base).href}. \"exports\" cannot contain some keys starting with '.' and some not. The exports object must either be an object of package subpath keys or an object of main entry condition name keys only.`\n );\n }\n }\n return sugar;\n })();\n if (isSugar) exports = { \".\": exports };\n const map = exports;\n if (Object.prototype.hasOwnProperty.call(map, subpath) && !subpath.includes(\"*\") && !subpath.endsWith(\"/\")) {\n const result = yield* resolveTarget(pjsonUrl, map[subpath], \"\", subpath, base, false, false, false);\n if (result == null) throw exportsNotFound(subpath, pjsonUrl, base);\n return result;\n }\n const best = bestPattern(map, subpath);\n if (best) {\n const result = yield* resolveTarget(pjsonUrl, map[best.key], best.subpath, best.key, base, true, false, subpath.endsWith(\"/\"));\n if (result == null) throw exportsNotFound(subpath, pjsonUrl, base);\n return result;\n }\n throw exportsNotFound(subpath, pjsonUrl, base);\n }\n function* packageImportsResolve(name, baseUrl) {\n const base = filePath(baseUrl);\n if (name === \"#\" || name.startsWith(\"#/\") || name.endsWith(\"/\")) {\n throw codedError(TypeError, \"ERR_INVALID_MODULE_SPECIFIER\", `Invalid module \"${name}\" is not a valid internal imports specifier name imported from ${base}`);\n }\n const config = yield* packageScopeConfig(new URL(baseUrl));\n let pjsonUrl;\n if (config.exists) {\n pjsonUrl = fileUrl(config.pjsonPath);\n const imports = config.imports;\n if (imports) {\n if (Object.prototype.hasOwnProperty.call(imports, name) && !name.includes(\"*\")) {\n const result = yield* resolveTarget(pjsonUrl, imports[name], \"\", name, base, false, true, false);\n if (result != null) return result;\n } else {\n const best = bestPattern(imports, name);\n if (best) {\n const result = yield* resolveTarget(pjsonUrl, imports[best.key], best.subpath, best.key, base, true, true, false);\n if (result != null) return result;\n }\n }\n }\n }\n const where = pjsonUrl ? ` in package ${filePath(new URL(\".\", pjsonUrl))}package.json` : \"\";\n throw codedError(TypeError, \"ERR_PACKAGE_IMPORT_NOT_DEFINED\", `Package import specifier \"${name}\" is not defined${where} imported from ${base}`);\n }\n function* legacyMainResolve(pjsonUrl, config, base) {\n const tries = [];\n if (config.main !== void 0) {\n for (const suffix of [\"\", \".js\", \".json\", \".node\", \"/index.js\", \"/index.json\", \"/index.node\"]) tries.push(`./${config.main}${suffix}`);\n }\n tries.push(\"./index.js\", \"./index.json\", \"./index.node\");\n for (const candidate of tries) {\n const url = new URL(candidate, pjsonUrl);\n if ((yield* ask.kind(filePath(url))) === \"file\") return url;\n }\n const dir = fileUrl(filePath(new URL(\".\", pjsonUrl)).replace(/\\/+/g, \"/\"));\n const missing = filePath(new URL(config.main ?? \"index.js\", dir));\n throw codedError(Error, \"ERR_MODULE_NOT_FOUND\", `Cannot find package '${missing}' imported from ${base}`);\n }\n function* packageResolve(specifier, baseUrl) {\n if (host.isBuiltin(specifier)) return new URL(\"node:\" + specifier);\n const base = filePath(baseUrl);\n let separator = specifier.indexOf(\"/\");\n let valid = true;\n let scoped = false;\n if (specifier[0] === \"@\") {\n scoped = true;\n if (separator === -1 || specifier.length === 0) valid = false;\n else separator = specifier.indexOf(\"/\", separator + 1);\n }\n const name = separator === -1 ? specifier : specifier.slice(0, separator);\n if (/^\\.|%|\\\\/.test(name)) valid = false;\n if (!valid) {\n throw codedError(TypeError, \"ERR_INVALID_MODULE_SPECIFIER\", `Invalid module \"${specifier}\" is not a valid package name imported from ${base}`);\n }\n const subpath = \".\" + (separator === -1 ? \"\" : specifier.slice(separator));\n const self = yield* packageScopeConfig(new URL(baseUrl));\n if (self.exists && self.exports != null && self.name === name) {\n return yield* packageExportsResolve(fileUrl(self.pjsonPath), subpath, self, base);\n }\n let pjsonUrl = new URL(\"./node_modules/\" + name + \"/package.json\", baseUrl);\n let pjsonPath = filePath(pjsonUrl);\n let lastPath;\n do {\n if ((yield* ask.kind(pjsonPath.slice(0, pjsonPath.length - 13))) !== \"directory\") {\n lastPath = pjsonPath;\n pjsonUrl = new URL((scoped ? \"../../../../node_modules/\" : \"../../../node_modules/\") + name + \"/package.json\", pjsonUrl);\n pjsonPath = filePath(pjsonUrl);\n continue;\n }\n const config = yield* readPackageConfig(pjsonPath, specifier, base);\n if (config.exports != null) return yield* packageExportsResolve(pjsonUrl, subpath, config, base);\n if (subpath === \".\") return yield* legacyMainResolve(pjsonUrl, config, base);\n return new URL(subpath, pjsonUrl);\n } while (pjsonPath.length !== lastPath.length);\n throw codedError(Error, \"ERR_MODULE_NOT_FOUND\", `Cannot find package '${name}' imported from ${base}`);\n }\n function* formatOf(url, path) {\n const base = path.slice(path.lastIndexOf(\"/\") + 1);\n const dot = base.lastIndexOf(\".\");\n const ext = dot > 0 ? base.slice(dot) : \"\";\n if (ext === \".mjs\" || ext === \".mts\") return \"module\";\n if (ext === \".cjs\" || ext === \".cts\") return \"commonjs\";\n if (ext === \".json\") return \"json\";\n if (ext === \".js\" || ext === \".ts\" || ext === \"\") {\n const type = (yield* packageScopeConfig(url)).type;\n if (type === \"module\") return \"module\";\n if (type === \"commonjs\") return \"commonjs\";\n return \"detect\";\n }\n throw codedError(TypeError, \"ERR_UNKNOWN_FILE_EXTENSION\", `Unknown file extension \"${ext}\" for ${path}`);\n }\n function* finalizeResolution(resolved, baseUrl) {\n const base = filePath(baseUrl);\n if (/%2f|%5c/i.test(resolved.pathname)) {\n throw codedError(\n TypeError,\n \"ERR_INVALID_MODULE_SPECIFIER\",\n `Invalid module \"${resolved.pathname}\" must not include encoded \"/\" or \"\\\\\" characters imported from ${base}`\n );\n }\n const path = filePath(resolved);\n const kind = path.endsWith(\"/\") ? \"directory\" : yield* ask.kind(path);\n if (kind === \"directory\") {\n throw Object.assign(\n codedError(Error, \"ERR_UNSUPPORTED_DIR_IMPORT\", `Directory import '${path}' is not supported resolving ES modules imported from ${base}`),\n { url: resolved.href }\n );\n }\n if (kind !== \"file\") {\n throw Object.assign(\n codedError(Error, \"ERR_MODULE_NOT_FOUND\", `Cannot find module '${path}' imported from ${base}`),\n { url: resolved.href }\n );\n }\n const real = yield* ask.realpath(path);\n const url = fileUrl(real);\n url.search = resolved.search;\n url.hash = resolved.hash;\n return { url: url.href, path: real };\n }\n function* moduleResolve(specifier, parentUrl) {\n let resolved;\n if (isRelativeOrAbsolute(specifier)) resolved = new URL(specifier, parentUrl);\n else if (specifier[0] === \"#\") resolved = yield* packageImportsResolve(specifier, parentUrl);\n else {\n try {\n resolved = new URL(specifier);\n } catch {\n resolved = yield* packageResolve(specifier, parentUrl);\n }\n }\n if (resolved.protocol === \"node:\") return { url: \"node:\" + resolved.pathname, builtin: resolved.pathname };\n if (resolved.protocol !== \"file:\") return { url: resolved.href };\n return yield* finalizeResolution(resolved, parentUrl);\n }\n function* loadable(resolved) {\n if (resolved.builtin !== void 0) {\n if (!host.isBuiltin(\"node:\" + resolved.builtin)) {\n throw codedError(Error, \"ERR_UNKNOWN_BUILTIN_MODULE\", `No such built-in module: node:${resolved.builtin}`);\n }\n return { url: resolved.url, builtin: resolved.builtin, format: \"builtin\" };\n }\n if (resolved.url.startsWith(\"data:\")) return { url: resolved.url, format: \"data\" };\n if (resolved.path === void 0) {\n throw codedError(\n Error,\n \"ERR_UNSUPPORTED_ESM_URL_SCHEME\",\n `Only URLs with a scheme in: file and data are supported by the default ESM loader. Received protocol '${new URL(resolved.url).protocol}'`\n );\n }\n return { url: resolved.url, path: resolved.path, format: yield* formatOf(new URL(resolved.url), resolved.path) };\n }\n function* commonJsHint(specifier, parentUrl) {\n let found = yield* ask.cjsResolve(specifier, filePath(parentUrl));\n if (found === null) return null;\n if (isRelativeSpecifier(specifier)) {\n const from = parentUrl.slice(\"file://\".length, parentUrl.lastIndexOf(\"/\")).split(\"/\").filter(Boolean);\n const to = fileUrl(found).pathname.split(\"/\").filter(Boolean);\n let common = 0;\n while (common < from.length && common < to.length && from[common] === to[common]) common++;\n found = [...from.slice(common).map(() => \"..\"), ...to.slice(common)].join(\"/\");\n if (!found.startsWith(\"../\")) found = `./${found}`;\n } else if (specifier[0] && specifier[0] !== \"/\" && specifier[0] !== \".\") {\n const slash = specifier.indexOf(\"/\");\n const pkg = slash === -1 ? specifier : specifier.slice(0, slash);\n const needle = `/node_modules/${pkg}/`;\n const at = found.lastIndexOf(needle);\n found = at !== -1 ? pkg + \"/\" + found.slice(at + needle.length).split(\"/\").map(encodeURIComponent).join(\"/\") : fileUrl(found).href;\n }\n return found;\n }\n function* resolveWithHint(specifier, parentUrl) {\n try {\n return yield* moduleResolve(specifier, parentUrl);\n } catch (error) {\n const code = codeOf(error);\n if (error instanceof Error && (code === \"ERR_MODULE_NOT_FOUND\" || code === \"ERR_UNSUPPORTED_DIR_IMPORT\")) {\n const asGiven = specifier.startsWith(\"file://\") ? filePath(specifier) : specifier;\n const found = yield* commonJsHint(asGiven, parentUrl);\n if (found && found !== asGiven) error.message += `\nDid you mean to import ${JSON.stringify(found)}?`;\n }\n throw error;\n }\n }\n function* importTarget(specifier, parentUrl) {\n return yield* loadable(yield* resolveWithHint(specifier, parentUrl));\n }\n function* metaResolve(specifier, parentUrl) {\n try {\n return (yield* moduleResolve(specifier, parentUrl)).url;\n } catch (error) {\n const code = codeOf(error);\n if ((code === \"ERR_MODULE_NOT_FOUND\" || code === \"ERR_UNSUPPORTED_DIR_IMPORT\") && error !== null && typeof error === \"object\" && \"url\" in error && typeof error.url === \"string\") return error.url;\n throw error;\n }\n }\n function runSync(steps) {\n let next = steps.next();\n while (!next.done) {\n if (next.value instanceof Promise) throw new Error(\"resolveSync: the host answered asynchronously\");\n next = steps.next(next.value);\n }\n return next.value;\n }\n return {\n async resolve(specifier, parentUrl) {\n const steps = importTarget(specifier, parentUrl);\n let next = steps.next();\n while (!next.done) {\n let answer;\n try {\n answer = await next.value;\n } catch (error) {\n next = steps.throw(error);\n continue;\n }\n next = steps.next(answer);\n }\n return next.value;\n },\n resolveSync: (specifier, parentUrl) => runSync(importTarget(specifier, parentUrl)),\n metaResolveSync: (specifier, parentUrl) => runSync(metaResolve(specifier, parentUrl)),\n validateAttributes(url, format, attributes) {\n for (const key of Object.keys(attributes)) {\n if (key !== \"type\") {\n throw codedError(TypeError, \"ERR_IMPORT_ATTRIBUTE_UNSUPPORTED\", `Import attribute \"${key}\" with value \"${attributes[key]}\" is not supported in ${url}`);\n }\n }\n const type = attributes.type;\n if (format === \"json\" || format === \"data\" && /^data:application\\/json(?:;[^,]*)?,/.test(url)) {\n if (type === \"json\") return;\n if (!(\"type\" in attributes)) {\n throw codedError(TypeError, \"ERR_IMPORT_ATTRIBUTE_MISSING\", `Module \"${url}\" needs an import attribute of \"type: json\"`);\n }\n } else if (type == null) {\n return;\n }\n if (typeof type !== \"string\") {\n throw codedError(TypeError, \"ERR_INVALID_ARG_TYPE\", `The \"type\" argument must be of type string. Received ${typeof type}`);\n }\n if (type !== \"json\") {\n throw codedError(TypeError, \"ERR_IMPORT_ATTRIBUTE_UNSUPPORTED\", `Import attribute \"type\" with value \"${type}\" is not supported in ${url}`);\n }\n throw codedError(TypeError, \"ERR_IMPORT_ATTRIBUTE_TYPE_INCOMPATIBLE\", `Module \"${url}\" is not of type \"json\"`);\n }\n };\n}";
@@ -1 +1 @@
1
- {"version":3,"file":"npm-resolve-preamble.d.ts","sourceRoot":"","sources":["../../src/loaders/npm-resolve-preamble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAsBH,eAAO,MAAM,oBAAoB,EAAE,MAmFlC,CAAC"}
1
+ {"version":3,"file":"npm-resolve-preamble.d.ts","sourceRoot":"","sources":["../../src/loaders/npm-resolve-preamble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAsBH,eAAO,MAAM,oBAAoB,EAAE,MAwDlC,CAAC"}
@@ -61,9 +61,6 @@ function NATIVE_EXECUTABLE_REJECT(pkg) {
61
61
  function NATIVE_PLATFORM_REJECT(pkg) {
62
62
  return __policyNativePlatformReject(__NIMBUS_PACKAGE_ABI_POLICY, pkg);
63
63
  }
64
- function NATIVE_BIN_ADVISORY(pkg) {
65
- return __policyNativeBinAdvisory(__NIMBUS_PACKAGE_ABI_POLICY, pkg);
66
- }
67
64
  function IS_OPTIONAL_NATIVE_BINDING(pkg) {
68
65
  return __policyIsOptionalNativeBinding(__NIMBUS_PACKAGE_ABI_POLICY, pkg);
69
66
  }
@@ -75,30 +72,6 @@ function STAGED_ARTIFACT_APPLY(pkg, entry) {
75
72
  __policyApplyStagedArtifact(pkg, entry, STAGED_ARTIFACT_BIN_PREFIX);
76
73
  }
77
74
 
78
- // ── Registry telemetry: facet-side event collection ──────────────────────
79
- // The facet cannot import the registry's emitRegistryEvent (preamble has
80
- // no import surface). Instead, decision sites push into a shared
81
- // __pendingEvents array which resolveOnePackumentInFacet returns inside
82
- // ResolveOneResult.events. The supervisor drains it and flushes via
83
- // emitRegistryEvent (npm-installer.ts).
84
- //
85
- // Shape of each entry:
86
- // { type: 'swap', from, to, ctx: 'transitive' }
87
- // { type: 'reject', from, reason, suggest?, ctx: 'transitive' }
88
- // { type: 'transitive-skip', from, reason }
89
- //
90
- // Note: ctx is always 'transitive' from this path (the supervisor's
91
- // applyW6Registry handles 'top'-ctx events directly without the facet).
92
- const __pendingEvents = [];
93
- function __EMIT_EVENT(e) { __pendingEvents.push(e); }
94
- function __DRAIN_EVENTS() {
95
- // Hand ownership to caller; reset for next run (defensive — facet
96
- // function bodies are re-instantiated per run anyway).
97
- const out = __pendingEvents.slice();
98
- __pendingEvents.length = 0;
99
- return out;
100
- }
101
-
102
75
  // ── Semver (embedded from src/npm/semver.ts) ────────────────────────────
103
76
  // Generated — do not edit here. npm/semver.ts is the single implementation;
104
77
  // tests/unit/npm-semver.mjs asserts the embedded functions answer exactly as
@@ -10,7 +10,10 @@
10
10
  * Specifically prebundleOne references:
11
11
  * - ESBUILD_WASM_JS_FN_BODY — function-body string (~117 KiB) that,
12
12
  * when run via new Function(...)(), returns
13
- * the esbuild namespace. SMALL — kept inline.
13
+ * the esbuild namespace. Staged beside the
14
+ * wasm and fetched by the supervisor at
15
+ * pool construction (fetchEsbuildJsFnBody),
16
+ * then spliced in here.
14
17
  * - resolvePackageEntry — the npm-resolver helper used by the
15
18
  * bare-specifier resolver
16
19
  *
@@ -35,7 +38,7 @@
35
38
  /**
36
39
  * Preamble string injected ahead of the prebundleOne function in every
37
40
  * pre-bundle facet isolate. Must be passed via IsolatePool's
38
- * `preamble` option.
41
+ * `preamble` option. `jsFnBody` is the staged esbuild adapter.
39
42
  */
40
- export declare const PRE_BUNDLE_PREAMBLE: string;
43
+ export declare function preBundlePreamble(jsFnBody: string): string;
41
44
  //# sourceMappingURL=pre-bundle-preamble.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pre-bundle-preamble.d.ts","sourceRoot":"","sources":["../../src/loaders/pre-bundle-preamble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAyCH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAqCjC,CAAC"}
1
+ {"version":3,"file":"pre-bundle-preamble.d.ts","sourceRoot":"","sources":["../../src/loaders/pre-bundle-preamble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAsCH;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAuC1D"}
@@ -10,7 +10,10 @@
10
10
  * Specifically prebundleOne references:
11
11
  * - ESBUILD_WASM_JS_FN_BODY — function-body string (~117 KiB) that,
12
12
  * when run via new Function(...)(), returns
13
- * the esbuild namespace. SMALL — kept inline.
13
+ * the esbuild namespace. Staged beside the
14
+ * wasm and fetched by the supervisor at
15
+ * pool construction (fetchEsbuildJsFnBody),
16
+ * then spliced in here.
14
17
  * - resolvePackageEntry — the npm-resolver helper used by the
15
18
  * bare-specifier resolver
16
19
  *
@@ -32,7 +35,7 @@
32
35
  * fine — esbuild boot is the dominant cost and re-paying it once on a
33
36
  * deploy is acceptable.
34
37
  */
35
- import { ESBUILD_WASM_JS_FN_BODY, ESBUILD_WASM_VERSION, } from '../esbuild-wasm-bundle.generated.js';
38
+ import { ESBUILD_WASM_VERSION } from '../esbuild-wasm-bundle.generated.js';
36
39
  import { getExportsResolverJS } from '@nimbus-sh/core/_shared/exports-resolver.js';
37
40
  // NOTE: wasm BYTES deliberately NOT in this preamble. They live in
38
41
  // env.ASSETS at /_assets/esbuild-<version>.wasm and are fetched by
@@ -69,16 +72,17 @@ const RESOLVER_HELPERS_SRC = getExportsResolverJS();
69
72
  /**
70
73
  * Preamble string injected ahead of the prebundleOne function in every
71
74
  * pre-bundle facet isolate. Must be passed via IsolatePool's
72
- * `preamble` option.
75
+ * `preamble` option. `jsFnBody` is the staged esbuild adapter.
73
76
  */
74
- export const PRE_BUNDLE_PREAMBLE = `
77
+ export function preBundlePreamble(jsFnBody) {
78
+ return `
75
79
  // ── pre-bundle facet preamble (auto-generated) ──────────────────────────
76
80
  // Esbuild JS helpers (small ~117 KiB). The wasm BYTES are NOT here —
77
- // they're fetched at facet boot via env.SUPERVISOR.getEsbuildWasm() to
78
- // keep the per-dispatch worker module source under ~120 KiB instead of
79
- // ~16 MiB. See this file's header for why.
81
+ // they ride IsolatePool's wasmModules option to keep the per-dispatch
82
+ // worker module source under ~120 KiB instead of ~16 MiB. See this
83
+ // file's header for why.
80
84
  const ESBUILD_WASM_VERSION = ${JSON.stringify(ESBUILD_WASM_VERSION)};
81
- const ESBUILD_WASM_JS_FN_BODY = ${JSON.stringify(ESBUILD_WASM_JS_FN_BODY)};
85
+ const ESBUILD_WASM_JS_FN_BODY = ${JSON.stringify(jsFnBody)};
82
86
 
83
87
  // ── Materialise esbuild namespace at MODULE STARTUP ─────────────────────
84
88
  // workerd's deployed config disallows \"Code generation from strings\" at
@@ -109,3 +113,4 @@ try {
109
113
  ${RESOLVER_HELPERS_SRC}
110
114
  // ── end pre-bundle facet preamble ───────────────────────────────────────
111
115
  `;
116
+ }
@@ -2,12 +2,21 @@
2
2
  * node-shims-artifact.generated.ts — AUTO-GENERATED by
3
3
  * scripts/bundle-node-shims.mjs. DO NOT EDIT.
4
4
  *
5
- * Pins the staged node-compat shim asset (the generateShimsCode() output
6
- * promoted out of the worker bundle). NODE_SHIMS_BUILD_ID is a content-hash
7
- * prefix so cache layers never serve stale bytes after a rebuild;
8
- * NODE_SHIMS_SHA256 is the full digest verified at fetch time.
5
+ * Pins the staged sources of the node-compat layer, promoted out of the worker
6
+ * bundle: the shims, the VFS write ledger and the resident store. Each
7
+ * <NAME>_BUILD_ID is a content-hash prefix so cache layers never serve stale
8
+ * bytes after a rebuild; <NAME>_SHA256 is the full digest verified at fetch time.
9
9
  */
10
+ /** dist/runtime/node-shims.js generateShimsCode() */
10
11
  export declare const NODE_SHIMS_ENTRY: string;
11
12
  export declare const NODE_SHIMS_BUILD_ID: string;
12
13
  export declare const NODE_SHIMS_SHA256: string;
14
+ /** @nimbus-sh/core dist/_shared/vfs-write-ledger.js VFS_WRITE_LEDGER_SOURCE */
15
+ export declare const VFS_WRITE_LEDGER_ENTRY: string;
16
+ export declare const VFS_WRITE_LEDGER_BUILD_ID: string;
17
+ export declare const VFS_WRITE_LEDGER_SHA256: string;
18
+ /** dist/vfs/facet-resident-store.js FACET_RESIDENT_STORE_SOURCE */
19
+ export declare const RESIDENT_STORE_ENTRY: string;
20
+ export declare const RESIDENT_STORE_BUILD_ID: string;
21
+ export declare const RESIDENT_STORE_SHA256: string;
13
22
  //# sourceMappingURL=node-shims-artifact.generated.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"node-shims-artifact.generated.d.ts","sourceRoot":"","sources":["../src/node-shims-artifact.generated.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,gBAAgB,EAAE,MAA0D,CAAC;AAC1F,eAAO,MAAM,mBAAmB,EAAE,MAA2B,CAAC;AAC9D,eAAO,MAAM,iBAAiB,EAAE,MAA2E,CAAC"}
1
+ {"version":3,"file":"node-shims-artifact.generated.d.ts","sourceRoot":"","sources":["../src/node-shims-artifact.generated.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,qDAAqD;AACrD,eAAO,MAAM,gBAAgB,EAAE,MAA0D,CAAC;AAC1F,eAAO,MAAM,mBAAmB,EAAE,MAA2B,CAAC;AAC9D,eAAO,MAAM,iBAAiB,EAAE,MAA2E,CAAC;AAE5G,+EAA+E;AAC/E,eAAO,MAAM,sBAAsB,EAAE,MAAgE,CAAC;AACtG,eAAO,MAAM,yBAAyB,EAAE,MAA2B,CAAC;AACpE,eAAO,MAAM,uBAAuB,EAAE,MAA2E,CAAC;AAElH,mEAAmE;AACnE,eAAO,MAAM,oBAAoB,EAAE,MAA8D,CAAC;AAClG,eAAO,MAAM,uBAAuB,EAAE,MAA2B,CAAC;AAClE,eAAO,MAAM,qBAAqB,EAAE,MAA2E,CAAC"}
@@ -2,11 +2,20 @@
2
2
  * node-shims-artifact.generated.ts — AUTO-GENERATED by
3
3
  * scripts/bundle-node-shims.mjs. DO NOT EDIT.
4
4
  *
5
- * Pins the staged node-compat shim asset (the generateShimsCode() output
6
- * promoted out of the worker bundle). NODE_SHIMS_BUILD_ID is a content-hash
7
- * prefix so cache layers never serve stale bytes after a rebuild;
8
- * NODE_SHIMS_SHA256 is the full digest verified at fetch time.
5
+ * Pins the staged sources of the node-compat layer, promoted out of the worker
6
+ * bundle: the shims, the VFS write ledger and the resident store. Each
7
+ * <NAME>_BUILD_ID is a content-hash prefix so cache layers never serve stale
8
+ * bytes after a rebuild; <NAME>_SHA256 is the full digest verified at fetch time.
9
9
  */
10
- export const NODE_SHIMS_ENTRY = "/_assets/runtime/node-shims-acaa037e6d26ec0d.js";
11
- export const NODE_SHIMS_BUILD_ID = "acaa037e6d26ec0d";
12
- export const NODE_SHIMS_SHA256 = "acaa037e6d26ec0da144c015269c2c0a61cade7a9b82caabcc63a29161e8aac5";
10
+ /** dist/runtime/node-shims.js generateShimsCode() */
11
+ export const NODE_SHIMS_ENTRY = "/_assets/runtime/node-shims-06565b121555c194.js";
12
+ export const NODE_SHIMS_BUILD_ID = "06565b121555c194";
13
+ export const NODE_SHIMS_SHA256 = "06565b121555c1941ec754f7ff2b44f71846c1e9bcc7cf3489e150abd41ab1f1";
14
+ /** @nimbus-sh/core dist/_shared/vfs-write-ledger.js VFS_WRITE_LEDGER_SOURCE */
15
+ export const VFS_WRITE_LEDGER_ENTRY = "/_assets/runtime/vfs-write-ledger-e501e8fc793bc2c1.js";
16
+ export const VFS_WRITE_LEDGER_BUILD_ID = "e501e8fc793bc2c1";
17
+ export const VFS_WRITE_LEDGER_SHA256 = "e501e8fc793bc2c11d7762b7d50e277a1f10e9c4215a03fd34ea99f2266475d1";
18
+ /** dist/vfs/facet-resident-store.js FACET_RESIDENT_STORE_SOURCE */
19
+ export const RESIDENT_STORE_ENTRY = "/_assets/runtime/resident-store-6ffb1939c53d982f.js";
20
+ export const RESIDENT_STORE_BUILD_ID = "6ffb1939c53d982f";
21
+ export const RESIDENT_STORE_SHA256 = "6ffb1939c53d982f364ec3c42098ac13c171ee1a1145fc4123609639f7c8e28a";
@@ -28,10 +28,12 @@ type WritableVfsLike = VfsLike & Pick<CredentialedVfs, 'mkdir' | 'writeFile' | '
28
28
  export declare function npmBinDirPath(nodeModulesPath: string): string;
29
29
  export declare function npmBinManifestPath(nodeModulesPath: string): string;
30
30
  export declare function createNpmBinManifest(entries: NpmBinEntry[]): NpmBinManifest;
31
- export declare function createNpmBinShim(entry: NpmBinEntry): string;
31
+ export declare function createNpmBinShim(entry: NpmBinEntry, shimDir: string): string;
32
32
  export declare function packageBinEntries(pkg: ResolvedPackage, nodeModulesPath: string): NpmBinEntry[];
33
33
  export declare function resolveNpmBin(vfs: VfsLike, cwd: string, name: string): NpmBinResolution | null;
34
34
  export declare function resolveNpmBinFromPath(vfs: VfsLike, cwd: string, envPath: string, name: string): NpmBinResolution | null;
35
+ /** A path-shaped invocation of an executable entry in a `node_modules/.bin` directory; null otherwise. */
36
+ export declare function resolveNpmBinPath(vfs: VfsLike & Pick<CredentialedVfs, 'stat'>, cwd: string, path: string): NpmBinResolution | null;
35
37
  export declare function materializeNpmBinShims(vfs: WritableVfsLike, nodeModulesPath: string, binDir: string): number;
36
38
  export {};
37
39
  //# sourceMappingURL=bin-links.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bin-links.d.ts","sourceRoot":"","sources":["../../src/npm/bin-links.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAIrD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,qBAAqB,yBAAyB,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,wBAAwB,CAAC;IACzC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,aAAa,GAAG,gBAAgB,GAAG,SAAS,CAAC,CAAC;AAC9F,KAAK,eAAe,GAAG,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,WAAW,GAAG,OAAO,CAAC,CAAA;AA8BvF,wBAAgB,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,kBAAkB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,cAAc,CAI3E;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAa3D;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,GAAG,WAAW,EAAE,CAqB9F;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAO9F;AAED,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,gBAAgB,GAAG,IAAI,CAMzB;AAED,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,eAAe,EACpB,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,GACb,MAAM,CAoBR"}
1
+ {"version":3,"file":"bin-links.d.ts","sourceRoot":"","sources":["../../src/npm/bin-links.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAIrD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,qBAAqB,yBAAyB,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,wBAAwB,CAAC;IACzC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,aAAa,GAAG,gBAAgB,GAAG,SAAS,CAAC,CAAC;AAC9F,KAAK,eAAe,GAAG,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,WAAW,GAAG,OAAO,CAAC,CAAA;AA8BvF,wBAAgB,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,kBAAkB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,cAAc,CAI3E;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAU5E;AAWD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,GAAG,WAAW,EAAE,CAqB9F;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAO9F;AAED,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,gBAAgB,GAAG,IAAI,CAMzB;AAED,0GAA0G;AAC1G,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAYlI;AAED,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,eAAe,EACpB,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,GACb,MAAM,CAoBR"}
@@ -45,19 +45,25 @@ export function createNpmBinManifest(entries) {
45
45
  bins[entry.name] = entry;
46
46
  return { version: NPM_BIN_MANIFEST_VERSION, bins };
47
47
  }
48
- export function createNpmBinShim(entry) {
48
+ export function createNpmBinShim(entry, shimDir) {
49
49
  if (isStagedArtifactTarget(entry.targetPath)) {
50
50
  // The runnable bundle is staged in the assets layer; the shell dispatches
51
51
  // it through the staged-artifact runtime by recognizing the sentinel in
52
52
  // the bin manifest. The shim body is only a marker for PATH discovery.
53
53
  return `#!/usr/bin/env node\n// nimbus staged artifact: ${entry.targetPath}\n`;
54
54
  }
55
- // targetPath is a normalized VFS path with no leading slash. require()
56
- // must receive it as absolute (leading "/"), otherwise the runtime's
57
- // resolver treats "home/user/…" as a bare specifier and fails the
58
- // node_modules lookup. Matches how npm-bin-entrypoints runs the manifest
59
- // target ("/" + targetPath).
60
- return `#!/usr/bin/env node\nrequire(${JSON.stringify('/' + entry.targetPath)});\n`;
55
+ // Relative to the shim, as npm's .bin symlinks are, so a node_modules
56
+ // tree that is moved (a staged install renamed into place) still runs.
57
+ return `#!/usr/bin/env node\nrequire(${JSON.stringify(relativeRequest(shimDir, entry.targetPath))});\n`;
58
+ }
59
+ function relativeRequest(fromDir, target) {
60
+ const from = normalizeVfsPath(fromDir).split('/').filter(Boolean);
61
+ const to = normalizeVfsPath(target).split('/').filter(Boolean);
62
+ let common = 0;
63
+ while (common < from.length && common < to.length - 1 && from[common] === to[common])
64
+ common++;
65
+ const rel = [...from.slice(common).map(() => '..'), ...to.slice(common)].join('/');
66
+ return rel.startsWith('../') ? rel : `./${rel}`;
61
67
  }
62
68
  export function packageBinEntries(pkg, nodeModulesPath) {
63
69
  const packagePath = normalizeVfsPath(`${nodeModulesPath}/${pkg.name}`);
@@ -99,6 +105,24 @@ export function resolveNpmBinFromPath(vfs, cwd, envPath, name) {
99
105
  }
100
106
  return null;
101
107
  }
108
+ /** A path-shaped invocation of an executable entry in a `node_modules/.bin` directory; null otherwise. */
109
+ export function resolveNpmBinPath(vfs, cwd, path) {
110
+ const shimPath = resolveVfsPath(path, cwd || '/home/user');
111
+ const slash = shimPath.lastIndexOf('/');
112
+ if (slash < 0)
113
+ return null;
114
+ const binDir = shimPath.slice(0, slash);
115
+ if (!binDir.endsWith('/node_modules/.bin'))
116
+ return null;
117
+ try {
118
+ if ((vfs.stat(shimPath).mode & 0o111) === 0)
119
+ return null;
120
+ }
121
+ catch {
122
+ return null;
123
+ }
124
+ return resolveNpmBinInBinDir(vfs, binDir, shimPath.slice(slash + 1));
125
+ }
102
126
  export function materializeNpmBinShims(vfs, nodeModulesPath, binDir) {
103
127
  const entries = listNpmBinEntries(vfs, normalizeVfsPath(nodeModulesPath));
104
128
  if (entries.length === 0)
@@ -107,7 +131,7 @@ export function materializeNpmBinShims(vfs, nodeModulesPath, binDir) {
107
131
  vfs.mkdir(targetBinDir, { recursive: true });
108
132
  for (const entry of entries) {
109
133
  const shimPath = `${targetBinDir}/${entry.name}`;
110
- vfs.writeFile(shimPath, createNpmBinShim(entry));
134
+ vfs.writeFile(shimPath, createNpmBinShim(entry, targetBinDir));
111
135
  // writeFile creates files 0o644; a bin shim on PATH must be executable
112
136
  // or the shell rejects it ("command not found"). Match the 0o755 the
113
137
  // Phase-6 .bin linker uses. chmod (not a mode arg) so a re-install over
@@ -39,6 +39,11 @@ export interface RegistryCacheEntry {
39
39
  optionalDepsJson?: string;
40
40
  fetchedAt: number;
41
41
  }
42
+ /**
43
+ * One placement in a project's lockfile. The Map key is the placement path
44
+ * (`name` at root, `<dependent>/node_modules/<name>` nested); it is what the
45
+ * `name` column of `pkg_lockfile` holds, whose primary key predates nesting.
46
+ */
42
47
  export interface LockfileEntry {
43
48
  name: string;
44
49
  resolvedVer: string;
@@ -121,8 +126,13 @@ export declare class NpmCache {
121
126
  written: number;
122
127
  failed: number;
123
128
  };
124
- /** Read the lockfile for a project. Returns null if not found. */
129
+ /** Read the lockfile for a project, keyed by placement path. Null if not found. */
125
130
  readLockfile(projectPath: string): Map<string, LockfileEntry> | null;
131
+ /**
132
+ * Every installed package directory (namespace key, no leading slash) and
133
+ * the integrity its tarball was pinned to, across projects.
134
+ */
135
+ installedIntegrities(): Map<string, string>;
126
136
  /** Write/overwrite the lockfile for a project. Atomic via transaction. */
127
137
  writeLockfile(projectPath: string, entries: Map<string, LockfileEntry>, ctx?: DurableObjectState): void;
128
138
  /** Delete lockfile for a project (e.g., after package.json changes). */
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/npm/cache.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,cAAc,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAID,qBAAa,QAAQ;IACnB,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,WAAW,CAAS;gBAEhB,GAAG,EAAE,UAAU;IAM3B,YAAY,IAAI,IAAI;IA6FpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CACwH;IAEhK,OAAO,CAAC,kBAAkB;IAkB1B;;;;;;;;mBAQe;IACf,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI;IA0B1E;;;;;;;;;OASG;IACH,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAU1D,kDAAkD;IAClD,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAUvD,8DAA8D;IAC9D,gBAAgB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAcjD;;;;;;;;;;;;;OAaG;IACH,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IA2BtF,kEAAkE;IAClE,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,IAAI;IAqBpE,0EAA0E;IAC1E,aAAa,CACX,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EACnC,GAAG,CAAC,EAAE,kBAAkB,GACvB,IAAI;IAmCP,wEAAwE;IACxE,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAOzC,oCAAoC;IACpC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAkBtD,sCAAsC;IACtC,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAUzC,oEAAoE;IACpE,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAKxC,2DAA2D;IAC3D,eAAe,IAAI,IAAI;IAOvB;;;;;;;;OAQG;IACH,sBAAsB,CACpB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACrB,wBAAwB,GAAG,IAAI;IAsBlC,iFAAiF;IACjF,sBAAsB,CAAC,KAAK,EAAE,wBAAwB,GAAG,IAAI;IAW7D;8BAC0B;IAC1B,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAOhD,QAAQ,IAAI;QACV,eAAe,EAAE,MAAM,CAAC;QACxB,gBAAgB,EAAE,MAAM,CAAC;QACzB,UAAU,EAAE,MAAM,CAAC;QACnB,oBAAoB,EAAE,MAAM,CAAC;KAC9B;CAaF"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/npm/cache.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,cAAc,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAID,qBAAa,QAAQ;IACnB,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,WAAW,CAAS;gBAEhB,GAAG,EAAE,UAAU;IAM3B,YAAY,IAAI,IAAI;IA6FpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CACwH;IAEhK,OAAO,CAAC,kBAAkB;IAkB1B;;;;;;;;mBAQe;IACf,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI;IA0B1E;;;;;;;;;OASG;IACH,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAU1D,kDAAkD;IAClD,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAUvD,8DAA8D;IAC9D,gBAAgB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAcjD;;;;;;;;;;;;;OAaG;IACH,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IA2BtF,mFAAmF;IACnF,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,IAAI;IAsBpE;;;OAGG;IACH,oBAAoB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAS3C,0EAA0E;IAC1E,aAAa,CACX,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EACnC,GAAG,CAAC,EAAE,kBAAkB,GACvB,IAAI;IAmCP,wEAAwE;IACxE,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAOzC,oCAAoC;IACpC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAkBtD,sCAAsC;IACtC,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAUzC,oEAAoE;IACpE,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAKxC,2DAA2D;IAC3D,eAAe,IAAI,IAAI;IAOvB;;;;;;;;OAQG;IACH,sBAAsB,CACpB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACrB,wBAAwB,GAAG,IAAI;IAsBlC,iFAAiF;IACjF,sBAAsB,CAAC,KAAK,EAAE,wBAAwB,GAAG,IAAI;IAW7D;8BAC0B;IAC1B,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAOhD,QAAQ,IAAI;QACV,eAAe,EAAE,MAAM,CAAC;QACxB,gBAAgB,EAAE,MAAM,CAAC;QACzB,UAAU,EAAE,MAAM,CAAC;QACnB,oBAAoB,EAAE,MAAM,CAAC;KAC9B;CAaF"}