@nimbus-sh/worker 0.6.0 → 0.8.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 (184) hide show
  1. package/README.md +2 -2
  2. package/dist/cirrus-npm-cjs.generated.d.ts +1 -1
  3. package/dist/cirrus-npm-cjs.generated.js +1 -1
  4. package/dist/facets/cirrus-real.d.ts.map +1 -1
  5. package/dist/facets/cirrus-real.js +6 -5
  6. package/dist/facets/compose.d.ts +148 -0
  7. package/dist/facets/compose.d.ts.map +1 -0
  8. package/dist/facets/compose.js +146 -0
  9. package/dist/facets/durable-images.d.ts +9 -5
  10. package/dist/facets/durable-images.d.ts.map +1 -1
  11. package/dist/facets/durable-images.js +17 -7
  12. package/dist/facets/esbuild-bundle-pool.d.ts +49 -0
  13. package/dist/facets/esbuild-bundle-pool.d.ts.map +1 -0
  14. package/dist/facets/esbuild-bundle-pool.js +122 -0
  15. package/dist/facets/exec-telemetry.d.ts +8 -0
  16. package/dist/facets/exec-telemetry.d.ts.map +1 -1
  17. package/dist/facets/manager.d.ts +240 -109
  18. package/dist/facets/manager.d.ts.map +1 -1
  19. package/dist/facets/manager.js +677 -342
  20. package/dist/facets/process.d.ts +20 -16
  21. package/dist/facets/process.d.ts.map +1 -1
  22. package/dist/facets/process.js +59 -28
  23. package/dist/facets/real-vite-fs-shim.js +2 -2
  24. package/dist/facets/real-vite-hmr.d.ts +3 -1
  25. package/dist/facets/real-vite-hmr.d.ts.map +1 -1
  26. package/dist/facets/real-vite-hmr.js +18 -8
  27. package/dist/facets/vite-dev-server.d.ts +25 -47
  28. package/dist/facets/vite-dev-server.d.ts.map +1 -1
  29. package/dist/facets/vite-dev-server.js +185 -219
  30. package/dist/facets/wasm-image-digest.d.ts +25 -0
  31. package/dist/facets/wasm-image-digest.d.ts.map +1 -0
  32. package/dist/facets/wasm-image-digest.js +25 -0
  33. package/dist/facets/wasm-swap-registry.d.ts +51 -92
  34. package/dist/facets/wasm-swap-registry.d.ts.map +1 -1
  35. package/dist/facets/wasm-swap-registry.js +68 -227
  36. package/dist/facets/ws-terminal.d.ts +9 -31
  37. package/dist/facets/ws-terminal.d.ts.map +1 -1
  38. package/dist/facets/ws-terminal.js +58 -51
  39. package/dist/git/network-facet.d.ts.map +1 -1
  40. package/dist/git/network-facet.js +6 -5
  41. package/dist/hosted/commands.d.ts +12 -0
  42. package/dist/hosted/commands.d.ts.map +1 -0
  43. package/dist/hosted/commands.js +1658 -0
  44. package/dist/hosted/runtime.d.ts +114 -0
  45. package/dist/hosted/runtime.d.ts.map +1 -0
  46. package/dist/hosted/runtime.js +288 -0
  47. package/dist/hosted/services.d.ts +40 -0
  48. package/dist/hosted/services.d.ts.map +1 -0
  49. package/dist/hosted/services.js +512 -0
  50. package/dist/loaders/child-process/spawn-pool.d.ts +3 -2
  51. package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -1
  52. package/dist/loaders/child-process/spawn-pool.js +3 -2
  53. package/dist/loaders/generated-workers.d.ts +2 -2
  54. package/dist/loaders/generated-workers.d.ts.map +1 -1
  55. package/dist/loaders/generated-workers.js +3 -3
  56. package/dist/loaders/npm-resolve-preamble.d.ts +3 -6
  57. package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -1
  58. package/dist/loaders/npm-resolve-preamble.js +34 -108
  59. package/dist/node-shims-artifact.generated.js +3 -3
  60. package/dist/npm/install-batch-facet.d.ts +3 -2
  61. package/dist/npm/install-batch-facet.d.ts.map +1 -1
  62. package/dist/npm/install-batch-facet.js +45 -15
  63. package/dist/npm/installer.d.ts +22 -17
  64. package/dist/npm/installer.d.ts.map +1 -1
  65. package/dist/npm/installer.js +209 -193
  66. package/dist/npm/pre-bundle-facet.d.ts +1 -1
  67. package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
  68. package/dist/npm/pre-bundle-facet.js +1 -1
  69. package/dist/npm/resolve-facet.d.ts +6 -0
  70. package/dist/npm/resolve-facet.d.ts.map +1 -1
  71. package/dist/npm/resolve-one-facet.d.ts +21 -20
  72. package/dist/npm/resolve-one-facet.d.ts.map +1 -1
  73. package/dist/npm/resolve-one-facet.js +85 -84
  74. package/dist/npm/semver.d.ts +59 -0
  75. package/dist/npm/semver.d.ts.map +1 -0
  76. package/dist/npm/semver.js +226 -0
  77. package/dist/router/remote-api.js +31 -1
  78. package/dist/runtime/bash-repl.d.ts +1 -1
  79. package/dist/runtime/bash-repl.d.ts.map +1 -1
  80. package/dist/runtime/bash-repl.js +38 -4
  81. package/dist/runtime/bun-runner.js +1 -1
  82. package/dist/runtime/html-entrypoint.d.ts +7 -0
  83. package/dist/runtime/html-entrypoint.d.ts.map +1 -1
  84. package/dist/runtime/html-entrypoint.js +18 -2
  85. package/dist/runtime/node-runner.d.ts +4 -1
  86. package/dist/runtime/node-runner.d.ts.map +1 -1
  87. package/dist/runtime/node-runner.js +9 -2
  88. package/dist/runtime/node-shims.d.ts.map +1 -1
  89. package/dist/runtime/node-shims.js +305 -29
  90. package/dist/runtime/opencode-facet-runner.js +16 -16
  91. package/dist/runtime/package-manager.d.ts +35 -122
  92. package/dist/runtime/package-manager.d.ts.map +1 -1
  93. package/dist/runtime/package-manager.js +61 -596
  94. package/dist/runtime/process-logs-api.d.ts +1 -1
  95. package/dist/runtime/process-logs-api.d.ts.map +1 -1
  96. package/dist/runtime/process-logs-api.js +1 -1
  97. package/dist/runtime/python-repl.d.ts +2 -1
  98. package/dist/runtime/python-repl.d.ts.map +1 -1
  99. package/dist/runtime/python-repl.js +82 -59
  100. package/dist/runtime/repl-session.d.ts +9 -47
  101. package/dist/runtime/repl-session.d.ts.map +1 -1
  102. package/dist/runtime/repl-session.js +105 -105
  103. package/dist/runtime/runtime-catalog.d.ts +13 -0
  104. package/dist/runtime/runtime-catalog.d.ts.map +1 -1
  105. package/dist/runtime/runtime-catalog.js +88 -0
  106. package/dist/session/agent.d.ts +1 -21
  107. package/dist/session/agent.d.ts.map +1 -1
  108. package/dist/session/ai.d.ts +5 -1
  109. package/dist/session/ai.d.ts.map +1 -1
  110. package/dist/session/ai.js +7 -0
  111. package/dist/session/helpers.d.ts +38 -0
  112. package/dist/session/helpers.d.ts.map +1 -1
  113. package/dist/session/helpers.js +76 -0
  114. package/dist/session/hibernation.d.ts +2 -1
  115. package/dist/session/hibernation.d.ts.map +1 -1
  116. package/dist/session/hibernation.js +7 -4
  117. package/dist/session/init-phases.d.ts +1 -1
  118. package/dist/session/init-phases.d.ts.map +1 -1
  119. package/dist/session/init-phases.js +2 -12
  120. package/dist/session/init.d.ts +15 -36
  121. package/dist/session/init.d.ts.map +1 -1
  122. package/dist/session/init.js +50 -2327
  123. package/dist/session/loopback.d.ts +2 -29
  124. package/dist/session/loopback.d.ts.map +1 -1
  125. package/dist/session/loopback.js +3 -27
  126. package/dist/session/nimbus-session.d.ts +77 -34
  127. package/dist/session/nimbus-session.d.ts.map +1 -1
  128. package/dist/session/nimbus-session.js +126 -514
  129. package/dist/session/npm-install-port.d.ts +18 -0
  130. package/dist/session/npm-install-port.d.ts.map +1 -0
  131. package/dist/session/npm-install-port.js +37 -0
  132. package/dist/session/port-capability.d.ts +44 -0
  133. package/dist/session/port-capability.d.ts.map +1 -1
  134. package/dist/session/port-capability.js +110 -0
  135. package/dist/session/programmatic.d.ts +36 -43
  136. package/dist/session/programmatic.d.ts.map +1 -1
  137. package/dist/session/programmatic.js +109 -115
  138. package/dist/session/routes.d.ts +30 -17
  139. package/dist/session/routes.d.ts.map +1 -1
  140. package/dist/session/routes.js +42 -131
  141. package/dist/session/rpc.d.ts +15 -15
  142. package/dist/session/rpc.d.ts.map +1 -1
  143. package/dist/session/rpc.js +98 -49
  144. package/dist/session/serving-port.d.ts +27 -0
  145. package/dist/session/serving-port.d.ts.map +1 -0
  146. package/dist/session/serving-port.js +27 -0
  147. package/dist/session/start-real-vite.d.ts +12 -0
  148. package/dist/session/start-real-vite.d.ts.map +1 -1
  149. package/dist/session/start-real-vite.js +4 -4
  150. package/dist/session/supervisor-op.d.ts +4 -4
  151. package/dist/session/supervisor-op.d.ts.map +1 -1
  152. package/dist/session/supervisor-op.js +24 -10
  153. package/dist/session/supervisor-rpc.d.ts +7 -7
  154. package/dist/session/supervisor-rpc.d.ts.map +1 -1
  155. package/dist/session/supervisor-rpc.js +4 -0
  156. package/dist/session/vite-command.d.ts +18 -0
  157. package/dist/session/vite-command.d.ts.map +1 -0
  158. package/dist/session/vite-command.js +609 -0
  159. package/dist/session/ws.d.ts +61 -0
  160. package/dist/session/ws.d.ts.map +1 -1
  161. package/dist/session/ws.js +122 -12
  162. package/dist/shell/npm-bin-entrypoints.d.ts +0 -35
  163. package/dist/shell/npm-bin-entrypoints.d.ts.map +1 -1
  164. package/dist/shell/npm-bin-entrypoints.js +12 -85
  165. package/dist/workspace-host.d.ts +6 -0
  166. package/dist/workspace-host.d.ts.map +1 -0
  167. package/dist/workspace-host.js +5 -0
  168. package/dist/workspace.d.ts +2 -0
  169. package/dist/workspace.d.ts.map +1 -0
  170. package/dist/workspace.js +1 -0
  171. package/package.json +34 -9
  172. package/public/_assets/runtime/{node-shims-9e1380d9ee430fcc.js → node-shims-8f8c64edd2a1f0f5.js} +305 -29
  173. package/public/index.html +1 -1
  174. package/scripts/bundle-facet-workers.mjs +1 -1
  175. package/scripts/bundle-npm-cjs.mjs +2 -2
  176. package/dist/facets/on-demand-bundle-gate.d.ts +0 -65
  177. package/dist/facets/on-demand-bundle-gate.d.ts.map +0 -1
  178. package/dist/facets/on-demand-bundle-gate.js +0 -125
  179. package/dist/npm/install-args.d.ts +0 -21
  180. package/dist/npm/install-args.d.ts.map +0 -1
  181. package/dist/npm/install-args.js +0 -70
  182. package/dist/npm/npm-log.d.ts +0 -31
  183. package/dist/npm/npm-log.d.ts.map +0 -1
  184. package/dist/npm/npm-log.js +0 -51
@@ -11,12 +11,12 @@
11
11
  * helpers by name.
12
12
  *
13
13
  * Tar-stream symbols: parseTarHeader, streamTarEntries,
14
- * readableStreamToAsyncIterable, MAX_FILE_BYTES.
14
+ * streamPackageEntries, readableStreamToAsyncIterable, MAX_FILE_BYTES.
15
15
  * W7-frame symbols: encodeWriteBatchStream, decodeWriteBatchStream,
16
16
  * W7_MAGIC, W7_MAX_RECORD_BYTES.
17
17
  *
18
- * Tar size: 4.15 KiB
18
+ * Tar size: 4.62 KiB
19
19
  * W7 size: 28.97 KiB
20
20
  */
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 = name.replace(/^package\\//, \"\");\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}";
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
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);\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) {\n this.reader = reader;\n }\n reader;\n done = false;\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.reader.read(new Uint8Array(length - offset));\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 reader.read();\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};";
@@ -8,13 +8,11 @@
8
8
  * re-declared in the preamble.
9
9
  *
10
10
  * The resolver facets reference the following preamble symbols:
11
- * - SHOULD_SKIP_PACKAGE(name, frameworkAware) → boolean
12
11
  * - SHOULD_SWAP(name) → swap entry | undefined
13
12
  * - SHOULD_REJECT_FAIL(name) → reject entry | undefined
14
- * - SHOULD_WARN_SKIP_TRANSITIVE(name) → reject entry | undefined
15
13
  * - NATIVE_EXECUTABLE_REJECT(pkg) → reject entry | undefined
16
14
  * - IS_OPTIONAL_NATIVE_BINDING(pkg) → boolean
17
- * - PARSE_SEMVER(v) → [major, minor, patch] | null
15
+ * - PARSE_SEMVER(v) → [major, minor, patch, prerelease[]] | null
18
16
  * - COMPARE_SEMVER(a, b) → number
19
17
  * - SATISFIES_RANGE(version, range) → boolean
20
18
  * - RESOLVE_VERSION(versions, range) → string | null
@@ -26,9 +24,8 @@
26
24
  * (`tests/unit/package-abi-policy.mjs`) extracts the injected policy and
27
25
  * asserts equality with the supervisor module.
28
26
  *
29
- * The semver helpers are pasted from src/npm/resolver.ts and MUST stay
30
- * byte-equivalent — divergence would mean the facet picks different
31
- * versions than the in-supervisor path.
27
+ * The semver helpers are embedded from src/npm/semver.ts the same way, so
28
+ * the facet picks versions with the supervisor's own implementation.
32
29
  *
33
30
  * Preamble bytes are part of the loader-cache key for IsolatePool —
34
31
  * any edit invalidates the warm slot and forces a re-load on next
@@ -1 +1 @@
1
- {"version":3,"file":"npm-resolve-preamble.d.ts","sourceRoot":"","sources":["../../src/loaders/npm-resolve-preamble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAcH,eAAO,MAAM,oBAAoB,EAAE,MA4JlC,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,MAmFlC,CAAC"}
@@ -8,13 +8,11 @@
8
8
  * re-declared in the preamble.
9
9
  *
10
10
  * The resolver facets reference the following preamble symbols:
11
- * - SHOULD_SKIP_PACKAGE(name, frameworkAware) → boolean
12
11
  * - SHOULD_SWAP(name) → swap entry | undefined
13
12
  * - SHOULD_REJECT_FAIL(name) → reject entry | undefined
14
- * - SHOULD_WARN_SKIP_TRANSITIVE(name) → reject entry | undefined
15
13
  * - NATIVE_EXECUTABLE_REJECT(pkg) → reject entry | undefined
16
14
  * - IS_OPTIONAL_NATIVE_BINDING(pkg) → boolean
17
- * - PARSE_SEMVER(v) → [major, minor, patch] | null
15
+ * - PARSE_SEMVER(v) → [major, minor, patch, prerelease[]] | null
18
16
  * - COMPARE_SEMVER(a, b) → number
19
17
  * - SATISFIES_RANGE(version, range) → boolean
20
18
  * - RESOLVE_VERSION(versions, range) → string | null
@@ -26,30 +24,28 @@
26
24
  * (`tests/unit/package-abi-policy.mjs`) extracts the injected policy and
27
25
  * asserts equality with the supervisor module.
28
26
  *
29
- * The semver helpers are pasted from src/npm/resolver.ts and MUST stay
30
- * byte-equivalent — divergence would mean the facet picks different
31
- * versions than the in-supervisor path.
27
+ * The semver helpers are embedded from src/npm/semver.ts the same way, so
28
+ * the facet picks versions with the supervisor's own implementation.
32
29
  *
33
30
  * Preamble bytes are part of the loader-cache key for IsolatePool —
34
31
  * any edit invalidates the warm slot and forces a re-load on next
35
32
  * dispatch. Acceptable cost for a one-shot resolver phase.
36
33
  */
37
- import { PACKAGE_ABI_POLICY, policyApplyStagedArtifact, policyIsOptionalNativeBinding, policyLookupReject, policyLookupStagedArtifact, policyLookupSwap, policyNativeArtifactReject, policyShouldSkipPackage, STAGED_ARTIFACT_BIN_PREFIX, } from '../facets/wasm-swap-registry.js';
34
+ import { PACKAGE_ABI_POLICY, policyApplyStagedArtifact, policyIsOptionalNativeBinding, policyLookupReject, policyLookupStagedArtifact, policyLookupSwap, policyNativeBinAdvisory, policyNativePlatformReject, STAGED_ARTIFACT_BIN_PREFIX, } from '../facets/wasm-swap-registry.js';
35
+ import { compareSemver, parseSemver, resolveVersion, satisfiesRange, semverComparators, } from '../npm/semver.js';
36
+ import { parseRegistryRequest } from '../npm/resolve-one-facet.js';
38
37
  export const NPM_RESOLVE_PREAMBLE = `
39
38
  // ── Package ABI policy (serialized from src/facets/wasm-swap-registry.ts) ──
40
39
  // Generated — do not edit here. PACKAGE_ABI_POLICY is the single source
41
40
  // of truth; tests/unit/package-abi-policy.mjs enforces parity.
42
41
  const __NIMBUS_PACKAGE_ABI_POLICY = ${JSON.stringify(PACKAGE_ABI_POLICY)};
43
- const __policyShouldSkipPackage = ${policyShouldSkipPackage.toString()};
44
42
  const __policyLookupSwap = ${policyLookupSwap.toString()};
45
43
  const __policyLookupReject = ${policyLookupReject.toString()};
46
- const __policyNativeArtifactReject = ${policyNativeArtifactReject.toString()};
47
- const __policyIsOptionalNativeBinding = ${policyIsOptionalNativeBinding.toString()};
44
+ const __policyNativePlatformReject = ${policyNativePlatformReject.toString()};
45
+ const __policyNativeBinAdvisory = ${policyNativeBinAdvisory.toString()};
48
46
  const __policyLookupStagedArtifact = ${policyLookupStagedArtifact.toString()};
49
47
  const __policyApplyStagedArtifact = ${policyApplyStagedArtifact.toString()};
50
- function SHOULD_SKIP_PACKAGE(name, frameworkAware) {
51
- return __policyShouldSkipPackage(__NIMBUS_PACKAGE_ABI_POLICY, name, !!frameworkAware);
52
- }
48
+ const __policyIsOptionalNativeBinding = ${policyIsOptionalNativeBinding.toString()};
53
49
  function SHOULD_SWAP(name) {
54
50
  return __policyLookupSwap(__NIMBUS_PACKAGE_ABI_POLICY, name);
55
51
  }
@@ -58,13 +54,15 @@ function SHOULD_REJECT_FAIL(name) {
58
54
  if (r && r.transitive === 'fail') return r;
59
55
  return undefined;
60
56
  }
61
- function SHOULD_WARN_SKIP_TRANSITIVE(name) {
62
- const r = __policyLookupReject(__NIMBUS_PACKAGE_ABI_POLICY, name);
63
- if (r && r.transitive === 'warn') return r;
64
- return undefined;
65
- }
66
57
  function NATIVE_EXECUTABLE_REJECT(pkg) {
67
- return __policyNativeArtifactReject(__NIMBUS_PACKAGE_ABI_POLICY, pkg);
58
+ return __policyNativeBinAdvisory(__NIMBUS_PACKAGE_ABI_POLICY, pkg)
59
+ ?? __policyNativePlatformReject(__NIMBUS_PACKAGE_ABI_POLICY, pkg);
60
+ }
61
+ function NATIVE_PLATFORM_REJECT(pkg) {
62
+ return __policyNativePlatformReject(__NIMBUS_PACKAGE_ABI_POLICY, pkg);
63
+ }
64
+ function NATIVE_BIN_ADVISORY(pkg) {
65
+ return __policyNativeBinAdvisory(__NIMBUS_PACKAGE_ABI_POLICY, pkg);
68
66
  }
69
67
  function IS_OPTIONAL_NATIVE_BINDING(pkg) {
70
68
  return __policyIsOptionalNativeBinding(__NIMBUS_PACKAGE_ABI_POLICY, pkg);
@@ -101,94 +99,22 @@ function __DRAIN_EVENTS() {
101
99
  return out;
102
100
  }
103
101
 
104
- // ── Semver helpers (pasted from src/npm-resolver.ts:83-202) ─────────────
105
- function PARSE_SEMVER(v) {
106
- const m = v.replace(/^v/, '').match(/^(\\d+)\\.(\\d+)\\.(\\d+)/);
107
- return m ? [parseInt(m[1]), parseInt(m[2]), parseInt(m[3])] : null;
108
- }
109
-
110
- function COMPARE_SEMVER(a, b) {
111
- return a[0] - b[0] || a[1] - b[1] || a[2] - b[2];
112
- }
113
-
114
- function __SATISFIES_COMPARATOR(version, comparator) {
115
- const comp = comparator.trim();
116
- if (!comp || comp === '*' || comp === 'latest' || comp === '' || comp === 'x') return true;
117
- let op = '';
118
- let rangeStr = comp;
119
- const prefixMatch = comp.match(/^([~^]|>=|<=|>|<|=)\\s*/);
120
- if (prefixMatch) {
121
- op = prefixMatch[1];
122
- rangeStr = comp.slice(prefixMatch[0].length);
123
- }
124
- rangeStr = rangeStr.replace(/\\.x/g, '.0');
125
- if (rangeStr.match(/^\\d+$/)) rangeStr += '.0.0';
126
- else if (rangeStr.match(/^\\d+\\.\\d+$/)) rangeStr += '.0';
127
- const vParts = PARSE_SEMVER(version);
128
- const rParts = PARSE_SEMVER(rangeStr);
129
- if (!vParts || !rParts) return false;
130
- const cmp = COMPARE_SEMVER(vParts, rParts);
131
- switch (op) {
132
- case '^': {
133
- if (rParts[0] > 0) {
134
- return vParts[0] === rParts[0] && cmp >= 0;
135
- }
136
- if (rParts[1] > 0) {
137
- return vParts[0] === 0 && vParts[1] === rParts[1] && cmp >= 0;
138
- }
139
- return vParts[0] === 0 && vParts[1] === 0 && vParts[2] === rParts[2];
140
- }
141
- case '~': {
142
- return vParts[0] === rParts[0] && vParts[1] === rParts[1] && vParts[2] >= rParts[2];
143
- }
144
- case '>=': return cmp >= 0;
145
- case '>': return cmp > 0;
146
- case '<=': return cmp <= 0;
147
- case '<': return cmp < 0;
148
- case '=': return cmp === 0;
149
- default: {
150
- if (comp.match(/^\\d/)) {
151
- return cmp === 0;
152
- }
153
- return cmp === 0;
154
- }
155
- }
156
- }
157
-
158
- function SATISFIES_RANGE(version, range) {
159
- const trimmed = range.trim();
160
- if (!trimmed || trimmed === '*' || trimmed === 'latest' || trimmed === '') return true;
161
- const orParts = trimmed.split(/\\s*\\|\\|\\s*/);
162
- for (const orPart of orParts) {
163
- const hyphen = orPart.match(/^(\\S+)\\s+-\\s+(\\S+)$/);
164
- if (hyphen) {
165
- if (__SATISFIES_COMPARATOR(version, '>=' + hyphen[1]) &&
166
- __SATISFIES_COMPARATOR(version, '<=' + hyphen[2])) {
167
- return true;
168
- }
169
- continue;
170
- }
171
- const andParts = orPart.trim().split(/\\s+/);
172
- const allMatch = andParts.every((part) => __SATISFIES_COMPARATOR(version, part));
173
- if (allMatch) return true;
174
- }
175
- return false;
176
- }
177
-
178
- function RESOLVE_VERSION(versions, range) {
179
- if (!range || range === 'latest' || range === '*' || range === '') return null;
180
- const matching = versions.filter((v) => {
181
- if (v.includes('-') && !range.includes('-')) return false;
182
- return SATISFIES_RANGE(v, range);
183
- });
184
- if (matching.length === 0) return null;
185
- matching.sort((a, b) => {
186
- const ap = PARSE_SEMVER(a);
187
- const bp = PARSE_SEMVER(b);
188
- if (!ap || !bp) return 0;
189
- return COMPARE_SEMVER(bp, ap);
190
- });
191
- return matching[0];
192
- }
102
+ // ── Semver (embedded from src/npm/semver.ts) ────────────────────────────
103
+ // Generated — do not edit here. npm/semver.ts is the single implementation;
104
+ // tests/unit/npm-semver.mjs asserts the embedded functions answer exactly as
105
+ // the exported ones do.
106
+ ${parseSemver.toString()}
107
+ ${compareSemver.toString()}
108
+ ${semverComparators.toString()}
109
+ ${satisfiesRange.toString()}
110
+ ${resolveVersion.toString()}
111
+ // ── Spec parsing (embedded from src/npm/resolve-one-facet.ts) ───────────
112
+ // Generated the same way — the facet body references the bare
113
+ // parseRegistryRequest binding.
114
+ ${parseRegistryRequest.toString()}
115
+ function PARSE_SEMVER(v) { return parseSemver(v); }
116
+ function COMPARE_SEMVER(a, b) { return compareSemver(a, b); }
117
+ function SATISFIES_RANGE(version, range) { return satisfiesRange(version, range); }
118
+ function RESOLVE_VERSION(versions, range) { return resolveVersion(versions, range); }
193
119
  // ── end npm-resolve preamble ────────────────────────────────────────────
194
120
  `;
@@ -7,6 +7,6 @@
7
7
  * prefix so cache layers never serve stale bytes after a rebuild;
8
8
  * NODE_SHIMS_SHA256 is the full digest verified at fetch time.
9
9
  */
10
- export const NODE_SHIMS_ENTRY = "/_assets/runtime/node-shims-9e1380d9ee430fcc.js";
11
- export const NODE_SHIMS_BUILD_ID = "9e1380d9ee430fcc";
12
- export const NODE_SHIMS_SHA256 = "9e1380d9ee430fcca4e8700a97da811eee0fe7e9cab4c6357e94c3fc21efa2d9";
10
+ export const NODE_SHIMS_ENTRY = "/_assets/runtime/node-shims-8f8c64edd2a1f0f5.js";
11
+ export const NODE_SHIMS_BUILD_ID = "8f8c64edd2a1f0f5";
12
+ export const NODE_SHIMS_SHA256 = "8f8c64edd2a1f0f54037793c4f2dc8d77aca0da808aa5fdb9b1c179208c191cc";
@@ -33,8 +33,9 @@
33
33
  * Stability invariants (cloudflare-parallel):
34
34
  * - No `this` references.
35
35
  * - No closure capture other than args + preamble names.
36
- * - Preamble symbols (streamTarEntries, readableStreamToAsyncIterable,
37
- * MAX_FILE_BYTES) referenced via @ts-ignore.
36
+ * - Preamble symbols (streamPackageEntries, streamTarEntries,
37
+ * readableStreamToAsyncIterable, MAX_FILE_BYTES) referenced via
38
+ * @ts-ignore.
38
39
  */
39
40
  import type { FacetPackageSpec } from './install-facet.js';
40
41
  import type { WriteBatchStreamResult } from '@nimbus-sh/core/vfs/sqlite-vfs.js';
@@ -1 +1 @@
1
- {"version":3,"file":"install-batch-facet.d.ts","sourceRoot":"","sources":["../../src/npm/install-batch-facet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAShF,MAAM,WAAW,gBAAgB;IAC/B;mDAC+C;IAC/C,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,mFAAmF;IACnF,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACrC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,UAAU,EAAE,sBAAsB,EAAE,CAAC;IACrC,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB;uFACmF;IACnF,aAAa,EAAE;QACb,iBAAiB,EAAE,MAAM,CAAC;QAC1B,sBAAsB,EAAE,MAAM,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC;QACrB;;uDAE+C;QAC/C,wBAAwB,EAAE,MAAM,CAAC;QACjC,0BAA0B,EAAE,MAAM,CAAC;QACnC;;;0DAGkD;QAClD,WAAW,EAAE,MAAM,CAAC;QACpB,kBAAkB,EAAE,MAAM,CAAC;QAC3B;;;;qEAI6D;QAC7D,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF;;;;;;;;;;OAUG;IACH,eAAe,EAAE,KAAK,CAClB;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAC9E;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,SAAS,CAAA;KAAE,CACnE,CAAC;CACH;AAUD,eAAO,MAAM,sBAAsB,GACjC,OAAO,gBAAgB,EACvB,KAAK;IACH,UAAU,EAAE;QAIV,gBAAgB,EAAE,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;QAK1F,gBAAgB,CAAC,EAAE,CACjB,SAAS,EAAE,MAAM,KACd,OAAO,CAAC;YACX,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;YACzB,MAAM,EAAE,KAAK,CACT;gBAAE,IAAI,EAAE,KAAK,CAAC;gBAAC,IAAI,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,MAAM,CAAA;aAAE,GAC/D;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,IAAI,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAA;aAAE,CACpD,CAAC;SACH,CAAC,CAAC;QACH,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KAC7F,CAAC;CACH,KACA,OAAO,CAAC,kBAAkB,CA0zB5B,CAAC"}
1
+ {"version":3,"file":"install-batch-facet.d.ts","sourceRoot":"","sources":["../../src/npm/install-batch-facet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAShF,MAAM,WAAW,gBAAgB;IAC/B;mDAC+C;IAC/C,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,mFAAmF;IACnF,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACrC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,UAAU,EAAE,sBAAsB,EAAE,CAAC;IACrC,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB;uFACmF;IACnF,aAAa,EAAE;QACb,iBAAiB,EAAE,MAAM,CAAC;QAC1B,sBAAsB,EAAE,MAAM,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC;QACrB;;uDAE+C;QAC/C,wBAAwB,EAAE,MAAM,CAAC;QACjC,0BAA0B,EAAE,MAAM,CAAC;QACnC;;;0DAGkD;QAClD,WAAW,EAAE,MAAM,CAAC;QACpB,kBAAkB,EAAE,MAAM,CAAC;QAC3B;;;;qEAI6D;QAC7D,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF;;;;;;;;;;OAUG;IACH,eAAe,EAAE,KAAK,CAClB;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAC9E;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,SAAS,CAAA;KAAE,CACnE,CAAC;CACH;AAUD,eAAO,MAAM,sBAAsB,GACjC,OAAO,gBAAgB,EACvB,KAAK;IACH,UAAU,EAAE;QAIV,gBAAgB,EAAE,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;QAK1F,gBAAgB,CAAC,EAAE,CACjB,SAAS,EAAE,MAAM,KACd,OAAO,CAAC;YACX,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;YACzB,MAAM,EAAE,KAAK,CACT;gBAAE,IAAI,EAAE,KAAK,CAAC;gBAAC,IAAI,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,MAAM,CAAA;aAAE,GAC/D;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,IAAI,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAA;aAAE,CACpD,CAAC;SACH,CAAC,CAAC;QACH,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KAC7F,CAAC;CACH,KACA,OAAO,CAAC,kBAAkB,CAs1B5B,CAAC"}
@@ -33,16 +33,17 @@
33
33
  * Stability invariants (cloudflare-parallel):
34
34
  * - No `this` references.
35
35
  * - No closure capture other than args + preamble names.
36
- * - Preamble symbols (streamTarEntries, readableStreamToAsyncIterable,
37
- * MAX_FILE_BYTES) referenced via @ts-ignore.
36
+ * - Preamble symbols (streamPackageEntries, streamTarEntries,
37
+ * readableStreamToAsyncIterable, MAX_FILE_BYTES) referenced via
38
+ * @ts-ignore.
38
39
  */
39
40
  // ── Facet function ──────────────────────────────────────────────────────
40
41
  //
41
42
  // Runs inside a IsolatePool isolate. Serialised via fn.toString();
42
- // the helpers it references at top-level scope (streamTarEntries,
43
- // readableStreamToAsyncIterable, MAX_FILE_BYTES) are NOT in the facet's
44
- // lexical scope — the pool injects them via the preamble. No static
45
- // imports of those names; references are bare identifiers.
43
+ // the helpers it references at top-level scope (streamPackageEntries,
44
+ // streamTarEntries, readableStreamToAsyncIterable, MAX_FILE_BYTES) are NOT
45
+ // in the facet's lexical scope — the pool injects them via the preamble.
46
+ // No static imports of those names; references are bare identifiers.
46
47
  export const installPackagesInFacet = async function installPackagesInFacet(batch, env) {
47
48
  const tBatchStart = Date.now();
48
49
  if (!batch || typeof batch !== 'object' || !Array.isArray(batch.packages)) {
@@ -121,6 +122,10 @@ export const installPackagesInFacet = async function installPackagesInFacet(batc
121
122
  let sharedChunks = [];
122
123
  let sharedBufferedBytes = 0;
123
124
  let sharedOwners = new Set();
125
+ // Directories staged into a wave, shard-wide. A directory is staged once
126
+ // per shard, not once per package — and a wave that fails removes its
127
+ // directories from this set so they are staged again (see doSharedFlush).
128
+ const landedDirs = new Set();
124
129
  const ownerWaves = new Map();
125
130
  const ownersWithCompletionMarker = new Set();
126
131
  const completionMarkers = new Map();
@@ -135,12 +140,20 @@ export const installPackagesInFacet = async function installPackagesInFacet(batc
135
140
  // for too long", so the schedule has to outlast a queue that deep; the
136
141
  // whole-batch timeout is 10 minutes, which bounds it.
137
142
  const WAVE_RETRY_BACKOFF_MS = [250, 1000, 3000, 6000, 12000, 20000];
143
+ // "Network connection lost" is the RPC transport between this shard and
144
+ // the coordinator DO dropping under load — the same class: the wave may
145
+ // or may not have run, and re-sending identical path-keyed bytes is safe
146
+ // either way. It was the dominant shard failure on a 629-package install
147
+ // (Markflow): one lost wave failed every package that had contributed to
148
+ // it, and the directories that wave carried never landed, so later waves
149
+ // of unrelated packages failed with ENOENT on those parents.
138
150
  const isSheddableWaveError = (message) => {
139
151
  const m = message.toLowerCase();
140
152
  return m.includes('overloaded')
141
153
  || m.includes('reset because its code was updated')
142
154
  || m.includes('starting up durable object storage')
143
- || (m.includes('storage operation') && m.includes('reset'));
155
+ || (m.includes('storage operation') && m.includes('reset'))
156
+ || m.includes('network connection lost');
144
157
  };
145
158
  // Mutex: only one flush runs at a time. Concurrent installs awaiting
146
159
  // flush() will line up behind this promise and resolve in arrival
@@ -177,7 +190,7 @@ export const installPackagesInFacet = async function installPackagesInFacet(batc
177
190
  // with every contributing package before awaiting the RPC, so a package
178
191
  // cannot report success while another package happens to be the caller
179
192
  // that triggered its shared flush.
180
- const wave = (async () => {
193
+ const sendWave = async () => {
181
194
  for (let attempt = 0;; attempt++) {
182
195
  try {
183
196
  // Each attempt encodes its OWN bytes. The encoder hands chunk
@@ -212,6 +225,19 @@ export const installPackagesInFacet = async function installPackagesInFacet(batc
212
225
  await new Promise((rs) => setTimeout(rs, delayMs));
213
226
  }
214
227
  }
228
+ };
229
+ const dirsInWave = inodesNow.filter((inode) => inode.isDir).map((inode) => inode.path);
230
+ const wave = (async () => {
231
+ const outcome = await sendWave();
232
+ // A wave that did not land took its directory inodes with it. Every
233
+ // package that staged one of them into this wave believes it exists;
234
+ // forget them so the next file under such a directory re-stages the
235
+ // chain into its own wave instead of failing ENOENT on a parent that
236
+ // was never written.
237
+ if (!outcome.ok)
238
+ for (const dir of dirsInWave)
239
+ landedDirs.delete(dir);
240
+ return outcome;
215
241
  })();
216
242
  for (const owner of ownersNow) {
217
243
  let waves = ownerWaves.get(owner);
@@ -647,7 +673,6 @@ export const installPackagesInFacet = async function installPackagesInFacet(batc
647
673
  // not per package. Per-package totals stay local to the result object.
648
674
  let totalFileInodes = 0;
649
675
  let totalBytesWritten = 0;
650
- const dirSet = new Set();
651
676
  let completionMarker = null;
652
677
  // Stage `installRoot` and every directory down to `dirPath` (inclusive),
653
678
  // root-to-leaf, BEFORE any file that needs them. The credentialed
@@ -663,9 +688,13 @@ export const installPackagesInFacet = async function installPackagesInFacet(batc
663
688
  const segs = suffix ? suffix.split('/') : [];
664
689
  for (let i = 0; i <= segs.length; i++) {
665
690
  const d = i === 0 ? installRoot : installRoot + '/' + segs.slice(0, i).join('/');
666
- if (dirSet.has(d))
691
+ if (landedDirs.has(d)) {
692
+ // Staged by an earlier wave of this shard. This owner's files
693
+ // depend on it, so this owner must see that wave's outcome too.
694
+ sharedOwners.add(ownerId);
667
695
  continue;
668
- dirSet.add(d);
696
+ }
697
+ landedDirs.add(d);
669
698
  await enqueueSharedDirectory(ownerId, d, spec.mtime);
670
699
  }
671
700
  };
@@ -685,10 +714,11 @@ export const installPackagesInFacet = async function installPackagesInFacet(batc
685
714
  // packages whose only member is package.json.
686
715
  await enqueueDirsUpTo(pkgDir);
687
716
  // @ts-ignore — preamble symbol.
688
- for await (const entry of streamTarEntries(asyncIter, onSkip)) {
689
- // entry.name is already canonicalized (no "."/".." segments) by
690
- // the tar parser, so joining under the canonical pkgDir yields a
691
- // canonical path the w7-frame writer accepts.
717
+ for await (const entry of streamPackageEntries(asyncIter, onSkip)) {
718
+ // entry.name is canonicalized (no "."/".." segments) and stripped of
719
+ // the archive's single top-level directory by streamPackageEntries,
720
+ // so joining under the canonical pkgDir yields a canonical path the
721
+ // w7-frame writer accepts.
692
722
  const filePath = pkgDir + '/' + entry.name;
693
723
  // Stage this file's parent-dir chain before the file itself.
694
724
  await enqueueDirsUpTo(filePath.substring(0, filePath.lastIndexOf('/')));
@@ -23,7 +23,8 @@ import type { SqliteVFS } from '@nimbus-sh/core/vfs/sqlite-vfs.js';
23
23
  import type { EsbuildService } from '@nimbus-sh/core/runtime/esbuild-service.js';
24
24
  import { NpmCache } from './cache.js';
25
25
  import { type FetchFn } from './resolver.js';
26
- import { type NpmLogEmitter } from './npm-log.js';
26
+ import { type NpmLogEmitter } from '@nimbus-sh/core/substrate/lifo/commands/system/npm-log.js';
27
+ import type { BundlePoolProvider } from '../facets/esbuild-bundle-pool.js';
27
28
  import type { InstallPhase } from '@nimbus-sh/platform/install-phase.js';
28
29
  export interface InstallProgress {
29
30
  phase: InstallPhase;
@@ -49,6 +50,8 @@ export declare class NpmInstaller {
49
50
  private readonly vfs;
50
51
  private cache;
51
52
  private esbuild;
53
+ /** The session's esbuild facet pool, shared with the on-demand dev-server path. */
54
+ private bundlePool;
52
55
  private ctx;
53
56
  private env;
54
57
  private onProgress;
@@ -68,6 +71,7 @@ export declare class NpmInstaller {
68
71
  private npmLog;
69
72
  constructor(vfs: SqliteVFS, sql: SqlStorage, opts?: {
70
73
  esbuild?: EsbuildService;
74
+ bundlePool?: BundlePoolProvider;
71
75
  ctx?: DurableObjectState;
72
76
  env?: any;
73
77
  onProgress?: (msg: string) => void;
@@ -86,6 +90,7 @@ export declare class NpmInstaller {
86
90
  production?: boolean;
87
91
  pid?: number;
88
92
  npmLog?: NpmLogEmitter;
93
+ onProgress?: (msg: string) => void;
89
94
  }): Promise<NpmInstallResult>;
90
95
  private _installInner;
91
96
  /**
@@ -104,7 +109,13 @@ export declare class NpmInstaller {
104
109
  * - X.5-G G1 optional-native silent-skip,
105
110
  * - X.5-drizzle best-effort tagging on optional-peer subtrees,
106
111
  * - W6 swap / warn / reject decisions (top-level enforcement; the
107
- * per-package task ALSO checks these for transitive correctness),
112
+ * per-package task ALSO checks these for transitive correctness).
113
+ * A package is required iff it is reachable from a required root
114
+ * (every selected spec except optionalDependencies roots) through
115
+ * a chain of required edges (`dependencies` minus the package's
116
+ * own optionalDependencies, required peers); W6 refusals are
117
+ * classified against the closure computed over the resolved
118
+ * graph at end of walk.
108
119
  * - cache flushing (one batched putRegistryEntries at end).
109
120
  *
110
121
  * The per-package task (resolveOnePackumentInFacet) owns ONLY the
@@ -139,24 +150,18 @@ export declare class NpmInstaller {
139
150
  * the V8 cap risk.
140
151
  */
141
152
  private fetchViaBatchFacet;
142
- /**
143
- * Build the dependency specs from package.json + explicit packages.
144
- */
145
- /**
146
- * W11: framework detection at install time. Reads package.json from the
147
- * project root and runs detectFramework() against its deps + the basenames
148
- * we can see in node_modules-adjacent siblings.
149
- *
150
- * Returns true if the project is detected as one of {next, astro, nuxt,
151
- * remix, sveltekit, vite, wrangler}. False for 'unknown'.
152
- */
153
- private detectFrameworkAware;
154
153
  private buildSpecs;
155
154
  /**
156
155
  * W6: apply the PACKAGE_ABI_POLICY swap rewrites and reject deny list
157
- * to a top-level spec map. Emits `[swap]` notices via onProgress; throws
158
- * a multi-line error on any reject (with `transitive='warn'` rejects
159
- * also failing at top level — they only soften at depth>0).
156
+ * to a top-level spec map. Emits `[swap]` notices via onProgress.
157
+ *
158
+ * G2: rejects are advisories — a listed package stays in the spec map
159
+ * and installs like any other (npm parity: it cannot run here, but
160
+ * install is the wrong place to say so). Each gets one `[npm] note:`
161
+ * line per install and an `advisory` registry event; the require-side
162
+ * refusal carries the reason when the artifact is invoked.
163
+ * `advised` dedupes across the top-level pass and the walk (the
164
+ * package still resolves and can surface transitively).
160
165
  *
161
166
  * Idempotent: running on already-swapped specs is a no-op.
162
167
  */
@@ -1 +1 @@
1
- {"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/npm/installer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/npm/installer.ts"],"names":[],"mappings":"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"}