@nimbus-sh/worker 0.1.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 (408) hide show
  1. package/README.md +219 -0
  2. package/dist/_shared/bytes.d.ts +18 -0
  3. package/dist/_shared/bytes.d.ts.map +1 -0
  4. package/dist/_shared/bytes.js +17 -0
  5. package/dist/_shared/cache-stats.d.ts +146 -0
  6. package/dist/_shared/cache-stats.d.ts.map +1 -0
  7. package/dist/_shared/cache-stats.js +162 -0
  8. package/dist/_shared/exports-resolver.d.ts +76 -0
  9. package/dist/_shared/exports-resolver.d.ts.map +1 -0
  10. package/dist/_shared/exports-resolver.js +284 -0
  11. package/dist/_shared/install-phase.d.ts +47 -0
  12. package/dist/_shared/install-phase.d.ts.map +1 -0
  13. package/dist/_shared/install-phase.js +1 -0
  14. package/dist/_shared/real-node-imports.d.ts +38 -0
  15. package/dist/_shared/real-node-imports.d.ts.map +1 -0
  16. package/dist/_shared/real-node-imports.js +46 -0
  17. package/dist/_shared/retry.d.ts +93 -0
  18. package/dist/_shared/retry.d.ts.map +1 -0
  19. package/dist/_shared/retry.js +161 -0
  20. package/dist/_shared/session-id.d.ts +39 -0
  21. package/dist/_shared/session-id.d.ts.map +1 -0
  22. package/dist/_shared/session-id.js +127 -0
  23. package/dist/_shared/session-router.d.ts +104 -0
  24. package/dist/_shared/session-router.d.ts.map +1 -0
  25. package/dist/_shared/session-router.js +165 -0
  26. package/dist/_shared/w7-frame.d.ts +93 -0
  27. package/dist/_shared/w7-frame.d.ts.map +1 -0
  28. package/dist/_shared/w7-frame.js +402 -0
  29. package/dist/auth/index.d.ts +16 -0
  30. package/dist/auth/index.d.ts.map +1 -0
  31. package/dist/auth/index.js +15 -0
  32. package/dist/auth/middleware.d.ts +85 -0
  33. package/dist/auth/middleware.d.ts.map +1 -0
  34. package/dist/auth/middleware.js +150 -0
  35. package/dist/auth/token.d.ts +96 -0
  36. package/dist/auth/token.d.ts.map +1 -0
  37. package/dist/auth/token.js +226 -0
  38. package/dist/auth/types.d.ts +141 -0
  39. package/dist/auth/types.d.ts.map +1 -0
  40. package/dist/auth/types.js +114 -0
  41. package/dist/bindings/d1.d.ts +102 -0
  42. package/dist/bindings/d1.d.ts.map +1 -0
  43. package/dist/bindings/d1.js +549 -0
  44. package/dist/bindings/kv.d.ts +82 -0
  45. package/dist/bindings/kv.d.ts.map +1 -0
  46. package/dist/bindings/kv.js +290 -0
  47. package/dist/bindings/r2.d.ts +137 -0
  48. package/dist/bindings/r2.d.ts.map +1 -0
  49. package/dist/bindings/r2.js +379 -0
  50. package/dist/cirrus-npm-cjs.generated.d.ts +17 -0
  51. package/dist/cirrus-npm-cjs.generated.d.ts.map +1 -0
  52. package/dist/cirrus-npm-cjs.generated.js +41 -0
  53. package/dist/cirrus-plugin-react.generated.d.ts +34 -0
  54. package/dist/cirrus-plugin-react.generated.d.ts.map +1 -0
  55. package/dist/cirrus-plugin-react.generated.js +33 -0
  56. package/dist/constants.d.ts +34 -0
  57. package/dist/constants.d.ts.map +1 -0
  58. package/dist/constants.js +116 -0
  59. package/dist/esbuild-wasm-bundle.generated.d.ts +41 -0
  60. package/dist/esbuild-wasm-bundle.generated.d.ts.map +1 -0
  61. package/dist/esbuild-wasm-bundle.generated.js +40 -0
  62. package/dist/facets/cirrus-real.d.ts +147 -0
  63. package/dist/facets/cirrus-real.d.ts.map +1 -0
  64. package/dist/facets/cirrus-real.js +981 -0
  65. package/dist/facets/inner-do-registry.d.ts +41 -0
  66. package/dist/facets/inner-do-registry.d.ts.map +1 -0
  67. package/dist/facets/inner-do-registry.js +51 -0
  68. package/dist/facets/manager.d.ts +314 -0
  69. package/dist/facets/manager.d.ts.map +1 -0
  70. package/dist/facets/manager.js +2681 -0
  71. package/dist/facets/process.d.ts +318 -0
  72. package/dist/facets/process.d.ts.map +1 -0
  73. package/dist/facets/process.js +567 -0
  74. package/dist/facets/real-vite-fs-shim.d.ts +151 -0
  75. package/dist/facets/real-vite-fs-shim.d.ts.map +1 -0
  76. package/dist/facets/real-vite-fs-shim.js +1279 -0
  77. package/dist/facets/real-vite-hmr.d.ts +142 -0
  78. package/dist/facets/real-vite-hmr.d.ts.map +1 -0
  79. package/dist/facets/real-vite-hmr.js +476 -0
  80. package/dist/facets/vite-dev-server.d.ts +293 -0
  81. package/dist/facets/vite-dev-server.d.ts.map +1 -0
  82. package/dist/facets/vite-dev-server.js +2580 -0
  83. package/dist/facets/wasm-swap-registry.d.ts +261 -0
  84. package/dist/facets/wasm-swap-registry.d.ts.map +1 -0
  85. package/dist/facets/wasm-swap-registry.js +551 -0
  86. package/dist/facets/ws-terminal.d.ts +107 -0
  87. package/dist/facets/ws-terminal.d.ts.map +1 -0
  88. package/dist/facets/ws-terminal.js +207 -0
  89. package/dist/git/commands.d.ts +13 -0
  90. package/dist/git/commands.d.ts.map +1 -0
  91. package/dist/git/commands.js +633 -0
  92. package/dist/git/network-facet.d.ts +61 -0
  93. package/dist/git/network-facet.d.ts.map +1 -0
  94. package/dist/git/network-facet.js +700 -0
  95. package/dist/git-bundle.generated.d.ts +16 -0
  96. package/dist/git-bundle.generated.d.ts.map +1 -0
  97. package/dist/git-bundle.generated.js +15 -0
  98. package/dist/index.d.ts +41 -0
  99. package/dist/index.d.ts.map +1 -0
  100. package/dist/index.js +73 -0
  101. package/dist/loaders/child-process/spawn-facet.d.ts +90 -0
  102. package/dist/loaders/child-process/spawn-facet.d.ts.map +1 -0
  103. package/dist/loaders/child-process/spawn-facet.js +103 -0
  104. package/dist/loaders/child-process/spawn-pool.d.ts +110 -0
  105. package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -0
  106. package/dist/loaders/child-process/spawn-pool.js +161 -0
  107. package/dist/loaders/fanout-pool.d.ts +195 -0
  108. package/dist/loaders/fanout-pool.d.ts.map +1 -0
  109. package/dist/loaders/fanout-pool.js +326 -0
  110. package/dist/loaders/generated-workers.d.ts +26 -0
  111. package/dist/loaders/generated-workers.d.ts.map +1 -0
  112. package/dist/loaders/generated-workers.js +25 -0
  113. package/dist/loaders/index.d.ts +15 -0
  114. package/dist/loaders/index.d.ts.map +1 -0
  115. package/dist/loaders/index.js +13 -0
  116. package/dist/loaders/loader-pool.d.ts +273 -0
  117. package/dist/loaders/loader-pool.d.ts.map +1 -0
  118. package/dist/loaders/loader-pool.js +624 -0
  119. package/dist/loaders/npm-resolve-preamble.d.ts +34 -0
  120. package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -0
  121. package/dist/loaders/npm-resolve-preamble.js +237 -0
  122. package/dist/loaders/pre-bundle-preamble.d.ts +41 -0
  123. package/dist/loaders/pre-bundle-preamble.d.ts.map +1 -0
  124. package/dist/loaders/pre-bundle-preamble.js +114 -0
  125. package/dist/loaders/vendor/codegen.d.ts +24 -0
  126. package/dist/loaders/vendor/codegen.d.ts.map +1 -0
  127. package/dist/loaders/vendor/codegen.js +44 -0
  128. package/dist/loaders/vendor/errors.d.ts +24 -0
  129. package/dist/loaders/vendor/errors.d.ts.map +1 -0
  130. package/dist/loaders/vendor/errors.js +46 -0
  131. package/dist/loaders/vendor/index.d.ts +16 -0
  132. package/dist/loaders/vendor/index.d.ts.map +1 -0
  133. package/dist/loaders/vendor/index.js +11 -0
  134. package/dist/loaders/vendor/pool.d.ts +88 -0
  135. package/dist/loaders/vendor/pool.d.ts.map +1 -0
  136. package/dist/loaders/vendor/pool.js +353 -0
  137. package/dist/loaders/vendor/primitives.d.ts +11 -0
  138. package/dist/loaders/vendor/primitives.d.ts.map +1 -0
  139. package/dist/loaders/vendor/primitives.js +33 -0
  140. package/dist/loaders/vendor/serialize.d.ts +3 -0
  141. package/dist/loaders/vendor/serialize.d.ts.map +1 -0
  142. package/dist/loaders/vendor/serialize.js +25 -0
  143. package/dist/loaders/vendor/types.d.ts +60 -0
  144. package/dist/loaders/vendor/types.d.ts.map +1 -0
  145. package/dist/loaders/vendor/types.js +4 -0
  146. package/dist/npm/cache.d.ts +136 -0
  147. package/dist/npm/cache.d.ts.map +1 -0
  148. package/dist/npm/cache.js +429 -0
  149. package/dist/npm/install-batch-facet.d.ts +129 -0
  150. package/dist/npm/install-batch-facet.d.ts.map +1 -0
  151. package/dist/npm/install-batch-facet.js +598 -0
  152. package/dist/npm/install-facet.d.ts +29 -0
  153. package/dist/npm/install-facet.d.ts.map +1 -0
  154. package/dist/npm/install-facet.js +9 -0
  155. package/dist/npm/installer.d.ts +239 -0
  156. package/dist/npm/installer.d.ts.map +1 -0
  157. package/dist/npm/installer.js +2022 -0
  158. package/dist/npm/npx-install.d.ts +74 -0
  159. package/dist/npm/npx-install.d.ts.map +1 -0
  160. package/dist/npm/npx-install.js +302 -0
  161. package/dist/npm/pre-bundle-facet.d.ts +168 -0
  162. package/dist/npm/pre-bundle-facet.d.ts.map +1 -0
  163. package/dist/npm/pre-bundle-facet.js +653 -0
  164. package/dist/npm/r2-cache.d.ts +286 -0
  165. package/dist/npm/r2-cache.d.ts.map +1 -0
  166. package/dist/npm/r2-cache.js +506 -0
  167. package/dist/npm/resolve-facet.d.ts +202 -0
  168. package/dist/npm/resolve-facet.d.ts.map +1 -0
  169. package/dist/npm/resolve-facet.js +833 -0
  170. package/dist/npm/resolve-one-facet.d.ts +204 -0
  171. package/dist/npm/resolve-one-facet.d.ts.map +1 -0
  172. package/dist/npm/resolve-one-facet.js +437 -0
  173. package/dist/npm/resolver.d.ts +109 -0
  174. package/dist/npm/resolver.d.ts.map +1 -0
  175. package/dist/npm/resolver.js +899 -0
  176. package/dist/npm/tarball-stream.d.ts +85 -0
  177. package/dist/npm/tarball-stream.d.ts.map +1 -0
  178. package/dist/npm/tarball-stream.js +205 -0
  179. package/dist/npm/tarball.d.ts +51 -0
  180. package/dist/npm/tarball.d.ts.map +1 -0
  181. package/dist/npm/tarball.js +185 -0
  182. package/dist/observability/diag-counters.d.ts +292 -0
  183. package/dist/observability/diag-counters.d.ts.map +1 -0
  184. package/dist/observability/diag-counters.js +302 -0
  185. package/dist/observability/heap-estimate.d.ts +166 -0
  186. package/dist/observability/heap-estimate.d.ts.map +1 -0
  187. package/dist/observability/heap-estimate.js +192 -0
  188. package/dist/observability/heavy-alloc-coord.d.ts +95 -0
  189. package/dist/observability/heavy-alloc-coord.d.ts.map +1 -0
  190. package/dist/observability/heavy-alloc-coord.js +149 -0
  191. package/dist/observability/oom-classify.d.ts +56 -0
  192. package/dist/observability/oom-classify.d.ts.map +1 -0
  193. package/dist/observability/oom-classify.js +118 -0
  194. package/dist/observability/oom-discriminator.d.ts +192 -0
  195. package/dist/observability/oom-discriminator.d.ts.map +1 -0
  196. package/dist/observability/oom-discriminator.js +233 -0
  197. package/dist/real-vite-bundle.generated.d.ts +46 -0
  198. package/dist/real-vite-bundle.generated.d.ts.map +1 -0
  199. package/dist/real-vite-bundle.generated.js +53 -0
  200. package/dist/replica/routing.d.ts +171 -0
  201. package/dist/replica/routing.d.ts.map +1 -0
  202. package/dist/replica/routing.js +288 -0
  203. package/dist/replica/suspension.d.ts +36 -0
  204. package/dist/replica/suspension.d.ts.map +1 -0
  205. package/dist/replica/suspension.js +49 -0
  206. package/dist/router/index.d.ts +156 -0
  207. package/dist/router/index.d.ts.map +1 -0
  208. package/dist/router/index.js +220 -0
  209. package/dist/runtime/assets-loader.d.ts +71 -0
  210. package/dist/runtime/assets-loader.d.ts.map +1 -0
  211. package/dist/runtime/assets-loader.js +128 -0
  212. package/dist/runtime/barrel-detect.d.ts +46 -0
  213. package/dist/runtime/barrel-detect.d.ts.map +1 -0
  214. package/dist/runtime/barrel-detect.js +73 -0
  215. package/dist/runtime/barrel-synthesizer.d.ts +181 -0
  216. package/dist/runtime/barrel-synthesizer.d.ts.map +1 -0
  217. package/dist/runtime/barrel-synthesizer.js +541 -0
  218. package/dist/runtime/bun-repl.d.ts +46 -0
  219. package/dist/runtime/bun-repl.d.ts.map +1 -0
  220. package/dist/runtime/bun-repl.js +326 -0
  221. package/dist/runtime/bun-runner.d.ts +66 -0
  222. package/dist/runtime/bun-runner.d.ts.map +1 -0
  223. package/dist/runtime/bun-runner.js +219 -0
  224. package/dist/runtime/clang-runner.d.ts +38 -0
  225. package/dist/runtime/clang-runner.d.ts.map +1 -0
  226. package/dist/runtime/clang-runner.js +1033 -0
  227. package/dist/runtime/comment-strip.d.ts +37 -0
  228. package/dist/runtime/comment-strip.d.ts.map +1 -0
  229. package/dist/runtime/comment-strip.js +74 -0
  230. package/dist/runtime/esbuild-service.d.ts +201 -0
  231. package/dist/runtime/esbuild-service.d.ts.map +1 -0
  232. package/dist/runtime/esbuild-service.js +1444 -0
  233. package/dist/runtime/esbuild-wasm-bytes.d.ts +87 -0
  234. package/dist/runtime/esbuild-wasm-bytes.d.ts.map +1 -0
  235. package/dist/runtime/esbuild-wasm-bytes.js +131 -0
  236. package/dist/runtime/framework-detect.d.ts +71 -0
  237. package/dist/runtime/framework-detect.d.ts.map +1 -0
  238. package/dist/runtime/framework-detect.js +178 -0
  239. package/dist/runtime/long-running-handle.d.ts +133 -0
  240. package/dist/runtime/long-running-handle.d.ts.map +1 -0
  241. package/dist/runtime/long-running-handle.js +192 -0
  242. package/dist/runtime/node-repl.d.ts +36 -0
  243. package/dist/runtime/node-repl.d.ts.map +1 -0
  244. package/dist/runtime/node-repl.js +293 -0
  245. package/dist/runtime/node-runner.d.ts +111 -0
  246. package/dist/runtime/node-runner.d.ts.map +1 -0
  247. package/dist/runtime/node-runner.js +194 -0
  248. package/dist/runtime/node-shims.d.ts +24 -0
  249. package/dist/runtime/node-shims.d.ts.map +1 -0
  250. package/dist/runtime/node-shims.js +3019 -0
  251. package/dist/runtime/package-manager.d.ts +118 -0
  252. package/dist/runtime/package-manager.d.ts.map +1 -0
  253. package/dist/runtime/package-manager.js +420 -0
  254. package/dist/runtime/port-registry.d.ts +80 -0
  255. package/dist/runtime/port-registry.d.ts.map +1 -0
  256. package/dist/runtime/port-registry.js +166 -0
  257. package/dist/runtime/process-logs-api.d.ts +102 -0
  258. package/dist/runtime/process-logs-api.d.ts.map +1 -0
  259. package/dist/runtime/process-logs-api.js +253 -0
  260. package/dist/runtime/process-logs.d.ts +311 -0
  261. package/dist/runtime/process-logs.d.ts.map +1 -0
  262. package/dist/runtime/process-logs.js +656 -0
  263. package/dist/runtime/process-table.d.ts +65 -0
  264. package/dist/runtime/process-table.d.ts.map +1 -0
  265. package/dist/runtime/process-table.js +107 -0
  266. package/dist/runtime/project-detect.d.ts +21 -0
  267. package/dist/runtime/project-detect.d.ts.map +1 -0
  268. package/dist/runtime/project-detect.js +46 -0
  269. package/dist/runtime/python-repl.d.ts +66 -0
  270. package/dist/runtime/python-repl.d.ts.map +1 -0
  271. package/dist/runtime/python-repl.js +563 -0
  272. package/dist/runtime/python-runner.d.ts +50 -0
  273. package/dist/runtime/python-runner.d.ts.map +1 -0
  274. package/dist/runtime/python-runner.js +870 -0
  275. package/dist/runtime/repl-session.d.ts +160 -0
  276. package/dist/runtime/repl-session.d.ts.map +1 -0
  277. package/dist/runtime/repl-session.js +393 -0
  278. package/dist/runtime/require-resolver.d.ts +52 -0
  279. package/dist/runtime/require-resolver.d.ts.map +1 -0
  280. package/dist/runtime/require-resolver.js +690 -0
  281. package/dist/runtime/router-basename.d.ts +36 -0
  282. package/dist/runtime/router-basename.d.ts.map +1 -0
  283. package/dist/runtime/router-basename.js +310 -0
  284. package/dist/runtime/ruby-repl.d.ts +43 -0
  285. package/dist/runtime/ruby-repl.d.ts.map +1 -0
  286. package/dist/runtime/ruby-repl.js +229 -0
  287. package/dist/runtime/ruby-runner.d.ts +62 -0
  288. package/dist/runtime/ruby-runner.d.ts.map +1 -0
  289. package/dist/runtime/ruby-runner.js +737 -0
  290. package/dist/runtime/runtime-catalog.d.ts +99 -0
  291. package/dist/runtime/runtime-catalog.d.ts.map +1 -0
  292. package/dist/runtime/runtime-catalog.js +183 -0
  293. package/dist/runtime/runtime-registry.d.ts +136 -0
  294. package/dist/runtime/runtime-registry.d.ts.map +1 -0
  295. package/dist/runtime/runtime-registry.js +318 -0
  296. package/dist/runtime/streams.d.ts +13 -0
  297. package/dist/runtime/streams.d.ts.map +1 -0
  298. package/dist/runtime/streams.js +402 -0
  299. package/dist/runtime/wasi-instance.d.ts +190 -0
  300. package/dist/runtime/wasi-instance.d.ts.map +1 -0
  301. package/dist/runtime/wasi-instance.js +2044 -0
  302. package/dist/runtime/wasm-runner.d.ts +117 -0
  303. package/dist/runtime/wasm-runner.d.ts.map +1 -0
  304. package/dist/runtime/wasm-runner.js +705 -0
  305. package/dist/session/bindings.d.ts +168 -0
  306. package/dist/session/bindings.d.ts.map +1 -0
  307. package/dist/session/bindings.js +524 -0
  308. package/dist/session/ctx-exports.d.ts +16 -0
  309. package/dist/session/ctx-exports.d.ts.map +1 -0
  310. package/dist/session/ctx-exports.js +22 -0
  311. package/dist/session/diag.d.ts +62 -0
  312. package/dist/session/diag.d.ts.map +1 -0
  313. package/dist/session/diag.js +118 -0
  314. package/dist/session/fs-watch.d.ts +132 -0
  315. package/dist/session/fs-watch.d.ts.map +1 -0
  316. package/dist/session/fs-watch.js +255 -0
  317. package/dist/session/helpers.d.ts +150 -0
  318. package/dist/session/helpers.d.ts.map +1 -0
  319. package/dist/session/helpers.js +472 -0
  320. package/dist/session/hibernation.d.ts +145 -0
  321. package/dist/session/hibernation.d.ts.map +1 -0
  322. package/dist/session/hibernation.js +385 -0
  323. package/dist/session/init-phases.d.ts +87 -0
  324. package/dist/session/init-phases.d.ts.map +1 -0
  325. package/dist/session/init-phases.js +137 -0
  326. package/dist/session/init.d.ts +46 -0
  327. package/dist/session/init.d.ts.map +1 -0
  328. package/dist/session/init.js +3579 -0
  329. package/dist/session/keys.d.ts +56 -0
  330. package/dist/session/keys.d.ts.map +1 -0
  331. package/dist/session/keys.js +55 -0
  332. package/dist/session/nimbus-session.d.ts +434 -0
  333. package/dist/session/nimbus-session.d.ts.map +1 -0
  334. package/dist/session/nimbus-session.js +1084 -0
  335. package/dist/session/programmatic.d.ts +105 -0
  336. package/dist/session/programmatic.d.ts.map +1 -0
  337. package/dist/session/programmatic.js +326 -0
  338. package/dist/session/replica-routes.d.ts +68 -0
  339. package/dist/session/replica-routes.d.ts.map +1 -0
  340. package/dist/session/replica-routes.js +77 -0
  341. package/dist/session/routes.d.ts +29 -0
  342. package/dist/session/routes.d.ts.map +1 -0
  343. package/dist/session/routes.js +1331 -0
  344. package/dist/session/rpc.d.ts +323 -0
  345. package/dist/session/rpc.d.ts.map +1 -0
  346. package/dist/session/rpc.js +808 -0
  347. package/dist/session/state-store.d.ts +210 -0
  348. package/dist/session/state-store.d.ts.map +1 -0
  349. package/dist/session/state-store.js +459 -0
  350. package/dist/session/supervisor-rpc.d.ts +269 -0
  351. package/dist/session/supervisor-rpc.d.ts.map +1 -0
  352. package/dist/session/supervisor-rpc.js +437 -0
  353. package/dist/session/ws-hibernation-config.d.ts +64 -0
  354. package/dist/session/ws-hibernation-config.d.ts.map +1 -0
  355. package/dist/session/ws-hibernation-config.js +89 -0
  356. package/dist/session/ws.d.ts +95 -0
  357. package/dist/session/ws.d.ts.map +1 -0
  358. package/dist/session/ws.js +395 -0
  359. package/dist/shell/features.d.ts +410 -0
  360. package/dist/shell/features.d.ts.map +1 -0
  361. package/dist/shell/features.js +1885 -0
  362. package/dist/shell/unix-commands.d.ts +15 -0
  363. package/dist/shell/unix-commands.d.ts.map +1 -0
  364. package/dist/shell/unix-commands.js +3703 -0
  365. package/dist/stubs/lifo-ui.d.ts +10 -0
  366. package/dist/stubs/lifo-ui.d.ts.map +1 -0
  367. package/dist/stubs/lifo-ui.js +1 -0
  368. package/dist/tailwind-play.generated.d.ts +19 -0
  369. package/dist/tailwind-play.generated.d.ts.map +1 -0
  370. package/dist/tailwind-play.generated.js +18 -0
  371. package/dist/vfs/dev-provider.d.ts +64 -0
  372. package/dist/vfs/dev-provider.d.ts.map +1 -0
  373. package/dist/vfs/dev-provider.js +191 -0
  374. package/dist/vfs/events.d.ts +51 -0
  375. package/dist/vfs/events.d.ts.map +1 -0
  376. package/dist/vfs/events.js +127 -0
  377. package/dist/vfs/path.d.ts +30 -0
  378. package/dist/vfs/path.d.ts.map +1 -0
  379. package/dist/vfs/path.js +41 -0
  380. package/dist/vfs/seed-project.d.ts +62 -0
  381. package/dist/vfs/seed-project.d.ts.map +1 -0
  382. package/dist/vfs/seed-project.js +1045 -0
  383. package/dist/vfs/sqlite-vfs.d.ts +435 -0
  384. package/dist/vfs/sqlite-vfs.d.ts.map +1 -0
  385. package/dist/vfs/sqlite-vfs.js +1670 -0
  386. package/dist/vfs/symlink-registry.d.ts +64 -0
  387. package/dist/vfs/symlink-registry.d.ts.map +1 -0
  388. package/dist/vfs/symlink-registry.js +137 -0
  389. package/dist/wrangler/nimbus-wrangler.d.ts +157 -0
  390. package/dist/wrangler/nimbus-wrangler.d.ts.map +1 -0
  391. package/dist/wrangler/nimbus-wrangler.js +931 -0
  392. package/package.json +77 -0
  393. package/public/_assets/cirrus-plugin-react.bundle.js +70740 -0
  394. package/public/_assets/esbuild-0.24.2.wasm +0 -0
  395. package/public/_assets/real-vite-bundle.js +101478 -0
  396. package/public/_assets/rollup.wasm +0 -0
  397. package/public/favicon.svg +8 -0
  398. package/public/index.html +565 -0
  399. package/public/s/index.html +2379 -0
  400. package/scripts/bundle-esbuild-wasm.mjs +244 -0
  401. package/scripts/bundle-facet-workers.mjs +137 -0
  402. package/scripts/bundle-git.mjs +118 -0
  403. package/scripts/bundle-npm-cjs.mjs +363 -0
  404. package/scripts/bundle-plugin-react.mjs +480 -0
  405. package/scripts/bundle-real-vite.mjs +959 -0
  406. package/scripts/bundle-runtime.mjs +600 -0
  407. package/scripts/bundle-tailwind-play.mjs +130 -0
  408. package/scripts/patch-lifo-ui.mjs +131 -0
@@ -0,0 +1,931 @@
1
+ /**
2
+ * nimbus-wrangler.ts — Lightweight wrangler dev replacement for Nimbus.
3
+ *
4
+ * Architecture (from spec §8):
5
+ * nimbus-wrangler dev:
6
+ * 1. Reads wrangler.jsonc/toml from VFS
7
+ * 2. Bundles user's Worker code via EsbuildService
8
+ * 3. Creates a dynamic worker via LOADER.load() with the bundled code
9
+ * 4. Routes /worker/* requests to the dynamic worker's fetch()
10
+ * 5. On VFS file change: re-bundles and recreates the dynamic worker
11
+ * 6. Simulates KV via the worker's own storage
12
+ *
13
+ * The dynamic worker IS the user's Worker — running on the actual
14
+ * Cloudflare Workers runtime, not a simulation.
15
+ */
16
+ import { normalizeVfsPath } from '../vfs/path.js';
17
+ import { registerInnerDoClass, clearInnerDoClasses } from '../facets/inner-do-registry.js';
18
+ import { KvEmulator } from '../bindings/kv.js';
19
+ import { D1Emulator } from '../bindings/d1.js';
20
+ import { R2Emulator } from '../bindings/r2.js';
21
+ // ── Proxy helpers ──────────────────────────────────────────────────────
22
+ /**
23
+ * Rewrite a Location header emitted by the inner Worker so that, when
24
+ * the browser follows it, the browser hits the outer-prefixed URL.
25
+ *
26
+ * Cases handled:
27
+ * - Same-origin absolute URL (http://localhost:.../s/foo/)
28
+ * → prepend outerWorkerBase to the pathname
29
+ * - Origin-relative (/s/foo/, /new)
30
+ * → prepend outerWorkerBase
31
+ * - Path-relative (foo/bar)
32
+ * → leave untouched (browser resolves against current URL, which
33
+ * is already outer-prefixed)
34
+ * - Cross-origin absolute URL (https://example.com/...)
35
+ * → leave untouched
36
+ * - Malformed / non-URL strings
37
+ * → leave untouched
38
+ *
39
+ * The outerWorkerBase is the full path prefix (e.g.
40
+ * "/s/nimble-otter-4271/worker"); do not include a trailing slash.
41
+ */
42
+ export function rewriteLocationForOuter(location, outerWorkerBase, currentRequestUrl) {
43
+ if (!location)
44
+ return location;
45
+ const base = outerWorkerBase.replace(/\/+$/, '');
46
+ // Path-relative (no leading slash, no scheme): browser resolves
47
+ // against the current request URL, which is already outer-prefixed,
48
+ // so the right thing happens naturally.
49
+ if (!location.startsWith('/') && !/^[a-z]+:\/\//i.test(location)) {
50
+ return location;
51
+ }
52
+ // Origin-relative starting with /. Prepend the outer base.
53
+ if (location.startsWith('/')) {
54
+ // Don't double-prefix if the inner already emitted an outer path
55
+ // (defensive — it shouldn't, but caches / badly-behaved inner
56
+ // workers could produce one).
57
+ if (location.startsWith(base + '/') || location === base)
58
+ return location;
59
+ return base + location;
60
+ }
61
+ // Absolute URL. Rewrite only when same-origin; pass cross-origin through.
62
+ try {
63
+ const current = new URL(currentRequestUrl);
64
+ const loc = new URL(location);
65
+ if (loc.origin !== current.origin)
66
+ return location;
67
+ if (loc.pathname.startsWith(base + '/') || loc.pathname === base)
68
+ return location;
69
+ loc.pathname = base + loc.pathname;
70
+ return loc.toString();
71
+ }
72
+ catch {
73
+ return location;
74
+ }
75
+ }
76
+ /**
77
+ * Small HTML body that stands in for the inner Worker's missing-root
78
+ * handler. Nimbus, when loaded as an inner worker via worker_loaders,
79
+ * has no ASSETS binding to serve its landing page at `/`, so the raw
80
+ * src/index.ts fallthrough emits a 9-byte "Not found". This page
81
+ * replaces that so users visiting `/s/<outer>/worker/` see a useful
82
+ * orientation instead of a scary 404.
83
+ *
84
+ * Style is kept minimal and in line with the outer Nimbus "no dev
85
+ * server running" placeholder so the visual transition when wrangler
86
+ * comes up is not jarring.
87
+ */
88
+ function renderWorkerRunningHtml(opts) {
89
+ const safeName = String(opts.workerName).replace(/[&<>"']/g, (c) => ({
90
+ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;',
91
+ }[c]));
92
+ const base = opts.outerWorkerBase.replace(/\/+$/, '');
93
+ const newHref = base + '/new';
94
+ return `<!DOCTYPE html>
95
+ <html lang="en"><head>
96
+ <meta charset="UTF-8">
97
+ <meta name="viewport" content="width=device-width,initial-scale=1">
98
+ <title>${safeName} — Worker running</title>
99
+ <style>
100
+ *{margin:0;padding:0;box-sizing:border-box}
101
+ html,body{height:100%}
102
+ body{background:#0a0a0a;color:#e6edf3;font:15px/1.6 ui-sans-serif,-apple-system,"Segoe UI",sans-serif;
103
+ display:flex;align-items:center;justify-content:center;padding:24px;
104
+ background-image:radial-gradient(800px 500px at 50% -10%,rgba(100,255,218,0.06),transparent 60%)}
105
+ .card{max-width:560px;text-align:center}
106
+ .dot{width:8px;height:8px;border-radius:50%;background:#3fb950;display:inline-block;
107
+ box-shadow:0 0 6px rgba(63,185,80,0.8);animation:pulse 1.6s ease-in-out infinite;margin-right:8px;vertical-align:middle}
108
+ @keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}}
109
+ .badge{display:inline-block;padding:6px 14px;border:1px solid #30363d;border-radius:999px;
110
+ font-family:ui-monospace,Menlo,monospace;font-size:12px;color:#8b949e;margin-bottom:18px}
111
+ h1{font-size:26px;color:#64ffda;margin-bottom:10px;font-family:ui-monospace,Menlo,monospace}
112
+ p{color:#8b949e;margin-bottom:22px}
113
+ code{font-family:ui-monospace,Menlo,monospace;background:#111;padding:2px 8px;border-radius:4px;color:#e6edf3;font-size:13px}
114
+ .links{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:12px}
115
+ a.btn{display:inline-block;background:#64ffda;color:#000;font-weight:700;padding:9px 18px;border-radius:6px;text-decoration:none}
116
+ a.btn.secondary{background:transparent;color:#8b949e;border:1px solid #30363d}
117
+ a.btn:hover{filter:brightness(1.1)}
118
+ </style></head>
119
+ <body><div class="card">
120
+ <span class="badge"><span class="dot"></span>${safeName} is running</span>
121
+ <h1>Worker has no route for <code>/</code></h1>
122
+ <p>The inner Worker is running, but it didn't define a handler for the root path. If this is Nimbus-in-Nimbus, visit <code>/new</code> to spawn a session.</p>
123
+ <div class="links">
124
+ <a class="btn" href="${newHref}">Open /new</a>
125
+ </div>
126
+ </div></body></html>`;
127
+ }
128
+ // ── NimbusWrangler ────────────────────────────────────────────────────────
129
+ export class NimbusWrangler {
130
+ vfs;
131
+ esbuild;
132
+ loaderEnv;
133
+ supervisorCtx; // ctx.facets for DO facets, ctx.exports for bindings
134
+ root;
135
+ onLog;
136
+ onHmrMessage;
137
+ running = false;
138
+ config = null;
139
+ workerStub = null;
140
+ buildVersion = 0;
141
+ unsubVfs = null;
142
+ rebuildTimer = null;
143
+ /** DO class map: binding name → DurableObjectClass from the inner worker. */
144
+ doClassMap = new Map();
145
+ /** Facet names we've created via ctx.facets.get — aborted on rebuild / stop. */
146
+ doFacetNames = new Set();
147
+ constructor(opts) {
148
+ this.vfs = opts.vfs;
149
+ this.esbuild = opts.esbuild;
150
+ this.loaderEnv = opts.env;
151
+ this.supervisorCtx = opts.ctx || null;
152
+ this.root = opts.root.replace(/^\/+/, '').replace(/\/+$/, '');
153
+ this.onLog = opts.onLog;
154
+ this.onHmrMessage = opts.onHmrMessage;
155
+ }
156
+ /** Start the wrangler dev server. */
157
+ async start() {
158
+ // 1. Read wrangler config
159
+ this.config = this.readConfig();
160
+ if (!this.config) {
161
+ this.onLog('\x1b[31mNo wrangler.jsonc or wrangler.toml found in ' + this.root + '\x1b[0m\n');
162
+ return false;
163
+ }
164
+ // 2. Build and load the worker
165
+ const ok = await this.buildAndLoad();
166
+ if (!ok)
167
+ return false;
168
+ // 3. Watch for file changes
169
+ this.running = true;
170
+ this.unsubVfs = this.vfs.events.on((events) => {
171
+ this.handleVfsEvents(events);
172
+ });
173
+ return true;
174
+ }
175
+ /** Stop the wrangler dev server. */
176
+ stop() {
177
+ this.running = false;
178
+ if (this.unsubVfs) {
179
+ this.unsubVfs();
180
+ this.unsubVfs = null;
181
+ }
182
+ if (this.rebuildTimer) {
183
+ clearTimeout(this.rebuildTimer);
184
+ this.rebuildTimer = null;
185
+ }
186
+ // Abort live inner-DO facets so their stubs drop. Storage persists per
187
+ // docs — next start() or `nimbus-wrangler reset` controls deletion.
188
+ if (this.doFacetNames.size > 0 && this.supervisorCtx?.facets?.abort) {
189
+ for (const name of this.doFacetNames) {
190
+ try {
191
+ this.supervisorCtx.facets.abort(name, new Error('nimbus-wrangler stopped'));
192
+ }
193
+ catch { }
194
+ }
195
+ }
196
+ this.doFacetNames.clear();
197
+ this.doClassMap.clear();
198
+ this.workerStub = null;
199
+ }
200
+ get isRunning() { return this.running; }
201
+ // ── Config reading ────────────────────────────────────────────────────
202
+ readConfig() {
203
+ // Try wrangler.jsonc first, then wrangler.json, then wrangler.toml
204
+ const jsonPaths = [
205
+ this.root + '/wrangler.jsonc',
206
+ this.root + '/wrangler.json',
207
+ ];
208
+ for (const p of jsonPaths) {
209
+ if (this.vfs.exists(p)) {
210
+ try {
211
+ let text = this.vfs.readFileString(p);
212
+ // Strip JSONC comments while preserving content inside strings.
213
+ // Walk character by character, skip // and /* */ outside of quotes.
214
+ let cleaned = '';
215
+ let i = 0;
216
+ let inString = false;
217
+ while (i < text.length) {
218
+ if (inString) {
219
+ if (text[i] === '\\') {
220
+ cleaned += text[i] + (text[i + 1] || '');
221
+ i += 2;
222
+ continue;
223
+ }
224
+ if (text[i] === '"')
225
+ inString = false;
226
+ cleaned += text[i];
227
+ i++;
228
+ }
229
+ else {
230
+ if (text[i] === '"') {
231
+ inString = true;
232
+ cleaned += text[i];
233
+ i++;
234
+ }
235
+ else if (text[i] === '/' && text[i + 1] === '/') {
236
+ while (i < text.length && text[i] !== '\n')
237
+ i++;
238
+ }
239
+ else if (text[i] === '/' && text[i + 1] === '*') {
240
+ i += 2;
241
+ while (i < text.length - 1 && !(text[i] === '*' && text[i + 1] === '/'))
242
+ i++;
243
+ i += 2;
244
+ }
245
+ else {
246
+ cleaned += text[i];
247
+ i++;
248
+ }
249
+ }
250
+ }
251
+ return JSON.parse(cleaned);
252
+ }
253
+ catch (e) {
254
+ this.onLog(`\x1b[33mWarning: could not parse ${p}: ${e?.message}\x1b[0m\n`);
255
+ }
256
+ }
257
+ }
258
+ // Try wrangler.toml (minimal parse)
259
+ const tomlPath = this.root + '/wrangler.toml';
260
+ if (this.vfs.exists(tomlPath)) {
261
+ try {
262
+ const text = this.vfs.readFileString(tomlPath);
263
+ return this.parseMinimalToml(text);
264
+ }
265
+ catch (e) {
266
+ this.onLog(`\x1b[33mWarning: could not parse ${tomlPath}: ${e?.message}\x1b[0m\n`);
267
+ }
268
+ }
269
+ return null;
270
+ }
271
+ /** Minimal TOML parser — handles key = "value" and main/name/compatibility_date. */
272
+ parseMinimalToml(text) {
273
+ const config = {};
274
+ for (const line of text.split('\n')) {
275
+ const trimmed = line.trim();
276
+ if (trimmed.startsWith('#') || !trimmed.includes('='))
277
+ continue;
278
+ const eqIdx = trimmed.indexOf('=');
279
+ const key = trimmed.substring(0, eqIdx).trim();
280
+ let val = trimmed.substring(eqIdx + 1).trim();
281
+ // Strip quotes
282
+ if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) {
283
+ val = val.slice(1, -1);
284
+ }
285
+ if (key === 'main')
286
+ config.main = val;
287
+ else if (key === 'name')
288
+ config.name = val;
289
+ else if (key === 'compatibility_date')
290
+ config.compatibility_date = val;
291
+ }
292
+ return config;
293
+ }
294
+ // ── Build & load ──────────────────────────────────────────────────────
295
+ /**
296
+ * Resolve the user's `main:` entry to a canonical VFS-key path.
297
+ *
298
+ * The wrangler.jsonc `main` field is user-controlled and templates
299
+ * commonly emit any of:
300
+ * - "src/index.ts" — clean relative
301
+ * - "./src/index.ts" — npm-style with leading dot
302
+ * - "/src/index.ts" — workspace-absolute mistake
303
+ * - "src//index.ts" — accidental double-slash
304
+ *
305
+ * Naive `this.root + '/' + main` concatenation produced a malformed
306
+ * VFS key for every shape except the first, so vfs.exists() returned
307
+ * false even when the file was present at the canonical location.
308
+ *
309
+ * normalizeVfsPath collapses '.', '..', '//' runs and strips leading
310
+ * slashes — exactly the canonicalization SqliteVFS expects (every
311
+ * inode key in the live store is no-leading-slash, no internal
312
+ * doubles; src/vfs/sqlite-vfs.ts:_mkdirSingle uses the same
313
+ * `path.split('/').filter(Boolean)` shape via `normalizePath`).
314
+ */
315
+ resolveEntryPath() {
316
+ return normalizeVfsPath(this.root + '/' + (this.config?.main ?? ''));
317
+ }
318
+ async buildAndLoad() {
319
+ if (!this.config?.main) {
320
+ this.onLog('\x1b[31mNo "main" entry point in wrangler config\x1b[0m\n');
321
+ return false;
322
+ }
323
+ const entryPoint = this.resolveEntryPath();
324
+ if (!this.vfs.exists(entryPoint)) {
325
+ this.onLog(`\x1b[31mEntry point not found: ${entryPoint}\x1b[0m\n`);
326
+ return false;
327
+ }
328
+ // Bundle via esbuild
329
+ this.onLog(' Building Worker...\n');
330
+ try {
331
+ // [WRANGLER-DEV-HANG P0b] Time-bound the bundle. Pre-fix,
332
+ // bundling Nimbus's own src/index.ts (~100 .ts files, ~25 MB
333
+ // closure) hung indefinitely with no error surfaced — neither
334
+ // result.errors[] nor !result.outputFiles[] paths fired because
335
+ // the await never returned. Likely cause(s): supervisor isolate
336
+ // OOM under the 64 MiB ceiling (esbuild-wasm baseline ~15-20 MiB
337
+ // + the AST of a 100-file source tree), or a vfsPlugin onResolve
338
+ // cycle. Either way the contract is "fail loud or succeed", not
339
+ // "hang silent" — see user-debug-transcript.txt lines 79-179
340
+ // (six attempts all hang at "Building Worker...").
341
+ //
342
+ // Timeout is generous (60s) so legitimate large-but-finishing
343
+ // builds aren't false-tripped. After timeout we surface a clear
344
+ // diagnostic with remediation hints.
345
+ const BUILD_TIMEOUT_MS = 60_000;
346
+ const buildOptions = {
347
+ bundle: true,
348
+ format: 'esm',
349
+ target: 'esnext',
350
+ platform: 'neutral',
351
+ minify: false,
352
+ // `node:*` handles prefixed imports; bare names (fs, path, etc.)
353
+ // are used by legacy CJS packages like esbuild-wasm's main.js.
354
+ // Mark both forms external so dynamic require('fs') round-trips
355
+ // to the inner runtime's nodejs_compat-provided modules.
356
+ external: [
357
+ 'cloudflare:*',
358
+ 'node:*',
359
+ 'fs', 'path', 'os', 'crypto', 'util', 'stream', 'events',
360
+ 'buffer', 'url', 'querystring', 'http', 'https', 'net', 'tls',
361
+ 'child_process', 'worker_threads', 'perf_hooks', 'zlib',
362
+ 'assert', 'fs/promises', 'process',
363
+ ],
364
+ };
365
+ let timeoutHandle = null;
366
+ const result = await Promise.race([
367
+ this.esbuild.build([entryPoint], buildOptions),
368
+ new Promise((_, reject) => {
369
+ timeoutHandle = setTimeout(() => {
370
+ reject(new Error(`esbuild bundle exceeded ${BUILD_TIMEOUT_MS / 1000}s timeout. ` +
371
+ `entry=${entryPoint}; main='${this.config?.main}'. ` +
372
+ `Likely cause: supervisor heap pressure (64 MiB ceiling) or ` +
373
+ `large source closure. Mitigation: split worker into smaller ` +
374
+ `entries, reduce transitive imports, or bundle externally.`));
375
+ }, BUILD_TIMEOUT_MS);
376
+ }),
377
+ ]).finally(() => { if (timeoutHandle)
378
+ clearTimeout(timeoutHandle); });
379
+ if (result.errors?.length) {
380
+ for (const e of result.errors) {
381
+ this.onLog(` \x1b[31merror: ${e.text}\x1b[0m\n`);
382
+ }
383
+ return false;
384
+ }
385
+ if (!result.outputFiles?.length) {
386
+ this.onLog(' \x1b[31mNo output from esbuild\x1b[0m\n');
387
+ return false;
388
+ }
389
+ const bundledCode = result.outputFiles[0].contents;
390
+ this.buildVersion++;
391
+ // On rebuild, abort any live DO facets so the NEXT get() runs the
392
+ // startup callback with the fresh class. Docs: abort invalidates
393
+ // all existing stubs but preserves storage; the next get() is the
394
+ // code-update pattern.
395
+ if (this.doFacetNames.size > 0 && this.supervisorCtx?.facets?.abort) {
396
+ for (const name of this.doFacetNames) {
397
+ try {
398
+ this.supervisorCtx.facets.abort(name, new Error('nimbus-wrangler rebuilding'));
399
+ }
400
+ catch { }
401
+ }
402
+ }
403
+ // Two-pass load to break the chicken-and-egg:
404
+ // Pass 1: load with NO env to extract any durable_objects classes.
405
+ // buildInnerEnv needs this.doClassMap to synthesize DO
406
+ // namespace bindings, but getDurableObjectClass() needs a
407
+ // worker stub, which we get only by loading.
408
+ // Pass 2: re-load with FULL env (including DO namespace shims)
409
+ // that the inner Worker actually uses.
410
+ //
411
+ // workerd caches by content hash, so the second load is cheap —
412
+ // it reuses the same compiled isolate and just swaps env.
413
+ const wrangCompatDate = this.config.compatibility_date || '2026-04-01';
414
+ // Filter flags that workerd refuses on dynamic-worker LOADER.load().
415
+ // `experimental` gates behind the parent process's --experimental
416
+ // CLI flag; dynamic workers can't inherit that, so workerd rejects
417
+ // the load with:
418
+ // "The compatibility flag experimental is experimental and may
419
+ // break or be removed in a future version of workerd. To use
420
+ // this flag, you must pass --experimental on the command line."
421
+ // The inner Worker rarely needs `experimental` — it's only required
422
+ // when the inner itself returns chained WorkerEntrypoint stubs
423
+ // across RPC (the NimbusLoaderRPC pattern, which WE implement but
424
+ // typical user Workers do not). Strip it here; document in the
425
+ // warning log so users who legitimately need it know.
426
+ const rawFlags = this.config.compatibility_flags || [];
427
+ const wrangCompatFlags = rawFlags.filter((f) => f !== 'experimental');
428
+ if (rawFlags.length !== wrangCompatFlags.length) {
429
+ this.onLog(` \x1b[2mnote: stripped 'experimental' from inner compat_flags (not propagatable via LOADER.load)\x1b[0m\n`);
430
+ }
431
+ const baseWorkerCode = {
432
+ compatibilityDate: wrangCompatDate,
433
+ compatibilityFlags: wrangCompatFlags,
434
+ mainModule: 'worker.js',
435
+ modules: { 'worker.js': bundledCode },
436
+ };
437
+ // Pass 1: class extraction (no env, no DO shims).
438
+ this.doClassMap.clear();
439
+ const doBindings = this.config.durable_objects?.bindings || [];
440
+ if (doBindings.length > 0) {
441
+ let probeWorker;
442
+ try {
443
+ probeWorker = this.loaderEnv.LOADER.load(baseWorkerCode);
444
+ }
445
+ catch (e) {
446
+ this.onLog(` \x1b[31mBuild error (probe load): ${e?.message || e}\x1b[0m\n`);
447
+ return false;
448
+ }
449
+ for (const b of doBindings) {
450
+ if (b.script_name && b.script_name !== this.config.name) {
451
+ this.onLog(` \x1b[31merror: durable_objects binding '${b.name}' references external script '${b.script_name}'. nimbus-wrangler cannot load external Workers by name.\x1b[0m\n`);
452
+ return false;
453
+ }
454
+ try {
455
+ const cls = probeWorker.getDurableObjectClass(b.class_name);
456
+ this.doClassMap.set(b.name, cls);
457
+ }
458
+ catch (e) {
459
+ this.onLog(` \x1b[31merror: durable_objects binding '${b.name}' => class '${b.class_name}' not found in bundle: ${e?.message || e}\x1b[0m\n`);
460
+ return false;
461
+ }
462
+ }
463
+ }
464
+ // Pass 2: real load with the full synthesized env. buildInnerEnv
465
+ // reads this.doClassMap populated above.
466
+ const innerEnv = this.buildInnerEnv();
467
+ const worker = this.loaderEnv.LOADER.load({
468
+ ...baseWorkerCode,
469
+ env: innerEnv,
470
+ });
471
+ this.workerStub = worker.getEntrypoint();
472
+ for (const w of result.warnings || []) {
473
+ this.onLog(` \x1b[33mwarning: ${w.text}\x1b[0m\n`);
474
+ }
475
+ this.onLog(` \x1b[32mWorker built (v${this.buildVersion}, ${bundledCode.length} bytes)\x1b[0m\n`);
476
+ return true;
477
+ }
478
+ catch (e) {
479
+ this.onLog(` \x1b[31mBuild error: ${e?.message || e}\x1b[0m\n`);
480
+ return false;
481
+ }
482
+ }
483
+ // ── Inner env synthesis ──────────────────────────────────────────────
484
+ //
485
+ // buildInnerEnv assembles the `env` object that the inner Worker's
486
+ // fetch(request, env, ctx) will see. Each binding category is built
487
+ // by a dedicated helper so they can be added/removed in isolation.
488
+ //
489
+ // Phases land in this order:
490
+ // Phase 0: vars + services (+ preflight of unsupported fields)
491
+ // Phase 1: assets → env[binding] = ctx.exports.NimbusAssetsRPC(...)
492
+ // Phase 2: worker_loaders → env[binding] = ctx.exports.NimbusLoaderRPC(...)
493
+ // Phase 3: durable_objects → env[binding] = synthesized DO namespace shim
494
+ //
495
+ // At the end of each phase the inner Worker has one more kind of binding
496
+ // it can access by name. Phase 0 is the plumbing: adding the `env` field
497
+ // to LOADER.load() at all, plus forwarding plain string vars.
498
+ buildInnerEnv() {
499
+ const env = {};
500
+ // ── vars ──
501
+ // Straight string copy. Collisions with synthesized binding names
502
+ // (later phases) would be surprising, so later phases will warn if
503
+ // they overwrite a vars-provided key.
504
+ if (this.config?.vars) {
505
+ for (const [k, v] of Object.entries(this.config.vars)) {
506
+ env[k] = v;
507
+ }
508
+ }
509
+ // ── services ──
510
+ // Honor a service binding only if the outer env has a field with the
511
+ // same NAME as the declared binding. In wrangler the `binding` field
512
+ // is the variable name inside the worker, while `service` is the name
513
+ // of the target deployed worker; in dev we only have the outer env's
514
+ // existing bindings to forward. Warn on every other case so the user
515
+ // knows not to expect real-wrangler passthrough.
516
+ if (this.config?.services?.length) {
517
+ for (const s of this.config.services) {
518
+ const name = s.binding;
519
+ if (!name)
520
+ continue;
521
+ if (this.loaderEnv && name in this.loaderEnv) {
522
+ env[name] = this.loaderEnv[name];
523
+ }
524
+ else {
525
+ this.onLog(` \x1b[33mwarning: services binding '${name}' not present in outer env; env.${name} will be undefined\x1b[0m\n`);
526
+ }
527
+ }
528
+ }
529
+ // ── assets ──
530
+ // Inner worker: env[binding].fetch(request) → reads a file under
531
+ // <vfsRoot>/<assetsDir>/<pathname>. Implemented via a WorkerEntrypoint
532
+ // loopback binding (NimbusAssetsRPC, re-exported from index.ts so
533
+ // ctx.exports auto-populates it).
534
+ if (this.config?.assets) {
535
+ const binding = this.config.assets.binding || 'ASSETS';
536
+ const directory = String(this.config.assets.directory || 'public');
537
+ const assetsDir = directory.replace(/^\.\//, '').replace(/^\/+/, '').replace(/\/+$/, '');
538
+ const ctxExports = this.supervisorCtx?.exports;
539
+ const doId = this.supervisorCtx?.id?.toString?.() || '';
540
+ if (!ctxExports?.NimbusAssetsRPC) {
541
+ this.onLog(` \x1b[33mwarning: ctx.exports.NimbusAssetsRPC unavailable; env.${binding} will not work\x1b[0m\n`);
542
+ }
543
+ else if (!doId) {
544
+ this.onLog(` \x1b[33mwarning: supervisor DO id unavailable; env.${binding} will not work\x1b[0m\n`);
545
+ }
546
+ else {
547
+ if (binding in env) {
548
+ this.onLog(` \x1b[33mwarning: assets binding '${binding}' overwrites a vars/services key with the same name\x1b[0m\n`);
549
+ }
550
+ env[binding] = ctxExports.NimbusAssetsRPC({
551
+ props: {
552
+ vfsRoot: this.root,
553
+ assetsDir,
554
+ doId,
555
+ },
556
+ });
557
+ }
558
+ }
559
+ // ── worker_loaders ──
560
+ // Inner worker: env[binding].load({...}) / env[binding].get(id, cb).
561
+ // Implemented as a WorkerEntrypoint that forwards to the OUTER
562
+ // env.LOADER. Each inner call increments the `depth` prop; the
563
+ // handler rejects once depth exceeds the configured cap (default 4,
564
+ // override via the outer session's NIMBUS_INNER_LOADER_DEPTH env).
565
+ if (this.config?.worker_loaders?.length) {
566
+ const ctxExports = this.supervisorCtx?.exports;
567
+ if (!ctxExports?.NimbusLoaderRPC) {
568
+ for (const wl of this.config.worker_loaders) {
569
+ this.onLog(` \x1b[33mwarning: ctx.exports.NimbusLoaderRPC unavailable; env.${wl.binding} will not work\x1b[0m\n`);
570
+ }
571
+ }
572
+ else {
573
+ const currentDepth = this.loaderEnv?.NIMBUS_INNER_LOADER_DEPTH_CURRENT
574
+ ? parseInt(String(this.loaderEnv.NIMBUS_INNER_LOADER_DEPTH_CURRENT), 10) || 0
575
+ : 0;
576
+ const nextDepth = currentDepth + 1;
577
+ for (const wl of this.config.worker_loaders) {
578
+ const binding = wl.binding;
579
+ if (!binding)
580
+ continue;
581
+ if (binding in env) {
582
+ this.onLog(` \x1b[33mwarning: worker_loaders binding '${binding}' overwrites a previous key\x1b[0m\n`);
583
+ }
584
+ env[binding] = ctxExports.NimbusLoaderRPC({
585
+ props: { depth: nextDepth },
586
+ });
587
+ }
588
+ }
589
+ }
590
+ // ── durable_objects ──
591
+ // Inner worker: env[binding].idFromName(name) + env[binding].get(id).fetch(req).
592
+ // The class list was resolved and stored in this.doClassMap during
593
+ // buildAndLoad(); register each class into the module-level
594
+ // registry consulted by _rpcInnerDoFetch, then synthesize the
595
+ // namespace stub via ctx.exports.NimbusDurableObjectNamespace(...).
596
+ if (this.doClassMap.size > 0) {
597
+ const ctxExports = this.supervisorCtx?.exports;
598
+ const doId = this.supervisorCtx?.id?.toString?.() || '';
599
+ if (!ctxExports?.NimbusDurableObjectNamespace) {
600
+ for (const [bindingName] of this.doClassMap) {
601
+ this.onLog(` \x1b[33mwarning: ctx.exports.NimbusDurableObjectNamespace unavailable; env.${bindingName} will not work\x1b[0m\n`);
602
+ }
603
+ }
604
+ else if (!doId) {
605
+ for (const [bindingName] of this.doClassMap) {
606
+ this.onLog(` \x1b[33mwarning: supervisor DO id unavailable; env.${bindingName} will not work\x1b[0m\n`);
607
+ }
608
+ }
609
+ else {
610
+ // Clear + repopulate the registry for this supervisor DO id.
611
+ clearInnerDoClasses(doId);
612
+ for (const [bindingName, cls] of this.doClassMap) {
613
+ registerInnerDoClass(doId, bindingName, cls);
614
+ if (bindingName in env) {
615
+ this.onLog(` \x1b[33mwarning: durable_objects binding '${bindingName}' overwrites a previous key\x1b[0m\n`);
616
+ }
617
+ env[bindingName] = ctxExports.NimbusDurableObjectNamespace({
618
+ props: {
619
+ bindingName,
620
+ supervisorDoId: doId,
621
+ },
622
+ });
623
+ // Track facet names we might create later so stop() can abort
624
+ // them cleanly. Exact ids aren't known until inner calls
625
+ // .get(id), so we just track the base name.
626
+ this.doFacetNames.add('innerDO-' + bindingName + '-*');
627
+ }
628
+ }
629
+ }
630
+ // ── kv_namespaces ── (W10)
631
+ // Inner worker: env[binding].get(key) / put / delete / list /
632
+ // getWithMetadata. Implementation is a plain JS class (KvEmulator)
633
+ // backed by SqliteVFS file blobs at <root>/.nimbus/kv/<binding>/.
634
+ // No ctx.exports loopback needed: KV is pure data, no callbacks
635
+ // back into the supervisor's fetch handlers. Each emulator instance
636
+ // is bound to one (binding, root) pair.
637
+ if (this.config?.kv_namespaces?.length) {
638
+ for (const kv of this.config.kv_namespaces) {
639
+ if (!kv.binding)
640
+ continue;
641
+ if (kv.binding in env) {
642
+ this.onLog(` \x1b[33mwarning: kv_namespaces binding '${kv.binding}' overwrites a previous key\x1b[0m\n`);
643
+ }
644
+ env[kv.binding] = new KvEmulator({
645
+ vfs: this.vfs,
646
+ root: this.root,
647
+ binding: kv.binding,
648
+ onLog: this.onLog,
649
+ });
650
+ }
651
+ }
652
+ // ── d1_databases ── (W10)
653
+ // Inner worker: env[binding].prepare(query) / batch / exec.
654
+ // Implementation: D1Emulator backed by the supervisor's SqlStorage
655
+ // with per-binding table-prefix isolation. See plan §14.1 — a
656
+ // child-DO-facet-per-binding upgrade is the W10.5 candidate.
657
+ //
658
+ // migrations_dir is honored: applyMigrations() walks the directory
659
+ // alphabetically and replays each .sql file once (idempotent via
660
+ // a per-binding ledger table).
661
+ if (this.config?.d1_databases?.length) {
662
+ const sqlStorage = this.supervisorCtx?.storage?.sql;
663
+ if (!sqlStorage) {
664
+ for (const d1 of this.config.d1_databases) {
665
+ this.onLog(` \x1b[33mwarning: ctx.storage.sql unavailable; env.${d1.binding} will not work\x1b[0m\n`);
666
+ }
667
+ }
668
+ else {
669
+ for (const d1 of this.config.d1_databases) {
670
+ if (!d1.binding)
671
+ continue;
672
+ if (d1.binding in env) {
673
+ this.onLog(` \x1b[33mwarning: d1_databases binding '${d1.binding}' overwrites a previous key\x1b[0m\n`);
674
+ }
675
+ const emu = new D1Emulator({
676
+ sqlStorage,
677
+ binding: d1.binding,
678
+ vfs: this.vfs,
679
+ root: this.root,
680
+ migrationsDir: d1.migrations_dir,
681
+ onLog: this.onLog,
682
+ });
683
+ env[d1.binding] = emu;
684
+ // Fire migrations in the background. They're idempotent so
685
+ // racing rebuilds is safe.
686
+ if (d1.migrations_dir) {
687
+ emu.applyMigrations().then((r) => {
688
+ if (r.applied > 0) {
689
+ this.onLog(` \x1b[2mD1 ${d1.binding}: applied ${r.applied} migrations\x1b[0m\n`);
690
+ }
691
+ }).catch((e) => {
692
+ this.onLog(` \x1b[33mwarning: D1 ${d1.binding} migrations failed: ${e?.message || e}\x1b[0m\n`);
693
+ });
694
+ }
695
+ }
696
+ }
697
+ }
698
+ // ── r2_buckets ── (W10)
699
+ // Inner worker: env[binding].get(key) / put / head / list / delete.
700
+ // Implementation: R2Emulator backed by SqliteVFS file blobs at
701
+ // <root>/.nimbus/r2/<binding>/. Etag is sha256(body); conditionals
702
+ // (etagMatches/etagDoesNotMatch/uploaded*) are honored.
703
+ //
704
+ // Multipart upload methods throw a clear "not supported" error
705
+ // (W10.5 candidate; see plan §13 review B4).
706
+ if (this.config?.r2_buckets?.length) {
707
+ for (const r2 of this.config.r2_buckets) {
708
+ if (!r2.binding)
709
+ continue;
710
+ if (r2.binding in env) {
711
+ this.onLog(` \x1b[33mwarning: r2_buckets binding '${r2.binding}' overwrites a previous key\x1b[0m\n`);
712
+ }
713
+ env[r2.binding] = new R2Emulator({
714
+ vfs: this.vfs,
715
+ root: this.root,
716
+ binding: r2.binding,
717
+ onLog: this.onLog,
718
+ });
719
+ }
720
+ }
721
+ return env;
722
+ }
723
+ // ── VFS event handling (hot reload) ───────────────────────────────────
724
+ handleVfsEvents(events) {
725
+ if (!this.running)
726
+ return;
727
+ // Check if any changed file is under our project root
728
+ let needsRebuild = false;
729
+ for (const event of events) {
730
+ if (event.type !== 'change' && event.type !== 'add' && event.type !== 'unlink')
731
+ continue;
732
+ if (event.path.startsWith(this.root) &&
733
+ !event.path.includes('node_modules/') &&
734
+ !event.path.includes('/.nimbus/')) {
735
+ // W10: skip writes by KV/D1/R2 emulators (they live under
736
+ // <root>/.nimbus/{kv,r2}/...) — otherwise every emulator put
737
+ // triggers a rebuild and the system feedback-loops itself.
738
+ needsRebuild = true;
739
+ break;
740
+ }
741
+ }
742
+ if (!needsRebuild)
743
+ return;
744
+ // Debounce rebuilds (250ms — allows rapid saves to coalesce)
745
+ if (this.rebuildTimer)
746
+ clearTimeout(this.rebuildTimer);
747
+ this.rebuildTimer = setTimeout(async () => {
748
+ this.rebuildTimer = null;
749
+ this.onLog('\n \x1b[33mFile change detected, rebuilding...\x1b[0m\n');
750
+ const ok = await this.buildAndLoad();
751
+ if (ok) {
752
+ this.onHmrMessage({ type: 'nimbus-hmr', event: 'full-reload' });
753
+ }
754
+ }, 250);
755
+ }
756
+ // ── Request handling ──────────────────────────────────────────────────
757
+ /**
758
+ * Forward a request to the user's Worker.
759
+ * Called from the DO's fetch() handler for /worker/* paths.
760
+ *
761
+ * Three things this proxy does besides a raw fetch:
762
+ * 1. Buffers the request body to an ArrayBuffer before forwarding.
763
+ * The inner Worker can legitimately respond with a 302 (e.g.
764
+ * Nimbus-in-Nimbus: POST /new → 302 /s/<id>/). Workerd's `fetch`
765
+ * defaults to follow-redirects which requires replaying the body;
766
+ * a stream body can only be read once. Buffering first sidesteps
767
+ * the "one-time-use body encountered a redirect" error. POSTs to
768
+ * Nimbus's own /new endpoint are typically empty, but KV/D1 sims
769
+ * and user workers may send non-trivial bodies.
770
+ * 2. Uses `redirect: 'manual'` so the inner's Location header comes
771
+ * back unchanged. We rewrite it below to prepend the outer worker
772
+ * prefix — otherwise the browser follows a bare `/s/<id>/` URL,
773
+ * which is an OUTER route and spawns a different session, not
774
+ * what the user wanted.
775
+ * 3. Replaces a "Not found" 404 at the inner root with a small
776
+ * landing page. Nimbus itself (the likely inner worker) has no
777
+ * route for `/` when loaded without an ASSETS binding — users
778
+ * hitting `/s/<outer>/worker/` directly would otherwise see a
779
+ * bare 9-byte "Not found" response and think the whole thing
780
+ * broke. The landing page explains the Worker is running and
781
+ * points them at `/worker/new` / their own routes.
782
+ */
783
+ async handleRequest(request, pathname,
784
+ /**
785
+ * Outer-facing prefix of this proxy (e.g. "/s/nimble-otter-4271/worker").
786
+ * Used to rewrite inner-emitted Location headers that reference
787
+ * their own origin-relative paths. When absent, Location headers
788
+ * are passed through unchanged.
789
+ */
790
+ outerWorkerBase) {
791
+ if (!this.workerStub) {
792
+ return new Response('Worker not loaded', { status: 503 });
793
+ }
794
+ try {
795
+ // Build a new Request with the rewritten URL
796
+ const workerUrl = new URL(request.url);
797
+ workerUrl.pathname = pathname;
798
+ // Buffer the body up front. Necessary even when we set
799
+ // redirect: 'manual' (see below) because workerd's internal
800
+ // fetch plumbing can still try to replay a streaming body in
801
+ // some paths (e.g. retry-after errors). Capturing once here is
802
+ // both correct and cheap — user worker requests are small.
803
+ let bodyBuffer;
804
+ if (request.method !== 'GET' && request.method !== 'HEAD') {
805
+ bodyBuffer = await request.arrayBuffer();
806
+ }
807
+ const workerReq = new Request(workerUrl.toString(), {
808
+ method: request.method,
809
+ headers: request.headers,
810
+ body: bodyBuffer,
811
+ // Don't auto-follow: a 302 to /s/<id>/ from the inner is its
812
+ // OWN path, not a path we can resolve — we need to rewrite
813
+ // and propagate it to the browser so the user lands on the
814
+ // correctly-prefixed outer URL.
815
+ redirect: 'manual',
816
+ });
817
+ const response = await this.workerStub.fetch(workerReq);
818
+ // ── Response post-processing ─────────────────────────────────
819
+ const newHeaders = new Headers(response.headers);
820
+ newHeaders.set('Access-Control-Allow-Origin', '*');
821
+ // (2) Rewrite Location headers so browser-follow lands on the
822
+ // outer-prefixed URL. Only rewrite for same-origin redirects —
823
+ // absolute cross-origin URLs pass through untouched.
824
+ if (outerWorkerBase && (response.status === 301 || response.status === 302 ||
825
+ response.status === 303 || response.status === 307 ||
826
+ response.status === 308)) {
827
+ const loc = response.headers.get('Location');
828
+ if (loc) {
829
+ const rewritten = rewriteLocationForOuter(loc, outerWorkerBase, request.url);
830
+ if (rewritten !== loc)
831
+ newHeaders.set('Location', rewritten);
832
+ }
833
+ }
834
+ // (3) Replace a bare "Not found" at the root with a helpful landing.
835
+ // We detect this conservatively: only a literal "Not found" body
836
+ // with status 404 for a request to "/", which is exactly what
837
+ // Nimbus-as-inner emits when its default fallthrough runs. User
838
+ // workers that deliberately return 404 at other paths are untouched.
839
+ if (response.status === 404 && pathname === '/') {
840
+ const bodyText = await response.clone().text();
841
+ if (bodyText === 'Not found' || bodyText.length === 0) {
842
+ const html = renderWorkerRunningHtml({
843
+ workerName: this.config?.name || 'user worker',
844
+ outerWorkerBase: outerWorkerBase || '/worker',
845
+ });
846
+ return new Response(html, {
847
+ status: 200,
848
+ headers: {
849
+ 'Content-Type': 'text/html; charset=utf-8',
850
+ 'Cache-Control': 'no-store',
851
+ 'Access-Control-Allow-Origin': '*',
852
+ },
853
+ });
854
+ }
855
+ }
856
+ return new Response(response.body, {
857
+ status: response.status,
858
+ statusText: response.statusText,
859
+ headers: newHeaders,
860
+ });
861
+ }
862
+ catch (e) {
863
+ return Response.json({ error: e?.message || String(e) }, { status: 500, headers: { 'Access-Control-Allow-Origin': '*' } });
864
+ }
865
+ }
866
+ get stats() {
867
+ return {
868
+ running: this.running,
869
+ name: this.config?.name || 'unknown',
870
+ main: this.config?.main || 'unknown',
871
+ root: this.root,
872
+ buildVersion: this.buildVersion,
873
+ };
874
+ }
875
+ // ── Test seams (W10 probes) ───────────────────────────────────────────
876
+ //
877
+ // These exist so probes can drive specific code paths (config parse,
878
+ // env synthesis, watcher installation) without running the full
879
+ // start() pipeline (which requires a real esbuild + LOADER + ctx).
880
+ //
881
+ // Production code does NOT use these; they're stable contracts only
882
+ // for the test probes. Naming convention: leading underscore + ForTest
883
+ // suffix.
884
+ /** @internal — test seam: parse the wrangler config and store it. Returns true on success. */
885
+ _readConfigForTest() {
886
+ this.config = this.readConfig();
887
+ return this.config != null;
888
+ }
889
+ /** @internal — test seam: invoke buildInnerEnv() without a probe-load pass. */
890
+ _buildInnerEnvForTest() {
891
+ return this.buildInnerEnv();
892
+ }
893
+ /** @internal — test seam: install the VFS file-watch listener and the
894
+ * mock-rebuild path (esbuild.build() is called, but the real
895
+ * buildAndLoad() pipeline is bypassed in favour of just calling
896
+ * esbuild). Used for hot-reload latency + nimbus-paths-not-watched
897
+ * probes. Production calls start() which installs the watcher AND the
898
+ * full rebuild pipeline. */
899
+ _installWatchersForTest() {
900
+ this.running = true;
901
+ this.unsubVfs = this.vfs.events.on(async (events) => {
902
+ let needsRebuild = false;
903
+ for (const event of events) {
904
+ if (event.type !== 'change' && event.type !== 'add' && event.type !== 'unlink')
905
+ continue;
906
+ if (event.path.startsWith(this.root) &&
907
+ !event.path.includes('node_modules/') &&
908
+ !event.path.includes('/.nimbus/')) {
909
+ needsRebuild = true;
910
+ break;
911
+ }
912
+ }
913
+ if (!needsRebuild)
914
+ return;
915
+ if (this.rebuildTimer)
916
+ clearTimeout(this.rebuildTimer);
917
+ this.rebuildTimer = setTimeout(async () => {
918
+ this.rebuildTimer = null;
919
+ try {
920
+ // Same canonicalization as the initial build — see
921
+ // resolveEntryPath().
922
+ await this.esbuild.build([this.resolveEntryPath()], {
923
+ bundle: true, format: 'esm', target: 'esnext', platform: 'neutral',
924
+ });
925
+ this.onHmrMessage({ type: 'nimbus-hmr', event: 'full-reload' });
926
+ }
927
+ catch { }
928
+ }, 250);
929
+ });
930
+ }
931
+ }