@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.
- package/README.md +219 -0
- package/dist/_shared/bytes.d.ts +18 -0
- package/dist/_shared/bytes.d.ts.map +1 -0
- package/dist/_shared/bytes.js +17 -0
- package/dist/_shared/cache-stats.d.ts +146 -0
- package/dist/_shared/cache-stats.d.ts.map +1 -0
- package/dist/_shared/cache-stats.js +162 -0
- package/dist/_shared/exports-resolver.d.ts +76 -0
- package/dist/_shared/exports-resolver.d.ts.map +1 -0
- package/dist/_shared/exports-resolver.js +284 -0
- package/dist/_shared/install-phase.d.ts +47 -0
- package/dist/_shared/install-phase.d.ts.map +1 -0
- package/dist/_shared/install-phase.js +1 -0
- package/dist/_shared/real-node-imports.d.ts +38 -0
- package/dist/_shared/real-node-imports.d.ts.map +1 -0
- package/dist/_shared/real-node-imports.js +46 -0
- package/dist/_shared/retry.d.ts +93 -0
- package/dist/_shared/retry.d.ts.map +1 -0
- package/dist/_shared/retry.js +161 -0
- package/dist/_shared/session-id.d.ts +39 -0
- package/dist/_shared/session-id.d.ts.map +1 -0
- package/dist/_shared/session-id.js +127 -0
- package/dist/_shared/session-router.d.ts +104 -0
- package/dist/_shared/session-router.d.ts.map +1 -0
- package/dist/_shared/session-router.js +165 -0
- package/dist/_shared/w7-frame.d.ts +93 -0
- package/dist/_shared/w7-frame.d.ts.map +1 -0
- package/dist/_shared/w7-frame.js +402 -0
- package/dist/auth/index.d.ts +16 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +15 -0
- package/dist/auth/middleware.d.ts +85 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +150 -0
- package/dist/auth/token.d.ts +96 -0
- package/dist/auth/token.d.ts.map +1 -0
- package/dist/auth/token.js +226 -0
- package/dist/auth/types.d.ts +141 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +114 -0
- package/dist/bindings/d1.d.ts +102 -0
- package/dist/bindings/d1.d.ts.map +1 -0
- package/dist/bindings/d1.js +549 -0
- package/dist/bindings/kv.d.ts +82 -0
- package/dist/bindings/kv.d.ts.map +1 -0
- package/dist/bindings/kv.js +290 -0
- package/dist/bindings/r2.d.ts +137 -0
- package/dist/bindings/r2.d.ts.map +1 -0
- package/dist/bindings/r2.js +379 -0
- package/dist/cirrus-npm-cjs.generated.d.ts +17 -0
- package/dist/cirrus-npm-cjs.generated.d.ts.map +1 -0
- package/dist/cirrus-npm-cjs.generated.js +41 -0
- package/dist/cirrus-plugin-react.generated.d.ts +34 -0
- package/dist/cirrus-plugin-react.generated.d.ts.map +1 -0
- package/dist/cirrus-plugin-react.generated.js +33 -0
- package/dist/constants.d.ts +34 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +116 -0
- package/dist/esbuild-wasm-bundle.generated.d.ts +41 -0
- package/dist/esbuild-wasm-bundle.generated.d.ts.map +1 -0
- package/dist/esbuild-wasm-bundle.generated.js +40 -0
- package/dist/facets/cirrus-real.d.ts +147 -0
- package/dist/facets/cirrus-real.d.ts.map +1 -0
- package/dist/facets/cirrus-real.js +981 -0
- package/dist/facets/inner-do-registry.d.ts +41 -0
- package/dist/facets/inner-do-registry.d.ts.map +1 -0
- package/dist/facets/inner-do-registry.js +51 -0
- package/dist/facets/manager.d.ts +314 -0
- package/dist/facets/manager.d.ts.map +1 -0
- package/dist/facets/manager.js +2681 -0
- package/dist/facets/process.d.ts +318 -0
- package/dist/facets/process.d.ts.map +1 -0
- package/dist/facets/process.js +567 -0
- package/dist/facets/real-vite-fs-shim.d.ts +151 -0
- package/dist/facets/real-vite-fs-shim.d.ts.map +1 -0
- package/dist/facets/real-vite-fs-shim.js +1279 -0
- package/dist/facets/real-vite-hmr.d.ts +142 -0
- package/dist/facets/real-vite-hmr.d.ts.map +1 -0
- package/dist/facets/real-vite-hmr.js +476 -0
- package/dist/facets/vite-dev-server.d.ts +293 -0
- package/dist/facets/vite-dev-server.d.ts.map +1 -0
- package/dist/facets/vite-dev-server.js +2580 -0
- package/dist/facets/wasm-swap-registry.d.ts +261 -0
- package/dist/facets/wasm-swap-registry.d.ts.map +1 -0
- package/dist/facets/wasm-swap-registry.js +551 -0
- package/dist/facets/ws-terminal.d.ts +107 -0
- package/dist/facets/ws-terminal.d.ts.map +1 -0
- package/dist/facets/ws-terminal.js +207 -0
- package/dist/git/commands.d.ts +13 -0
- package/dist/git/commands.d.ts.map +1 -0
- package/dist/git/commands.js +633 -0
- package/dist/git/network-facet.d.ts +61 -0
- package/dist/git/network-facet.d.ts.map +1 -0
- package/dist/git/network-facet.js +700 -0
- package/dist/git-bundle.generated.d.ts +16 -0
- package/dist/git-bundle.generated.d.ts.map +1 -0
- package/dist/git-bundle.generated.js +15 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/loaders/child-process/spawn-facet.d.ts +90 -0
- package/dist/loaders/child-process/spawn-facet.d.ts.map +1 -0
- package/dist/loaders/child-process/spawn-facet.js +103 -0
- package/dist/loaders/child-process/spawn-pool.d.ts +110 -0
- package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -0
- package/dist/loaders/child-process/spawn-pool.js +161 -0
- package/dist/loaders/fanout-pool.d.ts +195 -0
- package/dist/loaders/fanout-pool.d.ts.map +1 -0
- package/dist/loaders/fanout-pool.js +326 -0
- package/dist/loaders/generated-workers.d.ts +26 -0
- package/dist/loaders/generated-workers.d.ts.map +1 -0
- package/dist/loaders/generated-workers.js +25 -0
- package/dist/loaders/index.d.ts +15 -0
- package/dist/loaders/index.d.ts.map +1 -0
- package/dist/loaders/index.js +13 -0
- package/dist/loaders/loader-pool.d.ts +273 -0
- package/dist/loaders/loader-pool.d.ts.map +1 -0
- package/dist/loaders/loader-pool.js +624 -0
- package/dist/loaders/npm-resolve-preamble.d.ts +34 -0
- package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -0
- package/dist/loaders/npm-resolve-preamble.js +237 -0
- package/dist/loaders/pre-bundle-preamble.d.ts +41 -0
- package/dist/loaders/pre-bundle-preamble.d.ts.map +1 -0
- package/dist/loaders/pre-bundle-preamble.js +114 -0
- package/dist/loaders/vendor/codegen.d.ts +24 -0
- package/dist/loaders/vendor/codegen.d.ts.map +1 -0
- package/dist/loaders/vendor/codegen.js +44 -0
- package/dist/loaders/vendor/errors.d.ts +24 -0
- package/dist/loaders/vendor/errors.d.ts.map +1 -0
- package/dist/loaders/vendor/errors.js +46 -0
- package/dist/loaders/vendor/index.d.ts +16 -0
- package/dist/loaders/vendor/index.d.ts.map +1 -0
- package/dist/loaders/vendor/index.js +11 -0
- package/dist/loaders/vendor/pool.d.ts +88 -0
- package/dist/loaders/vendor/pool.d.ts.map +1 -0
- package/dist/loaders/vendor/pool.js +353 -0
- package/dist/loaders/vendor/primitives.d.ts +11 -0
- package/dist/loaders/vendor/primitives.d.ts.map +1 -0
- package/dist/loaders/vendor/primitives.js +33 -0
- package/dist/loaders/vendor/serialize.d.ts +3 -0
- package/dist/loaders/vendor/serialize.d.ts.map +1 -0
- package/dist/loaders/vendor/serialize.js +25 -0
- package/dist/loaders/vendor/types.d.ts +60 -0
- package/dist/loaders/vendor/types.d.ts.map +1 -0
- package/dist/loaders/vendor/types.js +4 -0
- package/dist/npm/cache.d.ts +136 -0
- package/dist/npm/cache.d.ts.map +1 -0
- package/dist/npm/cache.js +429 -0
- package/dist/npm/install-batch-facet.d.ts +129 -0
- package/dist/npm/install-batch-facet.d.ts.map +1 -0
- package/dist/npm/install-batch-facet.js +598 -0
- package/dist/npm/install-facet.d.ts +29 -0
- package/dist/npm/install-facet.d.ts.map +1 -0
- package/dist/npm/install-facet.js +9 -0
- package/dist/npm/installer.d.ts +239 -0
- package/dist/npm/installer.d.ts.map +1 -0
- package/dist/npm/installer.js +2022 -0
- package/dist/npm/npx-install.d.ts +74 -0
- package/dist/npm/npx-install.d.ts.map +1 -0
- package/dist/npm/npx-install.js +302 -0
- package/dist/npm/pre-bundle-facet.d.ts +168 -0
- package/dist/npm/pre-bundle-facet.d.ts.map +1 -0
- package/dist/npm/pre-bundle-facet.js +653 -0
- package/dist/npm/r2-cache.d.ts +286 -0
- package/dist/npm/r2-cache.d.ts.map +1 -0
- package/dist/npm/r2-cache.js +506 -0
- package/dist/npm/resolve-facet.d.ts +202 -0
- package/dist/npm/resolve-facet.d.ts.map +1 -0
- package/dist/npm/resolve-facet.js +833 -0
- package/dist/npm/resolve-one-facet.d.ts +204 -0
- package/dist/npm/resolve-one-facet.d.ts.map +1 -0
- package/dist/npm/resolve-one-facet.js +437 -0
- package/dist/npm/resolver.d.ts +109 -0
- package/dist/npm/resolver.d.ts.map +1 -0
- package/dist/npm/resolver.js +899 -0
- package/dist/npm/tarball-stream.d.ts +85 -0
- package/dist/npm/tarball-stream.d.ts.map +1 -0
- package/dist/npm/tarball-stream.js +205 -0
- package/dist/npm/tarball.d.ts +51 -0
- package/dist/npm/tarball.d.ts.map +1 -0
- package/dist/npm/tarball.js +185 -0
- package/dist/observability/diag-counters.d.ts +292 -0
- package/dist/observability/diag-counters.d.ts.map +1 -0
- package/dist/observability/diag-counters.js +302 -0
- package/dist/observability/heap-estimate.d.ts +166 -0
- package/dist/observability/heap-estimate.d.ts.map +1 -0
- package/dist/observability/heap-estimate.js +192 -0
- package/dist/observability/heavy-alloc-coord.d.ts +95 -0
- package/dist/observability/heavy-alloc-coord.d.ts.map +1 -0
- package/dist/observability/heavy-alloc-coord.js +149 -0
- package/dist/observability/oom-classify.d.ts +56 -0
- package/dist/observability/oom-classify.d.ts.map +1 -0
- package/dist/observability/oom-classify.js +118 -0
- package/dist/observability/oom-discriminator.d.ts +192 -0
- package/dist/observability/oom-discriminator.d.ts.map +1 -0
- package/dist/observability/oom-discriminator.js +233 -0
- package/dist/real-vite-bundle.generated.d.ts +46 -0
- package/dist/real-vite-bundle.generated.d.ts.map +1 -0
- package/dist/real-vite-bundle.generated.js +53 -0
- package/dist/replica/routing.d.ts +171 -0
- package/dist/replica/routing.d.ts.map +1 -0
- package/dist/replica/routing.js +288 -0
- package/dist/replica/suspension.d.ts +36 -0
- package/dist/replica/suspension.d.ts.map +1 -0
- package/dist/replica/suspension.js +49 -0
- package/dist/router/index.d.ts +156 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +220 -0
- package/dist/runtime/assets-loader.d.ts +71 -0
- package/dist/runtime/assets-loader.d.ts.map +1 -0
- package/dist/runtime/assets-loader.js +128 -0
- package/dist/runtime/barrel-detect.d.ts +46 -0
- package/dist/runtime/barrel-detect.d.ts.map +1 -0
- package/dist/runtime/barrel-detect.js +73 -0
- package/dist/runtime/barrel-synthesizer.d.ts +181 -0
- package/dist/runtime/barrel-synthesizer.d.ts.map +1 -0
- package/dist/runtime/barrel-synthesizer.js +541 -0
- package/dist/runtime/bun-repl.d.ts +46 -0
- package/dist/runtime/bun-repl.d.ts.map +1 -0
- package/dist/runtime/bun-repl.js +326 -0
- package/dist/runtime/bun-runner.d.ts +66 -0
- package/dist/runtime/bun-runner.d.ts.map +1 -0
- package/dist/runtime/bun-runner.js +219 -0
- package/dist/runtime/clang-runner.d.ts +38 -0
- package/dist/runtime/clang-runner.d.ts.map +1 -0
- package/dist/runtime/clang-runner.js +1033 -0
- package/dist/runtime/comment-strip.d.ts +37 -0
- package/dist/runtime/comment-strip.d.ts.map +1 -0
- package/dist/runtime/comment-strip.js +74 -0
- package/dist/runtime/esbuild-service.d.ts +201 -0
- package/dist/runtime/esbuild-service.d.ts.map +1 -0
- package/dist/runtime/esbuild-service.js +1444 -0
- package/dist/runtime/esbuild-wasm-bytes.d.ts +87 -0
- package/dist/runtime/esbuild-wasm-bytes.d.ts.map +1 -0
- package/dist/runtime/esbuild-wasm-bytes.js +131 -0
- package/dist/runtime/framework-detect.d.ts +71 -0
- package/dist/runtime/framework-detect.d.ts.map +1 -0
- package/dist/runtime/framework-detect.js +178 -0
- package/dist/runtime/long-running-handle.d.ts +133 -0
- package/dist/runtime/long-running-handle.d.ts.map +1 -0
- package/dist/runtime/long-running-handle.js +192 -0
- package/dist/runtime/node-repl.d.ts +36 -0
- package/dist/runtime/node-repl.d.ts.map +1 -0
- package/dist/runtime/node-repl.js +293 -0
- package/dist/runtime/node-runner.d.ts +111 -0
- package/dist/runtime/node-runner.d.ts.map +1 -0
- package/dist/runtime/node-runner.js +194 -0
- package/dist/runtime/node-shims.d.ts +24 -0
- package/dist/runtime/node-shims.d.ts.map +1 -0
- package/dist/runtime/node-shims.js +3019 -0
- package/dist/runtime/package-manager.d.ts +118 -0
- package/dist/runtime/package-manager.d.ts.map +1 -0
- package/dist/runtime/package-manager.js +420 -0
- package/dist/runtime/port-registry.d.ts +80 -0
- package/dist/runtime/port-registry.d.ts.map +1 -0
- package/dist/runtime/port-registry.js +166 -0
- package/dist/runtime/process-logs-api.d.ts +102 -0
- package/dist/runtime/process-logs-api.d.ts.map +1 -0
- package/dist/runtime/process-logs-api.js +253 -0
- package/dist/runtime/process-logs.d.ts +311 -0
- package/dist/runtime/process-logs.d.ts.map +1 -0
- package/dist/runtime/process-logs.js +656 -0
- package/dist/runtime/process-table.d.ts +65 -0
- package/dist/runtime/process-table.d.ts.map +1 -0
- package/dist/runtime/process-table.js +107 -0
- package/dist/runtime/project-detect.d.ts +21 -0
- package/dist/runtime/project-detect.d.ts.map +1 -0
- package/dist/runtime/project-detect.js +46 -0
- package/dist/runtime/python-repl.d.ts +66 -0
- package/dist/runtime/python-repl.d.ts.map +1 -0
- package/dist/runtime/python-repl.js +563 -0
- package/dist/runtime/python-runner.d.ts +50 -0
- package/dist/runtime/python-runner.d.ts.map +1 -0
- package/dist/runtime/python-runner.js +870 -0
- package/dist/runtime/repl-session.d.ts +160 -0
- package/dist/runtime/repl-session.d.ts.map +1 -0
- package/dist/runtime/repl-session.js +393 -0
- package/dist/runtime/require-resolver.d.ts +52 -0
- package/dist/runtime/require-resolver.d.ts.map +1 -0
- package/dist/runtime/require-resolver.js +690 -0
- package/dist/runtime/router-basename.d.ts +36 -0
- package/dist/runtime/router-basename.d.ts.map +1 -0
- package/dist/runtime/router-basename.js +310 -0
- package/dist/runtime/ruby-repl.d.ts +43 -0
- package/dist/runtime/ruby-repl.d.ts.map +1 -0
- package/dist/runtime/ruby-repl.js +229 -0
- package/dist/runtime/ruby-runner.d.ts +62 -0
- package/dist/runtime/ruby-runner.d.ts.map +1 -0
- package/dist/runtime/ruby-runner.js +737 -0
- package/dist/runtime/runtime-catalog.d.ts +99 -0
- package/dist/runtime/runtime-catalog.d.ts.map +1 -0
- package/dist/runtime/runtime-catalog.js +183 -0
- package/dist/runtime/runtime-registry.d.ts +136 -0
- package/dist/runtime/runtime-registry.d.ts.map +1 -0
- package/dist/runtime/runtime-registry.js +318 -0
- package/dist/runtime/streams.d.ts +13 -0
- package/dist/runtime/streams.d.ts.map +1 -0
- package/dist/runtime/streams.js +402 -0
- package/dist/runtime/wasi-instance.d.ts +190 -0
- package/dist/runtime/wasi-instance.d.ts.map +1 -0
- package/dist/runtime/wasi-instance.js +2044 -0
- package/dist/runtime/wasm-runner.d.ts +117 -0
- package/dist/runtime/wasm-runner.d.ts.map +1 -0
- package/dist/runtime/wasm-runner.js +705 -0
- package/dist/session/bindings.d.ts +168 -0
- package/dist/session/bindings.d.ts.map +1 -0
- package/dist/session/bindings.js +524 -0
- package/dist/session/ctx-exports.d.ts +16 -0
- package/dist/session/ctx-exports.d.ts.map +1 -0
- package/dist/session/ctx-exports.js +22 -0
- package/dist/session/diag.d.ts +62 -0
- package/dist/session/diag.d.ts.map +1 -0
- package/dist/session/diag.js +118 -0
- package/dist/session/fs-watch.d.ts +132 -0
- package/dist/session/fs-watch.d.ts.map +1 -0
- package/dist/session/fs-watch.js +255 -0
- package/dist/session/helpers.d.ts +150 -0
- package/dist/session/helpers.d.ts.map +1 -0
- package/dist/session/helpers.js +472 -0
- package/dist/session/hibernation.d.ts +145 -0
- package/dist/session/hibernation.d.ts.map +1 -0
- package/dist/session/hibernation.js +385 -0
- package/dist/session/init-phases.d.ts +87 -0
- package/dist/session/init-phases.d.ts.map +1 -0
- package/dist/session/init-phases.js +137 -0
- package/dist/session/init.d.ts +46 -0
- package/dist/session/init.d.ts.map +1 -0
- package/dist/session/init.js +3579 -0
- package/dist/session/keys.d.ts +56 -0
- package/dist/session/keys.d.ts.map +1 -0
- package/dist/session/keys.js +55 -0
- package/dist/session/nimbus-session.d.ts +434 -0
- package/dist/session/nimbus-session.d.ts.map +1 -0
- package/dist/session/nimbus-session.js +1084 -0
- package/dist/session/programmatic.d.ts +105 -0
- package/dist/session/programmatic.d.ts.map +1 -0
- package/dist/session/programmatic.js +326 -0
- package/dist/session/replica-routes.d.ts +68 -0
- package/dist/session/replica-routes.d.ts.map +1 -0
- package/dist/session/replica-routes.js +77 -0
- package/dist/session/routes.d.ts +29 -0
- package/dist/session/routes.d.ts.map +1 -0
- package/dist/session/routes.js +1331 -0
- package/dist/session/rpc.d.ts +323 -0
- package/dist/session/rpc.d.ts.map +1 -0
- package/dist/session/rpc.js +808 -0
- package/dist/session/state-store.d.ts +210 -0
- package/dist/session/state-store.d.ts.map +1 -0
- package/dist/session/state-store.js +459 -0
- package/dist/session/supervisor-rpc.d.ts +269 -0
- package/dist/session/supervisor-rpc.d.ts.map +1 -0
- package/dist/session/supervisor-rpc.js +437 -0
- package/dist/session/ws-hibernation-config.d.ts +64 -0
- package/dist/session/ws-hibernation-config.d.ts.map +1 -0
- package/dist/session/ws-hibernation-config.js +89 -0
- package/dist/session/ws.d.ts +95 -0
- package/dist/session/ws.d.ts.map +1 -0
- package/dist/session/ws.js +395 -0
- package/dist/shell/features.d.ts +410 -0
- package/dist/shell/features.d.ts.map +1 -0
- package/dist/shell/features.js +1885 -0
- package/dist/shell/unix-commands.d.ts +15 -0
- package/dist/shell/unix-commands.d.ts.map +1 -0
- package/dist/shell/unix-commands.js +3703 -0
- package/dist/stubs/lifo-ui.d.ts +10 -0
- package/dist/stubs/lifo-ui.d.ts.map +1 -0
- package/dist/stubs/lifo-ui.js +1 -0
- package/dist/tailwind-play.generated.d.ts +19 -0
- package/dist/tailwind-play.generated.d.ts.map +1 -0
- package/dist/tailwind-play.generated.js +18 -0
- package/dist/vfs/dev-provider.d.ts +64 -0
- package/dist/vfs/dev-provider.d.ts.map +1 -0
- package/dist/vfs/dev-provider.js +191 -0
- package/dist/vfs/events.d.ts +51 -0
- package/dist/vfs/events.d.ts.map +1 -0
- package/dist/vfs/events.js +127 -0
- package/dist/vfs/path.d.ts +30 -0
- package/dist/vfs/path.d.ts.map +1 -0
- package/dist/vfs/path.js +41 -0
- package/dist/vfs/seed-project.d.ts +62 -0
- package/dist/vfs/seed-project.d.ts.map +1 -0
- package/dist/vfs/seed-project.js +1045 -0
- package/dist/vfs/sqlite-vfs.d.ts +435 -0
- package/dist/vfs/sqlite-vfs.d.ts.map +1 -0
- package/dist/vfs/sqlite-vfs.js +1670 -0
- package/dist/vfs/symlink-registry.d.ts +64 -0
- package/dist/vfs/symlink-registry.d.ts.map +1 -0
- package/dist/vfs/symlink-registry.js +137 -0
- package/dist/wrangler/nimbus-wrangler.d.ts +157 -0
- package/dist/wrangler/nimbus-wrangler.d.ts.map +1 -0
- package/dist/wrangler/nimbus-wrangler.js +931 -0
- package/package.json +77 -0
- package/public/_assets/cirrus-plugin-react.bundle.js +70740 -0
- package/public/_assets/esbuild-0.24.2.wasm +0 -0
- package/public/_assets/real-vite-bundle.js +101478 -0
- package/public/_assets/rollup.wasm +0 -0
- package/public/favicon.svg +8 -0
- package/public/index.html +565 -0
- package/public/s/index.html +2379 -0
- package/scripts/bundle-esbuild-wasm.mjs +244 -0
- package/scripts/bundle-facet-workers.mjs +137 -0
- package/scripts/bundle-git.mjs +118 -0
- package/scripts/bundle-npm-cjs.mjs +363 -0
- package/scripts/bundle-plugin-react.mjs +480 -0
- package/scripts/bundle-real-vite.mjs +959 -0
- package/scripts/bundle-runtime.mjs +600 -0
- package/scripts/bundle-tailwind-play.mjs +130 -0
- package/scripts/patch-lifo-ui.mjs +131 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* real-vite-hmr.ts — Phase 2 HMR bridge for the real-vite facet.
|
|
3
|
+
*
|
|
4
|
+
* The browser's `@vite/client` script (served as-is by Vite) opens a
|
|
5
|
+
* WebSocket to Vite's HMR path. In local dev that's a raw TCP socket;
|
|
6
|
+
* under workerd we don't have one, so we:
|
|
7
|
+
*
|
|
8
|
+
* 1. Route the browser's upgrade request to a new DO endpoint
|
|
9
|
+
* `/s/<id>/preview/__nimbus_hmr` (picked as an unusual path that
|
|
10
|
+
* won't collide with user code). The DO accepts the WebSocket.
|
|
11
|
+
* 2. On the facet side, we shim `ws.WebSocketServer` — the npm
|
|
12
|
+
* module Vite bundles for HMR. The shim registers itself in a
|
|
13
|
+
* facet-local "pending connections" table; when a connection
|
|
14
|
+
* arrives via RPC, the shim delivers an "on('connection')" event
|
|
15
|
+
* to Vite.
|
|
16
|
+
* 3. Messages from Vite (server → client, e.g. HMR update) are
|
|
17
|
+
* pushed back to the supervisor via `SUPERVISOR.hmrSend(clientId,
|
|
18
|
+
* msg)`, which the supervisor forwards to the right WebSocket.
|
|
19
|
+
* 4. Messages from the browser (client → server, e.g. ping/pong,
|
|
20
|
+
* custom events) are ferried via a long-poll
|
|
21
|
+
* `SUPERVISOR.hmrNextEvent(serverId)` that returns the queued
|
|
22
|
+
* batch.
|
|
23
|
+
*
|
|
24
|
+
* Phase 1's VFS-backed fs shim is the prerequisite: chokidar's watch
|
|
25
|
+
* events drive Vite's HMR, so we need real file change notifications
|
|
26
|
+
* plumbed to the facet. Those come via the SAME long-poll loop as
|
|
27
|
+
* client-side WS messages — both are just "events from the
|
|
28
|
+
* supervisor", multiplexed.
|
|
29
|
+
*
|
|
30
|
+
* Scope note: Phase 2 implements the minimum viable path —
|
|
31
|
+
* connection + server→client messages — enough for the
|
|
32
|
+
* "[vite] connected" handshake + full-reload triggers on file save.
|
|
33
|
+
* True module-level `import.meta.hot.accept()` needs chokidar events
|
|
34
|
+
* to fire Vite's `moduleGraph.invalidate`; wire that up once Phase 1's
|
|
35
|
+
* fs shim is streaming VFS events.
|
|
36
|
+
*/
|
|
37
|
+
import { WorkerEntrypoint } from 'cloudflare:workers';
|
|
38
|
+
/**
|
|
39
|
+
* Supervisor-side registry of active HMR connections for a single
|
|
40
|
+
* real-vite session. One instance lives on each NimbusSession that has
|
|
41
|
+
* real-vite running. The instance is bound to a specific facet via
|
|
42
|
+
* its `facetStub` (a ctx.exports wrapper around the facet's
|
|
43
|
+
* WorkerEntrypoint).
|
|
44
|
+
*
|
|
45
|
+
* Lifecycle:
|
|
46
|
+
* - On browser WS upgrade (/preview/__nimbus_hmr), the DO calls
|
|
47
|
+
* bridge.attachClient(ws) → HMR connection id is generated, ws
|
|
48
|
+
* is stored, and a one-shot RPC to the facet tells it "new
|
|
49
|
+
* connection".
|
|
50
|
+
* - The facet's ws shim emits a 'connection' event to Vite. Vite
|
|
51
|
+
* starts sending handshake messages via the shim's .send() →
|
|
52
|
+
* those come back to the supervisor via SUPERVISOR.hmrSend →
|
|
53
|
+
* HmrBridge.relayToBrowser(clientId, msg).
|
|
54
|
+
* - Browser WS messages arrive at the DO's webSocketMessage
|
|
55
|
+
* handler, which calls bridge.deliverClientMessage(clientId, msg)
|
|
56
|
+
* → enqueued for the next hmrNextEvent long-poll.
|
|
57
|
+
* - Same long-poll returns VFS change events so chokidar can fire.
|
|
58
|
+
*/
|
|
59
|
+
export declare class HmrBridge {
|
|
60
|
+
/** clientId → WebSocket */
|
|
61
|
+
private clients;
|
|
62
|
+
/** Pending events awaiting the next long-poll. */
|
|
63
|
+
private pending;
|
|
64
|
+
/** Resolver for the currently-suspended long-poll, if any. */
|
|
65
|
+
private resolver;
|
|
66
|
+
/** Has the facet ever called hmrNextEvent? Used for diagnostics. */
|
|
67
|
+
_everAwaitedEvents: boolean;
|
|
68
|
+
private _nextId;
|
|
69
|
+
/** Register a new browser WebSocket. Returns the assigned client id. */
|
|
70
|
+
attachClient(ws: WebSocket): string;
|
|
71
|
+
detachClient(id: string): void;
|
|
72
|
+
/** Called by the DO webSocketMessage handler. Forwards to the facet. */
|
|
73
|
+
deliverClientMessage(id: string, msg: string): void;
|
|
74
|
+
/** Called by the facet via SUPERVISOR.hmrSend to push a msg to a browser. */
|
|
75
|
+
relayToBrowser(id: string | null, msg: string): void;
|
|
76
|
+
/**
|
|
77
|
+
* Push a synthetic VFS event into the event queue. Called by
|
|
78
|
+
* NimbusSession's VFS-events listener so the facet's chokidar shim
|
|
79
|
+
* fires file-change callbacks.
|
|
80
|
+
*/
|
|
81
|
+
pushVfsEvent(event: string, path: string, oldPath?: string): void;
|
|
82
|
+
private push;
|
|
83
|
+
/**
|
|
84
|
+
* Called by the facet via SUPERVISOR.hmrNextEvent. Long-polls up to
|
|
85
|
+
* `timeoutMs` for the next batch of events. Returns an empty array
|
|
86
|
+
* on timeout so the facet can loop without leaking a promise.
|
|
87
|
+
*/
|
|
88
|
+
nextEvents(timeoutMs?: number): Promise<any[]>;
|
|
89
|
+
/** Active client count. */
|
|
90
|
+
get size(): number;
|
|
91
|
+
/** Drop all clients (facet restart, session close). */
|
|
92
|
+
closeAll(): void;
|
|
93
|
+
}
|
|
94
|
+
export declare function registerHmrBridge(doId: string, holder: {
|
|
95
|
+
hmr: HmrBridge;
|
|
96
|
+
}): void;
|
|
97
|
+
/**
|
|
98
|
+
* WorkerEntrypoint the facet talks to via `env.CIRRUS_HMR`.
|
|
99
|
+
*
|
|
100
|
+
* hmrSend CANNOT write to browser WSs directly (workerd forbids
|
|
101
|
+
* cross-request I/O on objects owned by a different request's
|
|
102
|
+
* context — even hibernatable WSs owned by the DO can't be written
|
|
103
|
+
* to from a sibling WorkerEntrypoint isolate). Instead, hmrSend
|
|
104
|
+
* routes through the DO stub's _rpcHmrRelay method, where the
|
|
105
|
+
* ws.send() happens in the DO's own request context.
|
|
106
|
+
*
|
|
107
|
+
* Props: { doId: string }
|
|
108
|
+
* doId — the supervisor DO's id, used to find the right stub +
|
|
109
|
+
* HmrBridge.
|
|
110
|
+
*/
|
|
111
|
+
export declare class CirrusHmrRPC extends WorkerEntrypoint {
|
|
112
|
+
private _bridge;
|
|
113
|
+
private _stub;
|
|
114
|
+
hmrSend(clientId: string | null, msg: string): Promise<void>;
|
|
115
|
+
hmrNextEvent(timeoutMs?: number): Promise<any[]>;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* ESM source for the `ws` npm module shim. Vite's bundle still
|
|
119
|
+
* statically imports things like `WebSocketServer` from `ws`; we
|
|
120
|
+
* externalize that specifier and provide this module at LOADER.load
|
|
121
|
+
* time.
|
|
122
|
+
*
|
|
123
|
+
* `new WebSocketServer({ noServer: true })` gives Vite back an object
|
|
124
|
+
* that:
|
|
125
|
+
* - emits 'connection' events whenever the supervisor reports a
|
|
126
|
+
* new client via the long-poll,
|
|
127
|
+
* - exposes .handleUpgrade (stubbed since we don't have raw sockets).
|
|
128
|
+
*
|
|
129
|
+
* The returned client has `.on('message', cb)`, `.send(msg)`, `.close()`
|
|
130
|
+
* — enough for Vite's hot.ts handshake.
|
|
131
|
+
*/
|
|
132
|
+
export declare function generateWsShimModuleCode(): string;
|
|
133
|
+
/**
|
|
134
|
+
* ESM source for the chokidar shim. Vite's bundle imports chokidar's
|
|
135
|
+
* `watch()` function; we reroute that to this module. Our watcher
|
|
136
|
+
* listens on the facet-global event dispatcher (fed by the long-poll
|
|
137
|
+
* loop) and translates VFS events to chokidar-shaped callbacks.
|
|
138
|
+
*
|
|
139
|
+
* Supported events: add, change, unlink, addDir, unlinkDir, ready, all.
|
|
140
|
+
*/
|
|
141
|
+
export declare function generateChokidarShimModuleCode(): string;
|
|
142
|
+
//# sourceMappingURL=real-vite-hmr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"real-vite-hmr.d.ts","sourceRoot":"","sources":["../../src/facets/real-vite-hmr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AASH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAatD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,SAAS;IACpB,2BAA2B;IAC3B,OAAO,CAAC,OAAO,CAAgC;IAC/C,kDAAkD;IAClD,OAAO,CAAC,OAAO,CAAiH;IAChI,8DAA8D;IAC9D,OAAO,CAAC,QAAQ,CAA0C;IAC1D,oEAAoE;IAC7D,kBAAkB,UAAS;IAClC,OAAO,CAAC,OAAO,CAAK;IAEpB,wEAAwE;IACxE,YAAY,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM;IAOnC,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAK9B,wEAAwE;IACxE,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAInD,6EAA6E;IAC7E,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAapD;;;;OAIG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAIjE,OAAO,CAAC,IAAI;IAWZ;;;;OAIG;IACG,UAAU,CAAC,SAAS,GAAE,MAAe,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAkB5D,2BAA2B;IAC3B,IAAI,IAAI,IAAI,MAAM,CAA8B;IAEhD,uDAAuD;IACvD,QAAQ,IAAI,IAAI;CAYjB;AAUD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE;IAAE,GAAG,EAAE,SAAS,CAAA;CAAE,GAAG,IAAI,CAEhF;AAKD;;;;;;;;;;;;;GAaG;AACH,qBAAa,YAAa,SAAQ,gBAAgB;IAChD,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,KAAK;IAOP,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ5D,YAAY,CAAC,SAAS,GAAE,MAAe,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;CAO/D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CA2HjD;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,IAAI,MAAM,CA0EvD"}
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* real-vite-hmr.ts — Phase 2 HMR bridge for the real-vite facet.
|
|
3
|
+
*
|
|
4
|
+
* The browser's `@vite/client` script (served as-is by Vite) opens a
|
|
5
|
+
* WebSocket to Vite's HMR path. In local dev that's a raw TCP socket;
|
|
6
|
+
* under workerd we don't have one, so we:
|
|
7
|
+
*
|
|
8
|
+
* 1. Route the browser's upgrade request to a new DO endpoint
|
|
9
|
+
* `/s/<id>/preview/__nimbus_hmr` (picked as an unusual path that
|
|
10
|
+
* won't collide with user code). The DO accepts the WebSocket.
|
|
11
|
+
* 2. On the facet side, we shim `ws.WebSocketServer` — the npm
|
|
12
|
+
* module Vite bundles for HMR. The shim registers itself in a
|
|
13
|
+
* facet-local "pending connections" table; when a connection
|
|
14
|
+
* arrives via RPC, the shim delivers an "on('connection')" event
|
|
15
|
+
* to Vite.
|
|
16
|
+
* 3. Messages from Vite (server → client, e.g. HMR update) are
|
|
17
|
+
* pushed back to the supervisor via `SUPERVISOR.hmrSend(clientId,
|
|
18
|
+
* msg)`, which the supervisor forwards to the right WebSocket.
|
|
19
|
+
* 4. Messages from the browser (client → server, e.g. ping/pong,
|
|
20
|
+
* custom events) are ferried via a long-poll
|
|
21
|
+
* `SUPERVISOR.hmrNextEvent(serverId)` that returns the queued
|
|
22
|
+
* batch.
|
|
23
|
+
*
|
|
24
|
+
* Phase 1's VFS-backed fs shim is the prerequisite: chokidar's watch
|
|
25
|
+
* events drive Vite's HMR, so we need real file change notifications
|
|
26
|
+
* plumbed to the facet. Those come via the SAME long-poll loop as
|
|
27
|
+
* client-side WS messages — both are just "events from the
|
|
28
|
+
* supervisor", multiplexed.
|
|
29
|
+
*
|
|
30
|
+
* Scope note: Phase 2 implements the minimum viable path —
|
|
31
|
+
* connection + server→client messages — enough for the
|
|
32
|
+
* "[vite] connected" handshake + full-reload triggers on file save.
|
|
33
|
+
* True module-level `import.meta.hot.accept()` needs chokidar events
|
|
34
|
+
* to fire Vite's `moduleGraph.invalidate`; wire that up once Phase 1's
|
|
35
|
+
* fs shim is streaming VFS events.
|
|
36
|
+
*/
|
|
37
|
+
// This file is pure source; at runtime it contributes:
|
|
38
|
+
// 1. Supervisor-side: HmrBridge class (connection registry + WS pump).
|
|
39
|
+
// 2. Supervisor-side: CirrusHmrRPC WorkerEntrypoint class (the RPC
|
|
40
|
+
// service the facet talks to for hmrSend/hmrNextEvent).
|
|
41
|
+
// 3. Facet-side: ESM source strings for the ws shim + chokidar shim.
|
|
42
|
+
// All are emitted by the generators below.
|
|
43
|
+
import { WorkerEntrypoint } from 'cloudflare:workers';
|
|
44
|
+
// CLN-3 (2026-05-11): supervisor-side debug gate. Mirrors the facet-side
|
|
45
|
+
// `globalThis.__cirrusDebug` flag declared at cirrus-real.ts:160. When
|
|
46
|
+
// `false` (default), the hot-path console.log calls in `HmrBridge`
|
|
47
|
+
// (every HMR message relay, every WS accept) are suppressed. Diagnostic
|
|
48
|
+
// users mutate at runtime (e.g. via wrangler tail's REPL) to re-enable.
|
|
49
|
+
//
|
|
50
|
+
// The two isolates (supervisor vs facet) each have their own globalThis;
|
|
51
|
+
// the flag must be set independently in each. Reading `undefined` here
|
|
52
|
+
// is fine — it's falsy, so the gate fires (no log) by default.
|
|
53
|
+
globalThis.__cirrusDebug ??= false;
|
|
54
|
+
/**
|
|
55
|
+
* Supervisor-side registry of active HMR connections for a single
|
|
56
|
+
* real-vite session. One instance lives on each NimbusSession that has
|
|
57
|
+
* real-vite running. The instance is bound to a specific facet via
|
|
58
|
+
* its `facetStub` (a ctx.exports wrapper around the facet's
|
|
59
|
+
* WorkerEntrypoint).
|
|
60
|
+
*
|
|
61
|
+
* Lifecycle:
|
|
62
|
+
* - On browser WS upgrade (/preview/__nimbus_hmr), the DO calls
|
|
63
|
+
* bridge.attachClient(ws) → HMR connection id is generated, ws
|
|
64
|
+
* is stored, and a one-shot RPC to the facet tells it "new
|
|
65
|
+
* connection".
|
|
66
|
+
* - The facet's ws shim emits a 'connection' event to Vite. Vite
|
|
67
|
+
* starts sending handshake messages via the shim's .send() →
|
|
68
|
+
* those come back to the supervisor via SUPERVISOR.hmrSend →
|
|
69
|
+
* HmrBridge.relayToBrowser(clientId, msg).
|
|
70
|
+
* - Browser WS messages arrive at the DO's webSocketMessage
|
|
71
|
+
* handler, which calls bridge.deliverClientMessage(clientId, msg)
|
|
72
|
+
* → enqueued for the next hmrNextEvent long-poll.
|
|
73
|
+
* - Same long-poll returns VFS change events so chokidar can fire.
|
|
74
|
+
*/
|
|
75
|
+
export class HmrBridge {
|
|
76
|
+
/** clientId → WebSocket */
|
|
77
|
+
clients = new Map();
|
|
78
|
+
/** Pending events awaiting the next long-poll. */
|
|
79
|
+
pending = [];
|
|
80
|
+
/** Resolver for the currently-suspended long-poll, if any. */
|
|
81
|
+
resolver = null;
|
|
82
|
+
/** Has the facet ever called hmrNextEvent? Used for diagnostics. */
|
|
83
|
+
_everAwaitedEvents = false;
|
|
84
|
+
_nextId = 1;
|
|
85
|
+
/** Register a new browser WebSocket. Returns the assigned client id. */
|
|
86
|
+
attachClient(ws) {
|
|
87
|
+
const id = 'c' + (this._nextId++);
|
|
88
|
+
this.clients.set(id, ws);
|
|
89
|
+
this.push({ type: 'connection', clientId: id });
|
|
90
|
+
return id;
|
|
91
|
+
}
|
|
92
|
+
detachClient(id) {
|
|
93
|
+
this.clients.delete(id);
|
|
94
|
+
this.push({ type: 'disconnect', clientId: id });
|
|
95
|
+
}
|
|
96
|
+
/** Called by the DO webSocketMessage handler. Forwards to the facet. */
|
|
97
|
+
deliverClientMessage(id, msg) {
|
|
98
|
+
this.push({ type: 'message', clientId: id, msg });
|
|
99
|
+
}
|
|
100
|
+
/** Called by the facet via SUPERVISOR.hmrSend to push a msg to a browser. */
|
|
101
|
+
relayToBrowser(id, msg) {
|
|
102
|
+
if (globalThis.__cirrusDebug)
|
|
103
|
+
console.log('[HmrBridge relay] id=', id, 'msg len=', msg?.length, 'clients=', this.clients.size);
|
|
104
|
+
if (id == null) {
|
|
105
|
+
for (const ws of this.clients.values()) {
|
|
106
|
+
try {
|
|
107
|
+
ws.send(msg);
|
|
108
|
+
}
|
|
109
|
+
catch { /* client gone */ }
|
|
110
|
+
}
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const ws = this.clients.get(id);
|
|
114
|
+
if (!ws) {
|
|
115
|
+
if (globalThis.__cirrusDebug)
|
|
116
|
+
console.log('[HmrBridge relay] no WS for id', id);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
ws.send(msg);
|
|
121
|
+
if (globalThis.__cirrusDebug)
|
|
122
|
+
console.log('[HmrBridge relay] sent ok');
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
if (globalThis.__cirrusDebug)
|
|
126
|
+
console.log('[HmrBridge relay] send threw:', e?.message);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Push a synthetic VFS event into the event queue. Called by
|
|
131
|
+
* NimbusSession's VFS-events listener so the facet's chokidar shim
|
|
132
|
+
* fires file-change callbacks.
|
|
133
|
+
*/
|
|
134
|
+
pushVfsEvent(event, path, oldPath) {
|
|
135
|
+
this.push({ type: 'vfs', event, path, oldPath });
|
|
136
|
+
}
|
|
137
|
+
push(ev) {
|
|
138
|
+
this.pending.push(ev);
|
|
139
|
+
if (this.resolver) {
|
|
140
|
+
const r = this.resolver;
|
|
141
|
+
this.resolver = null;
|
|
142
|
+
const batch = this.pending;
|
|
143
|
+
this.pending = [];
|
|
144
|
+
try {
|
|
145
|
+
r(batch);
|
|
146
|
+
}
|
|
147
|
+
catch { /* dropped */ }
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Called by the facet via SUPERVISOR.hmrNextEvent. Long-polls up to
|
|
152
|
+
* `timeoutMs` for the next batch of events. Returns an empty array
|
|
153
|
+
* on timeout so the facet can loop without leaking a promise.
|
|
154
|
+
*/
|
|
155
|
+
async nextEvents(timeoutMs = 25_000) {
|
|
156
|
+
this._everAwaitedEvents = true;
|
|
157
|
+
if (this.pending.length > 0) {
|
|
158
|
+
const batch = this.pending;
|
|
159
|
+
this.pending = [];
|
|
160
|
+
return batch;
|
|
161
|
+
}
|
|
162
|
+
return new Promise((resolve) => {
|
|
163
|
+
this.resolver = resolve;
|
|
164
|
+
setTimeout(() => {
|
|
165
|
+
if (this.resolver === resolve) {
|
|
166
|
+
this.resolver = null;
|
|
167
|
+
resolve([]);
|
|
168
|
+
}
|
|
169
|
+
}, timeoutMs);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/** Active client count. */
|
|
173
|
+
get size() { return this.clients.size; }
|
|
174
|
+
/** Drop all clients (facet restart, session close). */
|
|
175
|
+
closeAll() {
|
|
176
|
+
for (const ws of this.clients.values()) {
|
|
177
|
+
try {
|
|
178
|
+
ws.close(1001, 'facet restart');
|
|
179
|
+
}
|
|
180
|
+
catch { /* ignore */ }
|
|
181
|
+
}
|
|
182
|
+
this.clients.clear();
|
|
183
|
+
if (this.resolver) {
|
|
184
|
+
const r = this.resolver;
|
|
185
|
+
this.resolver = null;
|
|
186
|
+
try {
|
|
187
|
+
r([]);
|
|
188
|
+
}
|
|
189
|
+
catch { /* ignore */ }
|
|
190
|
+
}
|
|
191
|
+
this.pending = [];
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Registry mapping `doId` → `CirrusReal` instance. Populated when
|
|
196
|
+
* NimbusSession creates a CirrusReal. The facet-side RPC looks up the
|
|
197
|
+
* right HmrBridge via this registry — otherwise CirrusHmrRPC.fetch
|
|
198
|
+
* can't know WHICH session called it.
|
|
199
|
+
*/
|
|
200
|
+
const _BRIDGES = new Map();
|
|
201
|
+
export function registerHmrBridge(doId, holder) {
|
|
202
|
+
_BRIDGES.set(doId, holder);
|
|
203
|
+
}
|
|
204
|
+
// unregisterHmrBridge intentionally not exposed — the registry is GC'd
|
|
205
|
+
// when the supervisor DO is evicted, and the cirrus-real comment at the
|
|
206
|
+
// stop() site explains why we don't unregister mid-life.
|
|
207
|
+
/**
|
|
208
|
+
* WorkerEntrypoint the facet talks to via `env.CIRRUS_HMR`.
|
|
209
|
+
*
|
|
210
|
+
* hmrSend CANNOT write to browser WSs directly (workerd forbids
|
|
211
|
+
* cross-request I/O on objects owned by a different request's
|
|
212
|
+
* context — even hibernatable WSs owned by the DO can't be written
|
|
213
|
+
* to from a sibling WorkerEntrypoint isolate). Instead, hmrSend
|
|
214
|
+
* routes through the DO stub's _rpcHmrRelay method, where the
|
|
215
|
+
* ws.send() happens in the DO's own request context.
|
|
216
|
+
*
|
|
217
|
+
* Props: { doId: string }
|
|
218
|
+
* doId — the supervisor DO's id, used to find the right stub +
|
|
219
|
+
* HmrBridge.
|
|
220
|
+
*/
|
|
221
|
+
export class CirrusHmrRPC extends WorkerEntrypoint {
|
|
222
|
+
_bridge() {
|
|
223
|
+
const doId = this.ctx.props?.doId;
|
|
224
|
+
if (!doId)
|
|
225
|
+
return null;
|
|
226
|
+
return _BRIDGES.get(doId)?.hmr || null;
|
|
227
|
+
}
|
|
228
|
+
_stub() {
|
|
229
|
+
const doId = this.ctx.props?.doId;
|
|
230
|
+
if (!doId)
|
|
231
|
+
return null;
|
|
232
|
+
const id = this.env.NIMBUS_SESSION.idFromString(doId);
|
|
233
|
+
return this.env.NIMBUS_SESSION.get(id);
|
|
234
|
+
}
|
|
235
|
+
async hmrSend(clientId, msg) {
|
|
236
|
+
const stub = this._stub();
|
|
237
|
+
if (!stub)
|
|
238
|
+
return;
|
|
239
|
+
// Call the DO's own RPC method, which runs in the DO's context
|
|
240
|
+
// and can legally call ws.send() on hibernatable sockets.
|
|
241
|
+
try {
|
|
242
|
+
await stub._rpcHmrRelay(clientId, msg);
|
|
243
|
+
}
|
|
244
|
+
catch { /* socket gone */ }
|
|
245
|
+
}
|
|
246
|
+
async hmrNextEvent(timeoutMs = 25_000) {
|
|
247
|
+
// Long-poll can stay on the WorkerEntrypoint side — nextEvents
|
|
248
|
+
// only awaits in-memory timers/queues, no WS I/O.
|
|
249
|
+
const b = this._bridge();
|
|
250
|
+
if (!b)
|
|
251
|
+
return [];
|
|
252
|
+
return b.nextEvents(Math.min(30_000, Math.max(1_000, timeoutMs)));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* ESM source for the `ws` npm module shim. Vite's bundle still
|
|
257
|
+
* statically imports things like `WebSocketServer` from `ws`; we
|
|
258
|
+
* externalize that specifier and provide this module at LOADER.load
|
|
259
|
+
* time.
|
|
260
|
+
*
|
|
261
|
+
* `new WebSocketServer({ noServer: true })` gives Vite back an object
|
|
262
|
+
* that:
|
|
263
|
+
* - emits 'connection' events whenever the supervisor reports a
|
|
264
|
+
* new client via the long-poll,
|
|
265
|
+
* - exposes .handleUpgrade (stubbed since we don't have raw sockets).
|
|
266
|
+
*
|
|
267
|
+
* The returned client has `.on('message', cb)`, `.send(msg)`, `.close()`
|
|
268
|
+
* — enough for Vite's hot.ts handshake.
|
|
269
|
+
*/
|
|
270
|
+
export function generateWsShimModuleCode() {
|
|
271
|
+
return `
|
|
272
|
+
// ── ws shim (generated by src/real-vite-hmr.ts) ────────────────
|
|
273
|
+
//
|
|
274
|
+
// Vite imports { WebSocketServer, WebSocket } from 'ws'. We route
|
|
275
|
+
// those imports to this module (via esbuild alias), so the facet
|
|
276
|
+
// never tries to bind a real socket. All connections are multiplexed
|
|
277
|
+
// through the single DO-side /__nimbus_hmr WS and delivered here as
|
|
278
|
+
// events from the long-poll loop.
|
|
279
|
+
|
|
280
|
+
const _g = globalThis;
|
|
281
|
+
|
|
282
|
+
// Self-seed the global bindings at module-eval time. Our post-patched
|
|
283
|
+
// vite.bundle.js looks up globalThis.__cirrusWsModule synchronously
|
|
284
|
+
// at module-init (inside \`var WebSocketServerRaw = ...\`), so this
|
|
285
|
+
// assignment MUST win the race. ESM evaluates imports depth-first in
|
|
286
|
+
// source order, so as long as main.js imports this module before
|
|
287
|
+
// vite.bundle.js, we're ahead.
|
|
288
|
+
|
|
289
|
+
class CirrusWsClient {
|
|
290
|
+
constructor(id) {
|
|
291
|
+
this.id = id;
|
|
292
|
+
this._listeners = { message: [], close: [], error: [], pong: [], ping: [] };
|
|
293
|
+
this.readyState = 1; // OPEN
|
|
294
|
+
}
|
|
295
|
+
on(ev, cb) {
|
|
296
|
+
if (this._listeners[ev]) this._listeners[ev].push(cb);
|
|
297
|
+
return this;
|
|
298
|
+
}
|
|
299
|
+
off(ev, cb) {
|
|
300
|
+
if (this._listeners[ev]) {
|
|
301
|
+
const i = this._listeners[ev].indexOf(cb);
|
|
302
|
+
if (i >= 0) this._listeners[ev].splice(i, 1);
|
|
303
|
+
}
|
|
304
|
+
return this;
|
|
305
|
+
}
|
|
306
|
+
emit(ev, ...args) {
|
|
307
|
+
if (this._listeners[ev]) for (const l of this._listeners[ev].slice()) { try { l(...args); } catch (e) { console.warn('[cirrus-ws] listener threw:', e?.message); } }
|
|
308
|
+
}
|
|
309
|
+
send(data, cb) {
|
|
310
|
+
const hmr = _g.__cirrusRealHmr;
|
|
311
|
+
if (hmr?.hmrSend) {
|
|
312
|
+
const msg = typeof data === 'string' ? data : data?.toString?.() || '';
|
|
313
|
+
hmr.hmrSend(this.id, msg).then(() => cb?.(), (e) => cb?.(e));
|
|
314
|
+
} else {
|
|
315
|
+
cb?.();
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
close(code, reason) {
|
|
319
|
+
this.readyState = 3;
|
|
320
|
+
this.emit('close', code || 1000, reason || '');
|
|
321
|
+
}
|
|
322
|
+
terminate() { this.close(1006, 'terminate'); }
|
|
323
|
+
ping() { /* no-op; Vite does this keep-alive */ }
|
|
324
|
+
pong() { /* no-op */ }
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
class CirrusWsServer {
|
|
328
|
+
constructor(opts) {
|
|
329
|
+
this.options = opts || {};
|
|
330
|
+
this._listeners = { connection: [], error: [], listening: [], close: [], headers: [] };
|
|
331
|
+
this.clients = new Set();
|
|
332
|
+
_g.__cirrusRealWsServer = this; // allow the boot loop to find us
|
|
333
|
+
// Tell the event loop we're ready. Some Vite codepaths emit
|
|
334
|
+
// 'listening' themselves; doing it here is harmless.
|
|
335
|
+
queueMicrotask(() => this.emit('listening'));
|
|
336
|
+
}
|
|
337
|
+
on(ev, cb) {
|
|
338
|
+
if (this._listeners[ev]) this._listeners[ev].push(cb);
|
|
339
|
+
return this;
|
|
340
|
+
}
|
|
341
|
+
off(ev, cb) {
|
|
342
|
+
if (this._listeners[ev]) {
|
|
343
|
+
const i = this._listeners[ev].indexOf(cb);
|
|
344
|
+
if (i >= 0) this._listeners[ev].splice(i, 1);
|
|
345
|
+
}
|
|
346
|
+
return this;
|
|
347
|
+
}
|
|
348
|
+
emit(ev, ...args) {
|
|
349
|
+
if (this._listeners[ev]) for (const l of this._listeners[ev].slice()) { try { l(...args); } catch (e) { console.warn('[cirrus-ws] listener threw:', e?.message); } }
|
|
350
|
+
}
|
|
351
|
+
/** Called by the HMR loop when a new connection shows up. */
|
|
352
|
+
_acceptConnection(id) {
|
|
353
|
+
const client = new CirrusWsClient(id);
|
|
354
|
+
this.clients.add(client);
|
|
355
|
+
_g.__cirrusRealWsClients ??= new Map();
|
|
356
|
+
_g.__cirrusRealWsClients.set(id, client);
|
|
357
|
+
if (globalThis.__cirrusDebug) console.log('[cirrus-ws] _acceptConnection id=' + id + ' listeners=' + (this._listeners.connection?.length || 0));
|
|
358
|
+
this.emit('connection', client, { url: '/', headers: {} });
|
|
359
|
+
return client;
|
|
360
|
+
}
|
|
361
|
+
_dispatchMessage(id, msg) {
|
|
362
|
+
const client = _g.__cirrusRealWsClients?.get(id);
|
|
363
|
+
if (client) client.emit('message', msg);
|
|
364
|
+
}
|
|
365
|
+
_disconnect(id) {
|
|
366
|
+
const client = _g.__cirrusRealWsClients?.get(id);
|
|
367
|
+
if (client) {
|
|
368
|
+
client.close(1001, 'client gone');
|
|
369
|
+
this.clients.delete(client);
|
|
370
|
+
_g.__cirrusRealWsClients.delete(id);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
handleUpgrade(req, sock, head, cb) {
|
|
374
|
+
// Never called in our flow, but Vite references it defensively.
|
|
375
|
+
if (typeof cb === 'function') cb(new CirrusWsClient('<stub>'));
|
|
376
|
+
}
|
|
377
|
+
close(cb) {
|
|
378
|
+
for (const c of this.clients) c.close(1001, 'server closing');
|
|
379
|
+
this.clients.clear();
|
|
380
|
+
cb?.();
|
|
381
|
+
}
|
|
382
|
+
shouldHandle() { return true; }
|
|
383
|
+
get clients() { return this._clients ??= new Set(); }
|
|
384
|
+
set clients(v) { this._clients = v; }
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export const WebSocketServer = CirrusWsServer;
|
|
388
|
+
export const WebSocket = CirrusWsClient;
|
|
389
|
+
const _exports = { WebSocketServer: CirrusWsServer, WebSocket: CirrusWsClient };
|
|
390
|
+
_g.__cirrusWsModule = _exports;
|
|
391
|
+
export default _exports;
|
|
392
|
+
`.trim();
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* ESM source for the chokidar shim. Vite's bundle imports chokidar's
|
|
396
|
+
* `watch()` function; we reroute that to this module. Our watcher
|
|
397
|
+
* listens on the facet-global event dispatcher (fed by the long-poll
|
|
398
|
+
* loop) and translates VFS events to chokidar-shaped callbacks.
|
|
399
|
+
*
|
|
400
|
+
* Supported events: add, change, unlink, addDir, unlinkDir, ready, all.
|
|
401
|
+
*/
|
|
402
|
+
export function generateChokidarShimModuleCode() {
|
|
403
|
+
return `
|
|
404
|
+
// ── chokidar shim (generated by src/real-vite-hmr.ts) ───────────
|
|
405
|
+
const _g = globalThis;
|
|
406
|
+
|
|
407
|
+
class CirrusWatcher {
|
|
408
|
+
constructor(paths, opts) {
|
|
409
|
+
this.paths = Array.isArray(paths) ? paths : [paths];
|
|
410
|
+
this.opts = opts || {};
|
|
411
|
+
this._listeners = { add: [], change: [], unlink: [], addDir: [], unlinkDir: [], ready: [], all: [], error: [], raw: [] };
|
|
412
|
+
this._watched = new Map();
|
|
413
|
+
this._closed = false;
|
|
414
|
+
_g.__cirrusRealWatchers ??= new Set();
|
|
415
|
+
_g.__cirrusRealWatchers.add(this);
|
|
416
|
+
queueMicrotask(() => { if (!this._closed) this.emit('ready'); });
|
|
417
|
+
}
|
|
418
|
+
on(ev, cb) {
|
|
419
|
+
if (this._listeners[ev]) this._listeners[ev].push(cb);
|
|
420
|
+
return this;
|
|
421
|
+
}
|
|
422
|
+
off(ev, cb) {
|
|
423
|
+
if (this._listeners[ev]) {
|
|
424
|
+
const i = this._listeners[ev].indexOf(cb);
|
|
425
|
+
if (i >= 0) this._listeners[ev].splice(i, 1);
|
|
426
|
+
}
|
|
427
|
+
return this;
|
|
428
|
+
}
|
|
429
|
+
emit(ev, ...args) {
|
|
430
|
+
if (this._listeners[ev]) for (const l of this._listeners[ev].slice()) { try { l(...args); } catch (e) { console.warn('[cirrus-chokidar] listener threw:', e?.message); } }
|
|
431
|
+
if (ev !== 'all' && ev !== 'error' && ev !== 'raw' && this._listeners.all) {
|
|
432
|
+
for (const l of this._listeners.all.slice()) { try { l(ev, ...args); } catch {} }
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
/** Called by the HMR loop with a VFS event. */
|
|
436
|
+
_dispatch(event, path, oldPath) {
|
|
437
|
+
// Chokidar's event types line up with ours 1:1 except 'rename'.
|
|
438
|
+
if (event === 'rename') {
|
|
439
|
+
if (oldPath) this.emit('unlink', oldPath);
|
|
440
|
+
this.emit('add', path);
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
if (this._listeners[event]) this.emit(event, path);
|
|
444
|
+
}
|
|
445
|
+
add(paths) {
|
|
446
|
+
const arr = Array.isArray(paths) ? paths : [paths];
|
|
447
|
+
for (const p of arr) if (!this.paths.includes(p)) this.paths.push(p);
|
|
448
|
+
return this;
|
|
449
|
+
}
|
|
450
|
+
unwatch(paths) {
|
|
451
|
+
const arr = Array.isArray(paths) ? paths : [paths];
|
|
452
|
+
this.paths = this.paths.filter((p) => !arr.includes(p));
|
|
453
|
+
return this;
|
|
454
|
+
}
|
|
455
|
+
getWatched() {
|
|
456
|
+
const out = {};
|
|
457
|
+
for (const p of this.paths) out[p] = [];
|
|
458
|
+
return out;
|
|
459
|
+
}
|
|
460
|
+
async close() {
|
|
461
|
+
this._closed = true;
|
|
462
|
+
_g.__cirrusRealWatchers?.delete(this);
|
|
463
|
+
}
|
|
464
|
+
get isReady() { return !this._closed; }
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
export function watch(paths, opts) {
|
|
468
|
+
if (globalThis.__cirrusDebug) console.log('[cirrus-chokidar] watch() called with paths=', JSON.stringify(paths).slice(0, 200));
|
|
469
|
+
return new CirrusWatcher(paths, opts);
|
|
470
|
+
}
|
|
471
|
+
export const FSWatcher = CirrusWatcher;
|
|
472
|
+
const _exports = { watch, FSWatcher };
|
|
473
|
+
_g.__cirrusChokidarModule = { default: _exports, ..._exports };
|
|
474
|
+
export default _exports;
|
|
475
|
+
`.trim();
|
|
476
|
+
}
|