@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,1279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* real-vite-fs-shim.ts — Phase 1 VFS-backed fs shim for the real-vite facet.
|
|
3
|
+
*
|
|
4
|
+
* What this file exports:
|
|
5
|
+
*
|
|
6
|
+
* generateFsShimModuleCode() — returns the ESM source of the module the
|
|
7
|
+
* facet imports as `node:fs` (via
|
|
8
|
+
* the esbuild alias in
|
|
9
|
+
* scripts/bundle-real-vite.mjs).
|
|
10
|
+
* generateFsPromisesShimModuleCode()
|
|
11
|
+
* — ditto for `node:fs/promises`.
|
|
12
|
+
* buildFsSnapshot(vfs, root) — supervisor-side helper that walks the
|
|
13
|
+
* SqliteVFS and returns a `{path: content}`
|
|
14
|
+
* snapshot to seed the facet's sync-fs Map.
|
|
15
|
+
*
|
|
16
|
+
* Design notes:
|
|
17
|
+
*
|
|
18
|
+
* workerd facets are **async-only** for RPC. But Vite's code (and its
|
|
19
|
+
* bundled deps like readdirp, picomatch, magic-string, etc.) calls a
|
|
20
|
+
* LOT of synchronous node:fs functions during module initialization
|
|
21
|
+
* and config resolution — readFileSync, existsSync, statSync,
|
|
22
|
+
* readdirSync. We can't block on SUPERVISOR.readFile() from a sync
|
|
23
|
+
* call site.
|
|
24
|
+
*
|
|
25
|
+
* Solution: the supervisor pre-builds an in-memory snapshot of the
|
|
26
|
+
* project VFS (all text files + synthetic vite package.json +
|
|
27
|
+
* node_modules of known-useful packages) and passes it to the facet
|
|
28
|
+
* via a synthetic `synthetic.js` module that seeds
|
|
29
|
+
* globalThis.__cirrusRealSynthetic. Every sync fs call first checks
|
|
30
|
+
* that Map. Async fs.promises calls fall through to
|
|
31
|
+
* env.SUPERVISOR.readFile(), letting Vite's middleware read files
|
|
32
|
+
* modified after boot.
|
|
33
|
+
*
|
|
34
|
+
* Writes (writeFile, writeFileSync, mkdir, mkdirSync, rename, unlink)
|
|
35
|
+
* update the facet-local Map immediately AND fire an async RPC to
|
|
36
|
+
* the supervisor. Sync writes are best-effort fire-and-forget — the
|
|
37
|
+
* supervisor eventually persists, but a sync writer that reads back
|
|
38
|
+
* what it just wrote will Just Work because the local Map is
|
|
39
|
+
* coherent.
|
|
40
|
+
*
|
|
41
|
+
* Watch (fs.watch, fs.watchFile): the facet runs a long-poll loop
|
|
42
|
+
* against SUPERVISOR.waitForVfsEvents(), translating VFS events into
|
|
43
|
+
* chokidar-shaped callbacks. This module exposes a minimal FSWatcher
|
|
44
|
+
* class that Vite's bundled chokidar sees via the esbuild alias
|
|
45
|
+
* (chokidar → this module).
|
|
46
|
+
*
|
|
47
|
+
* All this logic is emitted as a JS string and loaded into the
|
|
48
|
+
* facet via LOADER.load({ modules }). Keeping it here (in a .ts
|
|
49
|
+
* source file) instead of a .generated.ts means editor + typecheck
|
|
50
|
+
* can read it even though TypeScript doesn't compile it.
|
|
51
|
+
*/
|
|
52
|
+
/**
|
|
53
|
+
* Walk the VFS and produce a snapshot suitable for seeding the facet's
|
|
54
|
+
* sync-fs Map.
|
|
55
|
+
*
|
|
56
|
+
* Included:
|
|
57
|
+
* - Everything under `root/` except large binary blobs (over 256 KB)
|
|
58
|
+
* and files that won't be read synchronously (images, fonts, .node,
|
|
59
|
+
* .map > 1 MB).
|
|
60
|
+
* - Every `package.json` under `root/node_modules/**` (needed for
|
|
61
|
+
* Vite's dep resolver walk-ups).
|
|
62
|
+
* - All `.js/.mjs/.cjs/.ts/.tsx/.jsx/.css/.json/.html/.svg` text files
|
|
63
|
+
* under `root/node_modules/vite/**` (Vite's own client assets) and
|
|
64
|
+
* `root/node_modules/@vitejs/**` (plugin source).
|
|
65
|
+
*
|
|
66
|
+
* Excluded:
|
|
67
|
+
* - Binary .node addons (workerd can't load them anyway).
|
|
68
|
+
* - .git/** (irrelevant).
|
|
69
|
+
* - Any file > MAX_FILE_BYTES (skipped with a diagnostic).
|
|
70
|
+
*
|
|
71
|
+
* Returns a Record<path, content>. Paths are absolute filesystem paths
|
|
72
|
+
* as seen by Vite (/home/user/app/src/main.tsx).
|
|
73
|
+
*/
|
|
74
|
+
const MAX_FILE_BYTES = 256 * 1024; // 256 KB per file
|
|
75
|
+
const MAX_TOTAL_USER_BYTES = 16 * 1024 * 1024; // 16 MB cap on USER project
|
|
76
|
+
const TEXT_EXTENSIONS = new Set([
|
|
77
|
+
'.js', '.mjs', '.cjs', '.ts', '.tsx', '.jsx', '.mts', '.cts',
|
|
78
|
+
'.json', '.html', '.htm', '.css', '.scss', '.sass', '.less',
|
|
79
|
+
'.vue', '.svelte', '.astro',
|
|
80
|
+
'.svg', '.md', '.mdx', '.txt',
|
|
81
|
+
'.map',
|
|
82
|
+
]);
|
|
83
|
+
const SKIP_DIRS_IN_USER_PROJECT = new Set([
|
|
84
|
+
'.git', '.cache', '.svelte-kit', 'coverage',
|
|
85
|
+
'.next', '.nuxt', '.parcel-cache',
|
|
86
|
+
'.wrangler', '.turbo', '.vercel',
|
|
87
|
+
'dist', 'build',
|
|
88
|
+
'node_modules', // walked separately, lazily
|
|
89
|
+
]);
|
|
90
|
+
function isLikelyText(filename) {
|
|
91
|
+
const idx = filename.lastIndexOf('.');
|
|
92
|
+
if (idx < 0)
|
|
93
|
+
return false;
|
|
94
|
+
return TEXT_EXTENSIONS.has(filename.slice(idx).toLowerCase());
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Build a LAZY snapshot of the project for the facet's sync-fs Map.
|
|
98
|
+
*
|
|
99
|
+
* What gets eagerly seeded:
|
|
100
|
+
* - Every file under the user project (outside node_modules) up to
|
|
101
|
+
* 16 MB total.
|
|
102
|
+
* - Every package.json under node_modules/** (needed for Vite's
|
|
103
|
+
* resolver walk-ups and for __cirrusRealUserspaceRequire).
|
|
104
|
+
*
|
|
105
|
+
* What does NOT get eagerly seeded:
|
|
106
|
+
* - Everything else in node_modules (JS source, CSS, etc.).
|
|
107
|
+
*
|
|
108
|
+
* Not-eagerly-seeded files are fetched on demand via the
|
|
109
|
+
* SUPERVISOR.readFile RPC from the facet's async fs-promises shim,
|
|
110
|
+
* AND populate the in-facet Map the first time they're read so
|
|
111
|
+
* subsequent sync reads hit local memory.
|
|
112
|
+
*
|
|
113
|
+
* This keeps the facet boot memory footprint bounded (typical real
|
|
114
|
+
* React project: ~2 MB instead of 10+ MB) while still delivering
|
|
115
|
+
* correctness — Vite reads deps lazily during the transform pipeline,
|
|
116
|
+
* so async-first-then-cache is the natural fit.
|
|
117
|
+
*/
|
|
118
|
+
export function buildFsSnapshot(vfs, projectRoot) {
|
|
119
|
+
const files = {};
|
|
120
|
+
const dirsSet = new Set();
|
|
121
|
+
// existingPaths: a LIGHTWEIGHT index of every file path in
|
|
122
|
+
// node_modules (paths only, no content). The fs-shim's existsSync
|
|
123
|
+
// and statSync consult this so Vite's resolver walks deep
|
|
124
|
+
// module trees correctly without us having to eager-cache every
|
|
125
|
+
// file. Async readFile RPCs fetch content on demand.
|
|
126
|
+
//
|
|
127
|
+
// Path-only storage is cheap: ~50-100 bytes per path × thousands
|
|
128
|
+
// of files ≈ several hundred KB. Compare with content (avg 5 KB
|
|
129
|
+
// per file × thousands = tens of MB).
|
|
130
|
+
const existingPaths = [];
|
|
131
|
+
let totalBytes = 0;
|
|
132
|
+
let skipped = 0;
|
|
133
|
+
let pkgJsonCount = 0;
|
|
134
|
+
const pRoot = projectRoot.replace(/^\/+/, '').replace(/\/+$/, '');
|
|
135
|
+
// Pass 1: walk the user project tree (skipping node_modules) and
|
|
136
|
+
// seed every text file up to the byte budget.
|
|
137
|
+
function walkUserTree(relDir, depth) {
|
|
138
|
+
if (depth > 32)
|
|
139
|
+
return;
|
|
140
|
+
if (totalBytes >= MAX_TOTAL_USER_BYTES)
|
|
141
|
+
return;
|
|
142
|
+
let entries;
|
|
143
|
+
try {
|
|
144
|
+
entries = vfs.readdir(relDir);
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
dirsSet.add('/' + relDir);
|
|
150
|
+
for (const entry of entries) {
|
|
151
|
+
const childRel = relDir ? relDir + '/' + entry.name : entry.name;
|
|
152
|
+
const absPath = '/' + childRel;
|
|
153
|
+
if (entry.type === 'directory') {
|
|
154
|
+
if (SKIP_DIRS_IN_USER_PROJECT.has(entry.name))
|
|
155
|
+
continue;
|
|
156
|
+
walkUserTree(childRel, depth + 1);
|
|
157
|
+
}
|
|
158
|
+
else if (entry.type === 'file') {
|
|
159
|
+
const isPkgJson = entry.name === 'package.json';
|
|
160
|
+
if (!isPkgJson && !isLikelyText(entry.name)) {
|
|
161
|
+
skipped++;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
if (totalBytes >= MAX_TOTAL_USER_BYTES) {
|
|
165
|
+
skipped++;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
const st = vfs.stat(childRel);
|
|
170
|
+
if (st.size > MAX_FILE_BYTES && !isPkgJson) {
|
|
171
|
+
skipped++;
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
const content = vfs.readFileString(childRel);
|
|
175
|
+
files[absPath] = content;
|
|
176
|
+
totalBytes += content.length;
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
skipped++;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// Pass 2: walk every node_modules/** package.json AND collect the
|
|
185
|
+
// entry files it points at (main / module / exports.* / types).
|
|
186
|
+
// Without this, Vite's resolvePackageEntry uses fs.existsSync to
|
|
187
|
+
// test entry paths — which returns false for files NOT in our
|
|
188
|
+
// snapshot, making the resolver fail with
|
|
189
|
+
// `Failed to resolve entry for package "react"`.
|
|
190
|
+
//
|
|
191
|
+
// We extract all plausible entry paths from the package.json's
|
|
192
|
+
// exports/main/module/browser fields and eagerly include just
|
|
193
|
+
// those specific files (and any subpath exports they reference).
|
|
194
|
+
// Typical package yields 2-5 entries, so the byte cost is
|
|
195
|
+
// bounded.
|
|
196
|
+
const entryFilesToSeed = new Set();
|
|
197
|
+
function collectExportPaths(node, out) {
|
|
198
|
+
if (!node)
|
|
199
|
+
return;
|
|
200
|
+
if (typeof node === 'string') {
|
|
201
|
+
if (node.startsWith('./'))
|
|
202
|
+
out.add(node.slice(2));
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (Array.isArray(node)) {
|
|
206
|
+
for (const n of node)
|
|
207
|
+
collectExportPaths(n, out);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (typeof node === 'object') {
|
|
211
|
+
for (const k of Object.keys(node)) {
|
|
212
|
+
collectExportPaths(node[k], out);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function walkNodeModules(relDir, depth) {
|
|
217
|
+
if (depth > 32)
|
|
218
|
+
return;
|
|
219
|
+
let entries;
|
|
220
|
+
try {
|
|
221
|
+
entries = vfs.readdir(relDir);
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
dirsSet.add('/' + relDir);
|
|
227
|
+
for (const entry of entries) {
|
|
228
|
+
const childRel = relDir ? relDir + '/' + entry.name : entry.name;
|
|
229
|
+
const absPath = '/' + childRel;
|
|
230
|
+
if (entry.type === 'directory') {
|
|
231
|
+
if (entry.name === '.bin' || entry.name === '.cache' ||
|
|
232
|
+
entry.name === 'node_modules' || entry.name === 'test' ||
|
|
233
|
+
entry.name === 'tests' || entry.name === '__tests__' ||
|
|
234
|
+
entry.name === 'docs' || entry.name === 'doc' ||
|
|
235
|
+
entry.name === 'examples' || entry.name === 'example') {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
walkNodeModules(childRel, depth + 1);
|
|
239
|
+
}
|
|
240
|
+
else if (entry.type === 'file') {
|
|
241
|
+
// Index the path (cheap — string only, no content).
|
|
242
|
+
// Used by fs.existsSync / statSync so Vite's resolver walks
|
|
243
|
+
// deep module imports correctly without paying to cache the
|
|
244
|
+
// content eagerly.
|
|
245
|
+
existingPaths.push(absPath);
|
|
246
|
+
if (entry.name === 'package.json') {
|
|
247
|
+
try {
|
|
248
|
+
const content = vfs.readFileString(childRel);
|
|
249
|
+
files[absPath] = content;
|
|
250
|
+
totalBytes += content.length;
|
|
251
|
+
pkgJsonCount++;
|
|
252
|
+
const pkg = JSON.parse(content);
|
|
253
|
+
const pkgDir = childRel.slice(0, -('/package.json'.length));
|
|
254
|
+
const candidates = new Set();
|
|
255
|
+
if (typeof pkg.main === 'string')
|
|
256
|
+
candidates.add(pkg.main);
|
|
257
|
+
if (typeof pkg.module === 'string')
|
|
258
|
+
candidates.add(pkg.module);
|
|
259
|
+
if (typeof pkg.browser === 'string')
|
|
260
|
+
candidates.add(pkg.browser);
|
|
261
|
+
if (typeof pkg.types === 'string')
|
|
262
|
+
candidates.add(pkg.types);
|
|
263
|
+
if (typeof pkg.typings === 'string')
|
|
264
|
+
candidates.add(pkg.typings);
|
|
265
|
+
if (pkg.exports)
|
|
266
|
+
collectExportPaths(pkg.exports, candidates);
|
|
267
|
+
if (pkg.imports)
|
|
268
|
+
collectExportPaths(pkg.imports, candidates);
|
|
269
|
+
for (const idx of ['index.js', 'index.mjs', 'index.cjs']) {
|
|
270
|
+
candidates.add(idx);
|
|
271
|
+
}
|
|
272
|
+
for (const rel of candidates) {
|
|
273
|
+
const clean = rel.replace(/^\.\//, '');
|
|
274
|
+
if (!clean || clean.includes('*'))
|
|
275
|
+
continue;
|
|
276
|
+
entryFilesToSeed.add(pkgDir + '/' + clean);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
skipped++;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
walkUserTree(pRoot, 0);
|
|
287
|
+
const nmPath = pRoot + '/node_modules';
|
|
288
|
+
if (vfs.exists(nmPath))
|
|
289
|
+
walkNodeModules(nmPath, 0);
|
|
290
|
+
// Pass 3: read every entry file collected above. Cap at ~256KB/file
|
|
291
|
+
// since some packages ship big bundles we don't need eagerly.
|
|
292
|
+
for (const rel of entryFilesToSeed) {
|
|
293
|
+
const abs = '/' + rel;
|
|
294
|
+
if (files[abs])
|
|
295
|
+
continue;
|
|
296
|
+
try {
|
|
297
|
+
const st = vfs.stat(rel);
|
|
298
|
+
if (st.type !== 'file')
|
|
299
|
+
continue;
|
|
300
|
+
if (st.size > MAX_FILE_BYTES) {
|
|
301
|
+
skipped++;
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
const content = vfs.readFileString(rel);
|
|
305
|
+
files[abs] = content;
|
|
306
|
+
totalBytes += content.length;
|
|
307
|
+
}
|
|
308
|
+
catch { /* missing — that's OK */ }
|
|
309
|
+
}
|
|
310
|
+
return {
|
|
311
|
+
files,
|
|
312
|
+
dirs: [...dirsSet].sort(),
|
|
313
|
+
existingPaths,
|
|
314
|
+
totalBytes,
|
|
315
|
+
skipped,
|
|
316
|
+
fileCount: Object.keys(files).length,
|
|
317
|
+
packageJsonCount: pkgJsonCount,
|
|
318
|
+
pathIndexCount: existingPaths.length,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* ESM source of the fs-shim module. esbuild's bundler sees
|
|
323
|
+
* import * as fs from 'node:fs'
|
|
324
|
+
* in vite's bundle and (thanks to the alias plugin in
|
|
325
|
+
* scripts/bundle-real-vite.mjs) rewrites those imports to this
|
|
326
|
+
* module. The shim exports every fs name Vite touches, routing them
|
|
327
|
+
* through `globalThis.__cirrusRealFs` — which we populate before the
|
|
328
|
+
* first import of vite.bundle.js in synthetic.js.
|
|
329
|
+
*
|
|
330
|
+
* The runtime lives in globalThis so it survives cross-module
|
|
331
|
+
* lookups AND can be re-seeded on facet reload.
|
|
332
|
+
*/
|
|
333
|
+
export function generateFsShimModuleCode() {
|
|
334
|
+
// The shim is plain ESM. It re-exports a handful of names that most
|
|
335
|
+
// libraries import from 'node:fs', routing reads through a Map we
|
|
336
|
+
// populate before the first vite.bundle.js import. The constants
|
|
337
|
+
// from the real node:fs are passed through.
|
|
338
|
+
return `
|
|
339
|
+
// ── fs shim (sync) — generated by src/real-vite-fs-shim.ts ────────
|
|
340
|
+
import * as _real from 'real-node-fs.js';
|
|
341
|
+
|
|
342
|
+
// The supervisor-seeded snapshot + live-write overlay.
|
|
343
|
+
// Shape: {
|
|
344
|
+
// files: Map<absPath, string> — cached content
|
|
345
|
+
// dirs: Set<absPath> — directories known to exist
|
|
346
|
+
// existingPaths: Set<absPath> — node_modules file paths
|
|
347
|
+
// (content lazy; index only)
|
|
348
|
+
// }
|
|
349
|
+
// Seeded by synthetic.js BEFORE vite.bundle.js evaluates.
|
|
350
|
+
const _g = globalThis;
|
|
351
|
+
if (!_g.__cirrusRealFs) _g.__cirrusRealFs = { files: new Map(), dirs: new Set(), existingPaths: new Set() };
|
|
352
|
+
if (!_g.__cirrusRealFs.existingPaths) _g.__cirrusRealFs.existingPaths = new Set();
|
|
353
|
+
|
|
354
|
+
function _norm(p) {
|
|
355
|
+
if (p == null) return null;
|
|
356
|
+
if (typeof p === 'object') {
|
|
357
|
+
// URL-ish
|
|
358
|
+
try { p = p.pathname || String(p); } catch { return null; }
|
|
359
|
+
}
|
|
360
|
+
if (typeof p !== 'string') return null;
|
|
361
|
+
return p.replace(/^file:\\/\\//, '').replace(/\\/+$/, p === '/' ? '/' : '');
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function _makeStats(size, isDir) {
|
|
365
|
+
return {
|
|
366
|
+
isFile: () => !isDir,
|
|
367
|
+
isDirectory: () => !!isDir,
|
|
368
|
+
isSymbolicLink: () => false,
|
|
369
|
+
isBlockDevice: () => false,
|
|
370
|
+
isCharacterDevice: () => false,
|
|
371
|
+
isFIFO: () => false,
|
|
372
|
+
isSocket: () => false,
|
|
373
|
+
size: size | 0,
|
|
374
|
+
mtime: new Date(0), ctime: new Date(0), atime: new Date(0), birthtime: new Date(0),
|
|
375
|
+
mtimeMs: 0, ctimeMs: 0, atimeMs: 0, birthtimeMs: 0,
|
|
376
|
+
mode: isDir ? 0o040755 : 0o100644,
|
|
377
|
+
uid: 0, gid: 0, ino: 0, nlink: 1, dev: 0, rdev: 0, blksize: 4096, blocks: 1,
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// ── Sync read methods ──
|
|
382
|
+
export const readFileSync = function(p, ...rest) {
|
|
383
|
+
let n = _norm(p);
|
|
384
|
+
if (globalThis.__cirrusFsDebug) console.log('[fs.readFileSync]', n);
|
|
385
|
+
if (globalThis.__cirrusResolveDebug && n && (n.includes('/react/') || n.includes('/react-dom/'))) console.log('[fs.readFileSync react]', n);
|
|
386
|
+
// Relative paths: the caller used _require.resolve("./x") which
|
|
387
|
+
// didn't fully resolve. Try the snapshot with ./x stripped to /x.
|
|
388
|
+
if (n && n.startsWith('./')) n = '/' + n.slice(2);
|
|
389
|
+
// Special case: rollup's wasm binding. Return the pre-seeded bytes.
|
|
390
|
+
if (n && n.endsWith('bindings_wasm_bg.wasm') && _g.__cirrusRealFs.getWasmBytes) {
|
|
391
|
+
const bytes = _g.__cirrusRealFs.getWasmBytes();
|
|
392
|
+
const opts = rest[0], enc = typeof opts === 'string' ? opts : opts?.encoding;
|
|
393
|
+
if (enc === 'base64') return btoa(String.fromCharCode(...bytes));
|
|
394
|
+
return bytes;
|
|
395
|
+
}
|
|
396
|
+
if (n != null && _g.__cirrusRealFs.files.has(n)) {
|
|
397
|
+
const c = _g.__cirrusRealFs.files.get(n);
|
|
398
|
+
const opts = rest[0], enc = typeof opts === 'string' ? opts : opts?.encoding;
|
|
399
|
+
if (enc) return c;
|
|
400
|
+
try { return globalThis.Buffer.from(c, 'utf-8'); }
|
|
401
|
+
catch { return new TextEncoder().encode(c); }
|
|
402
|
+
}
|
|
403
|
+
try { return _real.readFileSync.call(_real, p, ...rest); }
|
|
404
|
+
catch (e) {
|
|
405
|
+
throw new Error('[cirrus-real fs] readFileSync missing from snapshot: ' + n + ' (' + (e?.message || e) + ')');
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
export const existsSync = function(p) {
|
|
410
|
+
const n = _norm(p);
|
|
411
|
+
if (globalThis.__cirrusFsDebug) console.log('[fs.existsSync]', n);
|
|
412
|
+
if (n != null) {
|
|
413
|
+
if (_g.__cirrusRealFs.files.has(n)) return true;
|
|
414
|
+
if (_g.__cirrusRealFs.dirs.has(n)) return true;
|
|
415
|
+
// Path-only index: answers "is this file in VFS?" without the
|
|
416
|
+
// file being eagerly cached. Vite's tryNodeResolve / tryFsResolve
|
|
417
|
+
// rely on existsSync to walk deep node_modules trees.
|
|
418
|
+
if (_g.__cirrusRealFs.existingPaths.has(n)) return true;
|
|
419
|
+
// Also treat any parent-dir of a known file as existing.
|
|
420
|
+
for (const k of _g.__cirrusRealFs.files.keys()) {
|
|
421
|
+
if (k.startsWith(n + '/')) return true;
|
|
422
|
+
}
|
|
423
|
+
// Check the path index for subpath-existence too (faster than
|
|
424
|
+
// iterating \`files\`).
|
|
425
|
+
const nSlash = n + '/';
|
|
426
|
+
for (const k of _g.__cirrusRealFs.existingPaths) {
|
|
427
|
+
if (k.startsWith(nSlash)) return true;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
try { return _real.existsSync.call(_real, p); } catch { return false; }
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
export const statSync = function(p, ...rest) {
|
|
434
|
+
const n = _norm(p);
|
|
435
|
+
if (globalThis.__cirrusFsDebug && n && (n.includes('react') || n.includes('/src/'))) console.log('[fs.statSync]', n);
|
|
436
|
+
if (n != null) {
|
|
437
|
+
if (_g.__cirrusRealFs.files.has(n)) return _makeStats(_g.__cirrusRealFs.files.get(n).length, false);
|
|
438
|
+
if (_g.__cirrusRealFs.dirs.has(n)) return _makeStats(0, true);
|
|
439
|
+
// Path-only index: we know the file exists but don't have its
|
|
440
|
+
// size. Return a placeholder stat with size=0 (accurate enough
|
|
441
|
+
// for resolver logic — it only checks isFile()/isDirectory()).
|
|
442
|
+
if (_g.__cirrusRealFs.existingPaths.has(n)) return _makeStats(0, false);
|
|
443
|
+
for (const k of _g.__cirrusRealFs.files.keys()) {
|
|
444
|
+
if (k.startsWith(n + '/')) return _makeStats(0, true);
|
|
445
|
+
}
|
|
446
|
+
const nSlash = n + '/';
|
|
447
|
+
for (const k of _g.__cirrusRealFs.existingPaths) {
|
|
448
|
+
if (k.startsWith(nSlash)) return _makeStats(0, true);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
try { return _real.statSync.call(_real, p, ...rest); }
|
|
452
|
+
catch (e) {
|
|
453
|
+
if (rest[0]?.throwIfNoEntry === false) return undefined;
|
|
454
|
+
throw e;
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
export const lstatSync = statSync;
|
|
459
|
+
|
|
460
|
+
export const realpathSync = function(p) {
|
|
461
|
+
const n = _norm(p);
|
|
462
|
+
if (n != null && (_g.__cirrusRealFs.files.has(n) || _g.__cirrusRealFs.dirs.has(n) || _g.__cirrusRealFs.existingPaths.has(n))) return n;
|
|
463
|
+
try { return _real.realpathSync.call(_real, p); } catch { return n || p; }
|
|
464
|
+
};
|
|
465
|
+
realpathSync.native = realpathSync;
|
|
466
|
+
|
|
467
|
+
export const readdirSync = function(p, opts) {
|
|
468
|
+
const n = _norm(p);
|
|
469
|
+
const out = new Set();
|
|
470
|
+
const outTypes = new Map();
|
|
471
|
+
if (n != null) {
|
|
472
|
+
// Collect direct children from files + dirs.
|
|
473
|
+
const prefix = n === '/' ? '/' : n + '/';
|
|
474
|
+
for (const k of _g.__cirrusRealFs.files.keys()) {
|
|
475
|
+
if (k.startsWith(prefix)) {
|
|
476
|
+
const rel = k.slice(prefix.length);
|
|
477
|
+
const slash = rel.indexOf('/');
|
|
478
|
+
if (slash < 0) {
|
|
479
|
+
out.add(rel);
|
|
480
|
+
outTypes.set(rel, 'file');
|
|
481
|
+
} else {
|
|
482
|
+
const seg = rel.slice(0, slash);
|
|
483
|
+
out.add(seg);
|
|
484
|
+
if (!outTypes.has(seg)) outTypes.set(seg, 'directory');
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
// Path-only index: include those too.
|
|
489
|
+
for (const k of _g.__cirrusRealFs.existingPaths) {
|
|
490
|
+
if (k.startsWith(prefix)) {
|
|
491
|
+
const rel = k.slice(prefix.length);
|
|
492
|
+
const slash = rel.indexOf('/');
|
|
493
|
+
if (slash < 0) {
|
|
494
|
+
out.add(rel);
|
|
495
|
+
if (!outTypes.has(rel)) outTypes.set(rel, 'file');
|
|
496
|
+
} else {
|
|
497
|
+
const seg = rel.slice(0, slash);
|
|
498
|
+
out.add(seg);
|
|
499
|
+
if (!outTypes.has(seg)) outTypes.set(seg, 'directory');
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
for (const d of _g.__cirrusRealFs.dirs) {
|
|
504
|
+
if (d.startsWith(prefix)) {
|
|
505
|
+
const rel = d.slice(prefix.length);
|
|
506
|
+
const slash = rel.indexOf('/');
|
|
507
|
+
const seg = slash < 0 ? rel : rel.slice(0, slash);
|
|
508
|
+
if (seg) { out.add(seg); if (!outTypes.has(seg)) outTypes.set(seg, 'directory'); }
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
const names = [...out].sort();
|
|
513
|
+
if (names.length === 0) {
|
|
514
|
+
try { return _real.readdirSync.call(_real, p, opts); } catch { /* empty */ }
|
|
515
|
+
}
|
|
516
|
+
if (opts?.withFileTypes) {
|
|
517
|
+
return names.map((name) => {
|
|
518
|
+
const t = outTypes.get(name) || 'file';
|
|
519
|
+
return {
|
|
520
|
+
name,
|
|
521
|
+
isFile: () => t === 'file',
|
|
522
|
+
isDirectory: () => t === 'directory',
|
|
523
|
+
isSymbolicLink: () => false,
|
|
524
|
+
isBlockDevice: () => false,
|
|
525
|
+
isCharacterDevice: () => false,
|
|
526
|
+
isFIFO: () => false,
|
|
527
|
+
isSocket: () => false,
|
|
528
|
+
};
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
return names;
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
export const accessSync = function(p) {
|
|
535
|
+
if (!existsSync(p)) throw new Error('ENOENT: ' + p);
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
// ── Sync write methods ──
|
|
539
|
+
// Update the in-facet Map synchronously so subsequent reads see the
|
|
540
|
+
// change, then fire-and-forget an RPC to the supervisor for
|
|
541
|
+
// persistence. Callers that must wait for the write to persist
|
|
542
|
+
// should use fs.promises.writeFile instead.
|
|
543
|
+
export const writeFileSync = function(p, data, opts) {
|
|
544
|
+
const n = _norm(p);
|
|
545
|
+
if (n == null) throw new Error('writeFileSync: invalid path');
|
|
546
|
+
let content;
|
|
547
|
+
if (typeof data === 'string') content = data;
|
|
548
|
+
else if (data && typeof data.toString === 'function') content = new TextDecoder('utf-8').decode(data instanceof Uint8Array ? data : new Uint8Array(data.buffer || data));
|
|
549
|
+
else content = String(data);
|
|
550
|
+
_g.__cirrusRealFs.files.set(n, content);
|
|
551
|
+
// Register parent dirs
|
|
552
|
+
let cur = n;
|
|
553
|
+
while (cur.lastIndexOf('/') > 0) {
|
|
554
|
+
cur = cur.slice(0, cur.lastIndexOf('/'));
|
|
555
|
+
_g.__cirrusRealFs.dirs.add(cur);
|
|
556
|
+
}
|
|
557
|
+
// Fire-and-forget RPC — if SUPERVISOR is bound, persist.
|
|
558
|
+
const sup = _g.__cirrusRealSupervisor;
|
|
559
|
+
if (sup?.writeFile) {
|
|
560
|
+
sup.writeFile(n.replace(/^\\/+/, ''), content).catch((e) => {
|
|
561
|
+
console.warn('[cirrus-real fs] async writeFile RPC failed for', n, e?.message);
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
export const mkdirSync = function(p, opts) {
|
|
567
|
+
const n = _norm(p);
|
|
568
|
+
if (n == null) return undefined;
|
|
569
|
+
_g.__cirrusRealFs.dirs.add(n);
|
|
570
|
+
if (opts?.recursive) {
|
|
571
|
+
let cur = n;
|
|
572
|
+
while (cur.lastIndexOf('/') > 0) {
|
|
573
|
+
cur = cur.slice(0, cur.lastIndexOf('/'));
|
|
574
|
+
_g.__cirrusRealFs.dirs.add(cur);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
const sup = _g.__cirrusRealSupervisor;
|
|
578
|
+
if (sup?.mkdir) {
|
|
579
|
+
sup.mkdir(n.replace(/^\\/+/, '')).catch(() => {});
|
|
580
|
+
}
|
|
581
|
+
return n;
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
export const unlinkSync = function(p) {
|
|
585
|
+
const n = _norm(p);
|
|
586
|
+
if (n != null) _g.__cirrusRealFs.files.delete(n);
|
|
587
|
+
const sup = _g.__cirrusRealSupervisor;
|
|
588
|
+
if (sup?.unlink) sup.unlink(n.replace(/^\\/+/, '')).catch(() => {});
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
export const rmSync = unlinkSync;
|
|
592
|
+
export const rmdirSync = function(p) { /* no-op */ };
|
|
593
|
+
|
|
594
|
+
export const renameSync = function(from, to) {
|
|
595
|
+
const f = _norm(from), t = _norm(to);
|
|
596
|
+
if (f && t && _g.__cirrusRealFs.files.has(f)) {
|
|
597
|
+
_g.__cirrusRealFs.files.set(t, _g.__cirrusRealFs.files.get(f));
|
|
598
|
+
_g.__cirrusRealFs.files.delete(f);
|
|
599
|
+
}
|
|
600
|
+
const sup = _g.__cirrusRealSupervisor;
|
|
601
|
+
if (sup?.writeFile && f && t && _g.__cirrusRealFs.files.has(t)) {
|
|
602
|
+
sup.writeFile(t.replace(/^\\/+/, ''), _g.__cirrusRealFs.files.get(t)).catch(() => {});
|
|
603
|
+
if (sup.unlink) sup.unlink(f.replace(/^\\/+/, '')).catch(() => {});
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
export const appendFileSync = function(p, data) {
|
|
608
|
+
const n = _norm(p);
|
|
609
|
+
if (n == null) return;
|
|
610
|
+
const prev = _g.__cirrusRealFs.files.get(n) || '';
|
|
611
|
+
const chunk = typeof data === 'string' ? data : new TextDecoder().decode(data);
|
|
612
|
+
writeFileSync(p, prev + chunk);
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
// ── Sync-shaped no-ops for things Vite occasionally touches ──
|
|
616
|
+
export const chmodSync = function() {};
|
|
617
|
+
export const chownSync = function() {};
|
|
618
|
+
export const utimesSync = function() {};
|
|
619
|
+
export const truncateSync = function() {};
|
|
620
|
+
export const symlinkSync = function() { throw new Error('symlinkSync not supported'); };
|
|
621
|
+
export const linkSync = function() { throw new Error('linkSync not supported'); };
|
|
622
|
+
export const readlinkSync = function() { throw new Error('readlinkSync not supported (no symlinks)'); };
|
|
623
|
+
|
|
624
|
+
// ── fs.watch ──
|
|
625
|
+
// Vite (via bundled chokidar) calls fs.watch in a few places. Our
|
|
626
|
+
// esbuild alias swaps chokidar out entirely, but the fs-shim still
|
|
627
|
+
// needs a safe watch() so plugins that call it directly don't explode.
|
|
628
|
+
// Implementation: no-op watcher that never fires. HMR is driven by
|
|
629
|
+
// the chokidar-alias + long-polled supervisor events, not by this.
|
|
630
|
+
export const watch = function() {
|
|
631
|
+
return {
|
|
632
|
+
close() {},
|
|
633
|
+
on() { return this; },
|
|
634
|
+
removeListener() {},
|
|
635
|
+
addListener() { return this; },
|
|
636
|
+
};
|
|
637
|
+
};
|
|
638
|
+
export const watchFile = function() {};
|
|
639
|
+
export const unwatchFile = function() {};
|
|
640
|
+
|
|
641
|
+
// ── Async methods (Promises + callback API) ──
|
|
642
|
+
// Callback-style: translate to our promise layer, then invoke the cb.
|
|
643
|
+
function _cb(fn) {
|
|
644
|
+
return function(...args) {
|
|
645
|
+
const cb = args[args.length - 1];
|
|
646
|
+
if (typeof cb !== 'function') throw new Error(fn.name + ': missing callback');
|
|
647
|
+
fn(...args.slice(0, -1)).then((v) => cb(null, v), (e) => cb(e));
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
export const readFile = _cb(async (p, opts) => readFilePromise(p, opts));
|
|
652
|
+
export const writeFile = _cb(async (p, data, opts) => writeFilePromise(p, data, opts));
|
|
653
|
+
export const stat = _cb(async (p) => statPromise(p));
|
|
654
|
+
export const lstat = _cb(async (p) => statPromise(p));
|
|
655
|
+
export const readdir = _cb(async (p, opts) => readdirPromise(p, opts));
|
|
656
|
+
export const mkdir = _cb(async (p, opts) => mkdirPromise(p, opts));
|
|
657
|
+
export const unlink = _cb(async (p) => unlinkPromise(p));
|
|
658
|
+
export const rename = _cb(async (from, to) => renamePromise(from, to));
|
|
659
|
+
export const access = _cb(async (p) => { if (!existsSync(p)) throw new Error('ENOENT: ' + p); });
|
|
660
|
+
export const realpath = _cb(async (p) => realpathSync(p));
|
|
661
|
+
Object.defineProperty(realpath, 'native', { value: realpath });
|
|
662
|
+
|
|
663
|
+
// Async "promise-returning" helpers used by the promises module too.
|
|
664
|
+
// ── LRU cap to bound the facet-resident cache ──────────────────
|
|
665
|
+
// Without this, every big node_modules source file (framer-motion,
|
|
666
|
+
// lucide-react, etc.) that Vite's transform pulls in sticks in
|
|
667
|
+
// \`__cirrusRealFs.files\` forever. On a real React project with
|
|
668
|
+
// 10+ deps transformed at once, that's tens of MB — compounded
|
|
669
|
+
// with Babel ASTs in flight, we blow the workerd isolate memory
|
|
670
|
+
// budget and exit 137.
|
|
671
|
+
//
|
|
672
|
+
// Strategy:
|
|
673
|
+
// - Files from the user's project (not under node_modules) are
|
|
674
|
+
// ALWAYS cached — they're small, seeds into the original
|
|
675
|
+
// snapshot, and needed synchronously for HMR transforms.
|
|
676
|
+
// - node_modules files go in an LRU with a 4 MB budget. Every
|
|
677
|
+
// cache hit touches access order; on insertion that would
|
|
678
|
+
// exceed the budget, oldest entries are evicted.
|
|
679
|
+
// - Files over SINGLE_FILE_CACHE_MAX (128 KB) are NEVER cached
|
|
680
|
+
// at all: they're re-read from supervisor on each access.
|
|
681
|
+
// Better to pay the RPC roundtrip than hold a multi-MB string
|
|
682
|
+
// that only gets parsed once.
|
|
683
|
+
//
|
|
684
|
+
// Sync reads from the snapshot are immune to this eviction. Only
|
|
685
|
+
// async RPC fetches get capped.
|
|
686
|
+
const _NM_LRU_LIMIT = 4 * 1024 * 1024;
|
|
687
|
+
const _SINGLE_FILE_CACHE_MAX = 128 * 1024;
|
|
688
|
+
_g.__cirrusRealFsLruSize = 0;
|
|
689
|
+
_g.__cirrusRealFsLruOrder = [];
|
|
690
|
+
|
|
691
|
+
function _cacheSetLru(path, content) {
|
|
692
|
+
// Only apply LRU to node_modules paths. User source stays sticky.
|
|
693
|
+
const inNodeModules = path.includes('/node_modules/');
|
|
694
|
+
if (!inNodeModules) {
|
|
695
|
+
_g.__cirrusRealFs.files.set(path, content);
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
if (content.length > _SINGLE_FILE_CACHE_MAX) {
|
|
699
|
+
// Too big — don't cache. Let future reads hit the supervisor again.
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
// Evict until there's room.
|
|
703
|
+
while (_g.__cirrusRealFsLruSize + content.length > _NM_LRU_LIMIT && _g.__cirrusRealFsLruOrder.length > 0) {
|
|
704
|
+
const victim = _g.__cirrusRealFsLruOrder.shift();
|
|
705
|
+
const v = _g.__cirrusRealFs.files.get(victim);
|
|
706
|
+
if (v !== undefined) {
|
|
707
|
+
_g.__cirrusRealFsLruSize -= v.length;
|
|
708
|
+
_g.__cirrusRealFs.files.delete(victim);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
_g.__cirrusRealFs.files.set(path, content);
|
|
712
|
+
_g.__cirrusRealFsLruSize += content.length;
|
|
713
|
+
_g.__cirrusRealFsLruOrder.push(path);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
function _cacheTouchLru(path) {
|
|
717
|
+
if (!path.includes('/node_modules/')) return;
|
|
718
|
+
const i = _g.__cirrusRealFsLruOrder.indexOf(path);
|
|
719
|
+
if (i >= 0 && i < _g.__cirrusRealFsLruOrder.length - 1) {
|
|
720
|
+
_g.__cirrusRealFsLruOrder.splice(i, 1);
|
|
721
|
+
_g.__cirrusRealFsLruOrder.push(path);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
export async function readFilePromise(p, opts) {
|
|
726
|
+
const n = _norm(p);
|
|
727
|
+
if (globalThis.__cirrusFsDebug) console.log('[fs.readFile]', n);
|
|
728
|
+
const enc = typeof opts === 'string' ? opts : opts?.encoding;
|
|
729
|
+
if (n != null && _g.__cirrusRealFs.files.has(n)) {
|
|
730
|
+
_cacheTouchLru(n);
|
|
731
|
+
const c = _g.__cirrusRealFs.files.get(n);
|
|
732
|
+
if (enc) return c;
|
|
733
|
+
try { return globalThis.Buffer.from(c, 'utf-8'); } catch { return new TextEncoder().encode(c); }
|
|
734
|
+
}
|
|
735
|
+
// Fall back to RPC (async path can block).
|
|
736
|
+
const sup = _g.__cirrusRealSupervisor;
|
|
737
|
+
if (sup?.readFile && n) {
|
|
738
|
+
const content = await sup.readFile(n.replace(/^\\/+/, ''));
|
|
739
|
+
if (typeof content === 'string') {
|
|
740
|
+
_cacheSetLru(n, content);
|
|
741
|
+
if (enc) return content;
|
|
742
|
+
try { return globalThis.Buffer.from(content, 'utf-8'); } catch { return new TextEncoder().encode(content); }
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
throw Object.assign(new Error('ENOENT: ' + n), { code: 'ENOENT', errno: -2, path: n });
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
export async function writeFilePromise(p, data, opts) {
|
|
749
|
+
// Same as sync path but awaits the RPC.
|
|
750
|
+
const n = _norm(p);
|
|
751
|
+
if (n == null) throw new Error('writeFile: invalid path');
|
|
752
|
+
let content;
|
|
753
|
+
if (typeof data === 'string') content = data;
|
|
754
|
+
else if (data instanceof Uint8Array) content = new TextDecoder('utf-8').decode(data);
|
|
755
|
+
else content = String(data);
|
|
756
|
+
_g.__cirrusRealFs.files.set(n, content);
|
|
757
|
+
let cur = n;
|
|
758
|
+
while (cur.lastIndexOf('/') > 0) {
|
|
759
|
+
cur = cur.slice(0, cur.lastIndexOf('/'));
|
|
760
|
+
_g.__cirrusRealFs.dirs.add(cur);
|
|
761
|
+
}
|
|
762
|
+
const sup = _g.__cirrusRealSupervisor;
|
|
763
|
+
if (sup?.writeFile) {
|
|
764
|
+
try { await sup.writeFile(n.replace(/^\\/+/, ''), content); }
|
|
765
|
+
catch (e) { /* supervisor may reject for read-only paths; local copy is authoritative */ }
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
export async function statPromise(p) { return statSync(p); }
|
|
770
|
+
export async function readdirPromise(p, opts) { return readdirSync(p, opts); }
|
|
771
|
+
export async function mkdirPromise(p, opts) { mkdirSync(p, opts); return p; }
|
|
772
|
+
export async function unlinkPromise(p) { unlinkSync(p); }
|
|
773
|
+
export async function renamePromise(from, to) { renameSync(from, to); }
|
|
774
|
+
export async function realpathPromise(p) { return realpathSync(p); }
|
|
775
|
+
|
|
776
|
+
// ── Constants + other exports Vite + deps look for ──
|
|
777
|
+
// _real may be a module namespace with direct named exports OR a
|
|
778
|
+
// default-exporting wrapper — pick whichever has the function. Keeps
|
|
779
|
+
// the shim robust across node / workerd import-resolution quirks.
|
|
780
|
+
function _pick(name) {
|
|
781
|
+
return (_real && (_real[name] || _real.default?.[name])) || (() => { throw new Error('[cirrus-real fs] ' + name + ' not available in workerd'); });
|
|
782
|
+
}
|
|
783
|
+
function _pickMaybe(name) {
|
|
784
|
+
return (_real && (_real[name] || _real.default?.[name])) || undefined;
|
|
785
|
+
}
|
|
786
|
+
export const constants = _pickMaybe('constants') || {};
|
|
787
|
+
export const Stats = _pickMaybe('Stats');
|
|
788
|
+
export const Dirent = _pickMaybe('Dirent');
|
|
789
|
+
export const Dir = _pickMaybe('Dir');
|
|
790
|
+
export const ReadStream = _pickMaybe('ReadStream');
|
|
791
|
+
export const WriteStream = _pickMaybe('WriteStream');
|
|
792
|
+
export const createReadStream = _pickMaybe('createReadStream');
|
|
793
|
+
export const createWriteStream = _pickMaybe('createWriteStream');
|
|
794
|
+
export const opendir = _pickMaybe('opendir');
|
|
795
|
+
export const opendirSync = _pickMaybe('opendirSync');
|
|
796
|
+
export const open = _pickMaybe('open');
|
|
797
|
+
export const openSync = _pickMaybe('openSync');
|
|
798
|
+
export const close = _pickMaybe('close');
|
|
799
|
+
export const closeSync = _pickMaybe('closeSync');
|
|
800
|
+
export const read = _pickMaybe('read');
|
|
801
|
+
export const readSync = _pickMaybe('readSync');
|
|
802
|
+
export const write = _pickMaybe('write');
|
|
803
|
+
export const writeSync = _pickMaybe('writeSync');
|
|
804
|
+
export const fstat = _pickMaybe('fstat');
|
|
805
|
+
export const fstatSync = _pickMaybe('fstatSync');
|
|
806
|
+
export const fsync = _pickMaybe('fsync');
|
|
807
|
+
export const fsyncSync = _pickMaybe('fsyncSync');
|
|
808
|
+
export const fdatasync = _pickMaybe('fdatasync');
|
|
809
|
+
export const fdatasyncSync = _pickMaybe('fdatasyncSync');
|
|
810
|
+
export const ftruncate = _pickMaybe('ftruncate');
|
|
811
|
+
export const ftruncateSync = _pickMaybe('ftruncateSync');
|
|
812
|
+
export const futimes = _pickMaybe('futimes');
|
|
813
|
+
export const futimesSync = _pickMaybe('futimesSync');
|
|
814
|
+
export const fchmod = _pickMaybe('fchmod');
|
|
815
|
+
export const fchmodSync = _pickMaybe('fchmodSync');
|
|
816
|
+
export const fchown = _pickMaybe('fchown');
|
|
817
|
+
export const fchownSync = _pickMaybe('fchownSync');
|
|
818
|
+
export const readv = _pickMaybe('readv');
|
|
819
|
+
export const readvSync = _pickMaybe('readvSync');
|
|
820
|
+
export const writev = _pickMaybe('writev');
|
|
821
|
+
export const writevSync = _pickMaybe('writevSync');
|
|
822
|
+
export const mkdtemp = _pickMaybe('mkdtemp');
|
|
823
|
+
export const mkdtempSync = _pickMaybe('mkdtempSync');
|
|
824
|
+
export const cp = _pickMaybe('cp');
|
|
825
|
+
export const cpSync = _pickMaybe('cpSync');
|
|
826
|
+
export const copyFile = _pickMaybe('copyFile');
|
|
827
|
+
export const copyFileSync = _pickMaybe('copyFileSync');
|
|
828
|
+
export const appendFile = _cb(async (p, data) => { appendFileSync(p, data); });
|
|
829
|
+
export const chmod = _cb(async () => {});
|
|
830
|
+
export const chown = _cb(async () => {});
|
|
831
|
+
export const utimes = _cb(async () => {});
|
|
832
|
+
export const truncate = _cb(async () => {});
|
|
833
|
+
export const symlink = _cb(async () => { throw new Error('symlink not supported'); });
|
|
834
|
+
export const link = _cb(async () => { throw new Error('link not supported'); });
|
|
835
|
+
export const readlink = _cb(async () => { throw new Error('readlink not supported'); });
|
|
836
|
+
export const rm = _cb(async (p) => unlinkSync(p));
|
|
837
|
+
export const rmdir = _cb(async () => {});
|
|
838
|
+
|
|
839
|
+
// The promises namespace — re-export the Promise-shaped versions.
|
|
840
|
+
export const promises = {
|
|
841
|
+
readFile: readFilePromise,
|
|
842
|
+
writeFile: writeFilePromise,
|
|
843
|
+
stat: statPromise,
|
|
844
|
+
lstat: statPromise,
|
|
845
|
+
readdir: readdirPromise,
|
|
846
|
+
mkdir: mkdirPromise,
|
|
847
|
+
unlink: unlinkPromise,
|
|
848
|
+
rename: renamePromise,
|
|
849
|
+
realpath: realpathPromise,
|
|
850
|
+
access: async (p) => { if (!existsSync(p)) throw new Error('ENOENT: ' + p); },
|
|
851
|
+
appendFile: async (p, data) => { appendFileSync(p, data); },
|
|
852
|
+
chmod: async () => {},
|
|
853
|
+
chown: async () => {},
|
|
854
|
+
utimes: async () => {},
|
|
855
|
+
truncate: async () => {},
|
|
856
|
+
symlink: async () => { throw new Error('symlink not supported'); },
|
|
857
|
+
link: async () => { throw new Error('link not supported'); },
|
|
858
|
+
readlink: async () => { throw new Error('readlink not supported'); },
|
|
859
|
+
rm: async (p) => unlinkSync(p),
|
|
860
|
+
rmdir: async () => {},
|
|
861
|
+
cp: _real.promises?.cp || (async () => { throw new Error('cp not supported'); }),
|
|
862
|
+
copyFile: _real.promises?.copyFile || (async () => {}),
|
|
863
|
+
opendir: _real.promises?.opendir || (async () => { throw new Error('opendir not supported'); }),
|
|
864
|
+
mkdtemp: _real.promises?.mkdtemp || (async () => { throw new Error('mkdtemp not supported'); }),
|
|
865
|
+
open: _real.promises?.open || (async () => { throw new Error('open not supported'); }),
|
|
866
|
+
constants: _real.constants,
|
|
867
|
+
};
|
|
868
|
+
|
|
869
|
+
const _defaultExport = {
|
|
870
|
+
// Shimmed (snapshot + RPC backed)
|
|
871
|
+
readFileSync, existsSync, statSync, lstatSync, realpathSync, readdirSync,
|
|
872
|
+
writeFileSync, mkdirSync, unlinkSync, rmSync, rmdirSync, renameSync,
|
|
873
|
+
appendFileSync, accessSync, chmodSync, chownSync, utimesSync, truncateSync,
|
|
874
|
+
symlinkSync, linkSync, readlinkSync, watch, watchFile, unwatchFile,
|
|
875
|
+
readFile, writeFile, stat, lstat, readdir, mkdir, unlink, rename, realpath,
|
|
876
|
+
access, rm, rmdir, appendFile, chmod, chown, utimes, truncate, symlink,
|
|
877
|
+
link, readlink,
|
|
878
|
+
// Passthrough from workerd's node:fs (may be undefined for some — the
|
|
879
|
+
// _pickMaybe helper tolerates that).
|
|
880
|
+
constants, Stats, Dirent, Dir, ReadStream, WriteStream,
|
|
881
|
+
createReadStream, createWriteStream, opendir, opendirSync,
|
|
882
|
+
open, openSync, close, closeSync, read, readSync, write, writeSync,
|
|
883
|
+
fstat, fstatSync, fsync, fsyncSync, fdatasync, fdatasyncSync,
|
|
884
|
+
ftruncate, ftruncateSync, futimes, futimesSync, fchmod, fchmodSync,
|
|
885
|
+
fchown, fchownSync, readv, readvSync, writev, writevSync,
|
|
886
|
+
mkdtemp, mkdtempSync, cp, cpSync, copyFile, copyFileSync,
|
|
887
|
+
promises,
|
|
888
|
+
};
|
|
889
|
+
// Expose on globalThis for the __require polyfill so CJS callers
|
|
890
|
+
// that do \`require('fs')\` get the same snapshot-backed impl.
|
|
891
|
+
globalThis.__cirrusRealFsShim = _defaultExport;
|
|
892
|
+
export default _defaultExport;
|
|
893
|
+
`.trim();
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* ESM source of the fs/promises shim. Thin wrapper around the main
|
|
897
|
+
* fs shim so `import x from 'node:fs/promises'` picks up the
|
|
898
|
+
* snapshot-backed impl.
|
|
899
|
+
*
|
|
900
|
+
* Uses a RELATIVE import to ./cirrus-fs.js (not 'node:fs') because
|
|
901
|
+
* cirrus-fs-promises.js is loaded as a LOADER module alongside
|
|
902
|
+
* cirrus-fs.js — bare 'node:fs' here would route through workerd's
|
|
903
|
+
* real node:fs instead of our shim.
|
|
904
|
+
*/
|
|
905
|
+
export function generateFsPromisesShimModuleCode() {
|
|
906
|
+
return `
|
|
907
|
+
// ── fs/promises shim — generated by src/real-vite-fs-shim.ts ─────
|
|
908
|
+
import fs from './cirrus-fs.js';
|
|
909
|
+
export const readFile = fs.promises.readFile;
|
|
910
|
+
export const writeFile = fs.promises.writeFile;
|
|
911
|
+
export const stat = fs.promises.stat;
|
|
912
|
+
export const lstat = fs.promises.lstat;
|
|
913
|
+
export const readdir = fs.promises.readdir;
|
|
914
|
+
export const mkdir = fs.promises.mkdir;
|
|
915
|
+
export const unlink = fs.promises.unlink;
|
|
916
|
+
export const rename = fs.promises.rename;
|
|
917
|
+
export const realpath = fs.promises.realpath;
|
|
918
|
+
export const access = fs.promises.access;
|
|
919
|
+
export const appendFile = fs.promises.appendFile;
|
|
920
|
+
export const chmod = fs.promises.chmod;
|
|
921
|
+
export const chown = fs.promises.chown;
|
|
922
|
+
export const utimes = fs.promises.utimes;
|
|
923
|
+
export const truncate = fs.promises.truncate;
|
|
924
|
+
export const symlink = fs.promises.symlink;
|
|
925
|
+
export const link = fs.promises.link;
|
|
926
|
+
export const readlink = fs.promises.readlink;
|
|
927
|
+
export const rm = fs.promises.rm;
|
|
928
|
+
export const rmdir = fs.promises.rmdir;
|
|
929
|
+
export const cp = fs.promises.cp;
|
|
930
|
+
export const copyFile = fs.promises.copyFile;
|
|
931
|
+
export const opendir = fs.promises.opendir;
|
|
932
|
+
export const mkdtemp = fs.promises.mkdtemp;
|
|
933
|
+
export const open = fs.promises.open;
|
|
934
|
+
export const constants = fs.promises.constants;
|
|
935
|
+
export default fs.promises;
|
|
936
|
+
`.trim();
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* ESM source for synthetic.js — seeds the globalThis-backed
|
|
940
|
+
* snapshot BEFORE vite.bundle.js evaluates. Takes the output of
|
|
941
|
+
* buildFsSnapshot() plus a few hard-coded synthetic files (vite's
|
|
942
|
+
* package.json + client assets) that the Phase 0 spike already
|
|
943
|
+
* proved we need.
|
|
944
|
+
*
|
|
945
|
+
* The supervisor binding (env.SUPERVISOR) is exposed as a global
|
|
946
|
+
* via the facet entrypoint — not here, because env access requires
|
|
947
|
+
* an async boot step.
|
|
948
|
+
*/
|
|
949
|
+
export function generateSyntheticModuleCode(opts) {
|
|
950
|
+
const { viteVersion, snapshotFiles, snapshotDirs, existingPaths, rollupWasmBase64, cjsPrebuiltBundles, viteClientMjs, viteEnvMjs, } = opts;
|
|
951
|
+
const vitePkgJson = JSON.stringify({
|
|
952
|
+
name: 'vite', version: viteVersion, type: 'module',
|
|
953
|
+
engines: { node: '>=20.0.0' }, dependencies: {},
|
|
954
|
+
});
|
|
955
|
+
// Pre-populated + Vite-specific synthetics. Vite's bundle has
|
|
956
|
+
// import.meta.url = 'file:///vite.bundle.js' (set by our bundler),
|
|
957
|
+
// so its relative URL lookups resolve under /. These entries seed
|
|
958
|
+
// /package.json and /dist/client/* for Vite's self-bootstrap.
|
|
959
|
+
// When the caller provides viteClientMjs/viteEnvMjs we use the REAL
|
|
960
|
+
// runtime (~32 KB) so the browser's HMR client actually works;
|
|
961
|
+
// otherwise we fall back to tiny stubs for server-side init.
|
|
962
|
+
const viteSynthetics = {
|
|
963
|
+
'/package.json': vitePkgJson,
|
|
964
|
+
'/dist/client/index.html': '<!doctype html><html><head></head><body></body></html>',
|
|
965
|
+
'/dist/client/client.mjs': viteClientMjs ?? '// vite client stub',
|
|
966
|
+
'/dist/client/env.mjs': viteEnvMjs ?? 'export {};',
|
|
967
|
+
'/dist/client/CLIENT.mjs': viteClientMjs ?? '// vite client stub (case probe)',
|
|
968
|
+
};
|
|
969
|
+
// Merge: snapshot files take precedence (they reflect the real
|
|
970
|
+
// project), but vite synthetics fill in anything the snapshot
|
|
971
|
+
// didn't cover.
|
|
972
|
+
const allFiles = { ...viteSynthetics, ...snapshotFiles };
|
|
973
|
+
// Emit as a Map literal. Large projects can push this to ~several
|
|
974
|
+
// MB, but we're already shipping a 2.3 MB vite bundle so an extra
|
|
975
|
+
// 1–3 MB of project text is acceptable.
|
|
976
|
+
const entries = Object.entries(allFiles);
|
|
977
|
+
const body = entries
|
|
978
|
+
.map(([k, v]) => ` [${JSON.stringify(k)}, ${JSON.stringify(v)}]`)
|
|
979
|
+
.join(',\n');
|
|
980
|
+
const dirEntries = snapshotDirs.map((d) => JSON.stringify(d)).join(', ');
|
|
981
|
+
return `
|
|
982
|
+
// ── Synthetic fs seed (generated by src/real-vite-fs-shim.ts) ────
|
|
983
|
+
// Populates globalThis.__cirrusRealFs BEFORE vite.bundle.js evaluates
|
|
984
|
+
// via ESM import hoisting (this module is the first import in main.js).
|
|
985
|
+
//
|
|
986
|
+
// Also pre-imports all node:* builtins that bundled CJS modules
|
|
987
|
+
// might require() at runtime, and exposes them via a table the
|
|
988
|
+
// patched __require polyfill consults before falling back to
|
|
989
|
+
// createRequire.
|
|
990
|
+
|
|
991
|
+
import * as __n_assert from 'node:assert';
|
|
992
|
+
import * as __n_buffer from 'node:buffer';
|
|
993
|
+
import * as __n_childProcess from 'node:child_process';
|
|
994
|
+
import * as __n_crypto from 'node:crypto';
|
|
995
|
+
import * as __n_dns from 'node:dns';
|
|
996
|
+
import * as __n_events from 'node:events';
|
|
997
|
+
import * as __n_fs from 'node:fs';
|
|
998
|
+
import * as __n_fsPromises from 'node:fs/promises';
|
|
999
|
+
import * as __n_http from 'node:http';
|
|
1000
|
+
import * as __n_https from 'node:https';
|
|
1001
|
+
import * as __n_module from 'node:module';
|
|
1002
|
+
import * as __n_net from 'node:net';
|
|
1003
|
+
import * as __n_os from 'node:os';
|
|
1004
|
+
import * as __n_path from 'node:path';
|
|
1005
|
+
import * as __n_perfHooks from 'node:perf_hooks';
|
|
1006
|
+
import * as __n_process from 'node:process';
|
|
1007
|
+
import * as __n_querystring from 'node:querystring';
|
|
1008
|
+
import * as __n_readline from 'node:readline';
|
|
1009
|
+
import * as __n_stream from 'node:stream';
|
|
1010
|
+
import * as __n_string_decoder from 'node:string_decoder';
|
|
1011
|
+
import * as __n_timers from 'node:timers';
|
|
1012
|
+
import * as __n_timersPromises from 'node:timers/promises';
|
|
1013
|
+
import * as __n_tls from 'node:tls';
|
|
1014
|
+
import * as __n_tty from 'node:tty';
|
|
1015
|
+
import * as __n_url from 'node:url';
|
|
1016
|
+
import * as __n_util from 'node:util';
|
|
1017
|
+
import * as __n_zlib from 'node:zlib';
|
|
1018
|
+
import * as __n_workerThreads from 'node:worker_threads';
|
|
1019
|
+
|
|
1020
|
+
const _builtinTable = {
|
|
1021
|
+
'assert': __n_assert, 'node:assert': __n_assert,
|
|
1022
|
+
'buffer': __n_buffer, 'node:buffer': __n_buffer,
|
|
1023
|
+
'child_process': __n_childProcess, 'node:child_process': __n_childProcess,
|
|
1024
|
+
'crypto': __n_crypto, 'node:crypto': __n_crypto,
|
|
1025
|
+
'dns': __n_dns, 'node:dns': __n_dns,
|
|
1026
|
+
'events': __n_events, 'node:events': __n_events,
|
|
1027
|
+
'fs': __n_fs, 'node:fs': __n_fs,
|
|
1028
|
+
'fs/promises': __n_fsPromises, 'node:fs/promises': __n_fsPromises,
|
|
1029
|
+
'http': __n_http, 'node:http': __n_http,
|
|
1030
|
+
'https': __n_https, 'node:https': __n_https,
|
|
1031
|
+
'module': __n_module, 'node:module': __n_module,
|
|
1032
|
+
'net': __n_net, 'node:net': __n_net,
|
|
1033
|
+
'os': __n_os, 'node:os': __n_os,
|
|
1034
|
+
'path': __n_path, 'node:path': __n_path,
|
|
1035
|
+
'perf_hooks': __n_perfHooks, 'node:perf_hooks': __n_perfHooks,
|
|
1036
|
+
'process': __n_process, 'node:process': __n_process,
|
|
1037
|
+
'querystring': __n_querystring, 'node:querystring': __n_querystring,
|
|
1038
|
+
'readline': __n_readline, 'node:readline': __n_readline,
|
|
1039
|
+
'stream': __n_stream, 'node:stream': __n_stream,
|
|
1040
|
+
'string_decoder': __n_string_decoder, 'node:string_decoder': __n_string_decoder,
|
|
1041
|
+
'timers': __n_timers, 'node:timers': __n_timers,
|
|
1042
|
+
'timers/promises': __n_timersPromises, 'node:timers/promises': __n_timersPromises,
|
|
1043
|
+
'tls': __n_tls, 'node:tls': __n_tls,
|
|
1044
|
+
'tty': __n_tty, 'node:tty': __n_tty,
|
|
1045
|
+
'url': __n_url, 'node:url': __n_url,
|
|
1046
|
+
'util': __n_util, 'node:util': __n_util,
|
|
1047
|
+
'zlib': __n_zlib, 'node:zlib': __n_zlib,
|
|
1048
|
+
'worker_threads': __n_workerThreads, 'node:worker_threads': __n_workerThreads,
|
|
1049
|
+
};
|
|
1050
|
+
// Flatten \`.default\` out of namespace imports where a CJS require
|
|
1051
|
+
// caller expects a bare module export (most do — e.g. \`require('path')\`
|
|
1052
|
+
// returns the path module's default export, not a namespace).
|
|
1053
|
+
const _normalize = (ns) => (ns && ns.default !== undefined && Object.keys(ns).length <= 2) ? ns.default : ns;
|
|
1054
|
+
globalThis.__cirrusNodeBuiltinTable = {};
|
|
1055
|
+
for (const [k, v] of Object.entries(_builtinTable)) {
|
|
1056
|
+
// Pass through both the namespace AND the default-collapsed form
|
|
1057
|
+
// because the two styles have different shapes. Storing the NS
|
|
1058
|
+
// directly is safer: most callers use \`path.resolve\`, which is
|
|
1059
|
+
// on the NS as a named export AND on the default via re-export.
|
|
1060
|
+
globalThis.__cirrusNodeBuiltinTable[k] = v.default ?? v;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
// __cirrusRealUserspaceRequire: tiny VFS-backed CJS loader. Used by
|
|
1064
|
+
// the __require polyfill in vite.bundle.js and by the rewritten
|
|
1065
|
+
// dynamic-imports inside user-vite-config.js. Defined HERE (in
|
|
1066
|
+
// synthetic.js) so it's available before any other LOADER module
|
|
1067
|
+
// evaluates — essential because userspace/vitejs-plugin-react.js
|
|
1068
|
+
// and user-vite-config.js both reach for it at module-init.
|
|
1069
|
+
globalThis.__cirrusRealUserspaceRequire = function __cirrusRealUserspaceRequire(name) {
|
|
1070
|
+
const fs = globalThis.__cirrusRealFs;
|
|
1071
|
+
if (!fs) return null;
|
|
1072
|
+
// First: try the builtin table (node:*).
|
|
1073
|
+
const bt = globalThis.__cirrusNodeBuiltinTable?.[name];
|
|
1074
|
+
if (bt) return bt;
|
|
1075
|
+
// Walk snapshot for /<...>/node_modules/<name>/package.json.
|
|
1076
|
+
const pkgSuffix = '/node_modules/' + name + '/package.json';
|
|
1077
|
+
for (const [path, content] of fs.files) {
|
|
1078
|
+
if (!path.endsWith(pkgSuffix)) continue;
|
|
1079
|
+
try {
|
|
1080
|
+
const pkg = JSON.parse(content);
|
|
1081
|
+
const pkgDir = path.slice(0, -('package.json'.length));
|
|
1082
|
+
// Prefer ESM entry via exports.import.default -> module -> main
|
|
1083
|
+
let entry = null;
|
|
1084
|
+
if (pkg.exports) {
|
|
1085
|
+
const e = pkg.exports;
|
|
1086
|
+
if (typeof e === 'string') entry = e;
|
|
1087
|
+
else if (e['.']) {
|
|
1088
|
+
const d = e['.'];
|
|
1089
|
+
entry = typeof d === 'string' ? d : (d.import?.default || d.import || d.require || d.default);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
if (!entry) entry = pkg.module || pkg.main || 'index.js';
|
|
1093
|
+
if (typeof entry === 'object' && entry?.default) entry = entry.default;
|
|
1094
|
+
if (typeof entry !== 'string') continue;
|
|
1095
|
+
const entryAbs = pkgDir + entry.replace(/^\\.\\//, '');
|
|
1096
|
+
const resolvedPath = (() => {
|
|
1097
|
+
if (fs.files.has(entryAbs)) return entryAbs;
|
|
1098
|
+
for (const ext of ['.js', '.mjs', '.cjs', '.json']) {
|
|
1099
|
+
if (fs.files.has(entryAbs + ext)) return entryAbs + ext;
|
|
1100
|
+
}
|
|
1101
|
+
if (fs.files.has(entryAbs + '/index.js')) return entryAbs + '/index.js';
|
|
1102
|
+
return null;
|
|
1103
|
+
})();
|
|
1104
|
+
if (!resolvedPath) continue;
|
|
1105
|
+
const code = fs.files.get(resolvedPath);
|
|
1106
|
+
const mod = { exports: {} };
|
|
1107
|
+
const moduleDir = resolvedPath.slice(0, resolvedPath.lastIndexOf('/'));
|
|
1108
|
+
const nestedRequire = (n) => {
|
|
1109
|
+
const b = globalThis.__cirrusNodeBuiltinTable?.[n];
|
|
1110
|
+
if (b) return b;
|
|
1111
|
+
if (n.startsWith('./') || n.startsWith('../')) {
|
|
1112
|
+
// Relative require — resolve against moduleDir.
|
|
1113
|
+
const segs = (moduleDir + '/' + n).split('/').reduce((acc, s) => {
|
|
1114
|
+
if (s === '..') acc.pop();
|
|
1115
|
+
else if (s && s !== '.') acc.push(s);
|
|
1116
|
+
return acc;
|
|
1117
|
+
}, []);
|
|
1118
|
+
const relAbs = '/' + segs.join('/');
|
|
1119
|
+
for (const ext of ['', '.js', '.mjs', '.cjs', '.json']) {
|
|
1120
|
+
if (fs.files.has(relAbs + ext)) {
|
|
1121
|
+
const c = fs.files.get(relAbs + ext);
|
|
1122
|
+
if ((relAbs + ext).endsWith('.json')) return JSON.parse(c);
|
|
1123
|
+
const subMod = { exports: {} };
|
|
1124
|
+
const subWrapped = new Function('module', 'exports', 'require', '__filename', '__dirname', c);
|
|
1125
|
+
try { subWrapped(subMod, subMod.exports, nestedRequire, relAbs + ext, relAbs); }
|
|
1126
|
+
catch (e) { throw new Error('nested require failed for ' + n + ' in ' + name + ': ' + (e?.message || e)); }
|
|
1127
|
+
return subMod.exports;
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
throw new Error('relative require not found: ' + n + ' from ' + moduleDir);
|
|
1131
|
+
}
|
|
1132
|
+
// Nested package require.
|
|
1133
|
+
const r = __cirrusRealUserspaceRequire(n);
|
|
1134
|
+
if (r) return r;
|
|
1135
|
+
throw new Error('nested userspace require failed: ' + n);
|
|
1136
|
+
};
|
|
1137
|
+
const wrapped = new Function('module', 'exports', 'require', '__filename', '__dirname', code);
|
|
1138
|
+
try {
|
|
1139
|
+
wrapped(mod, mod.exports, nestedRequire, resolvedPath, moduleDir);
|
|
1140
|
+
} catch (e) {
|
|
1141
|
+
throw new Error('userspace require failed for ' + name + ': ' + (e?.message || e));
|
|
1142
|
+
}
|
|
1143
|
+
return mod.exports;
|
|
1144
|
+
} catch (e) {
|
|
1145
|
+
if (e instanceof SyntaxError || /userspace require failed/.test(e?.message || '')) throw e;
|
|
1146
|
+
// Malformed package.json or similar — try next match.
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
return null;
|
|
1150
|
+
};
|
|
1151
|
+
|
|
1152
|
+
// Note: we deliberately do NOT ship a runtime CJS→ESM transform.
|
|
1153
|
+
// workerd forbids \`new Function(src)\` / \`eval()\` outside startup
|
|
1154
|
+
// scope, so the common "evaluate CJS, emit ESM stub" trick doesnt
|
|
1155
|
+
// work. Instead we pre-bundle the common CJS packages at build
|
|
1156
|
+
// time (src/cirrus-npm-cjs.generated.ts, emitted by
|
|
1157
|
+
// scripts/bundle-npm-cjs.mjs) and ship them as an intercept
|
|
1158
|
+
// table that the vite:esbuild transform patch checks against.
|
|
1159
|
+
|
|
1160
|
+
import { createRequire as __cirrusCreateRequire } from 'node:module';
|
|
1161
|
+
// Wrap workerd's createRequire so .resolve() works via a VFS walk.
|
|
1162
|
+
// plugin-react and other packages use \`require.resolve(pkg)\` to
|
|
1163
|
+
// locate their optional deps on disk; workerd only implements the
|
|
1164
|
+
// raw require() but not .resolve(). The wrapper walks the snapshot
|
|
1165
|
+
// for /<...>/node_modules/<pkg>/package.json and returns its path.
|
|
1166
|
+
globalThis.__cirrusNodeCreateRequire = function(parentUrl) {
|
|
1167
|
+
const inner = __cirrusCreateRequire(parentUrl);
|
|
1168
|
+
const wrapped = function(name) {
|
|
1169
|
+
// Try the builtin table first — same as __require shim.
|
|
1170
|
+
const bt = globalThis.__cirrusNodeBuiltinTable?.[name];
|
|
1171
|
+
if (bt) return bt;
|
|
1172
|
+
const uspace = globalThis.__cirrusRealUserspaceRequire?.(name);
|
|
1173
|
+
if (uspace) return uspace;
|
|
1174
|
+
return inner(name);
|
|
1175
|
+
};
|
|
1176
|
+
wrapped.resolve = function(name, _opts) {
|
|
1177
|
+
// VFS walk. name can be "pkg" or "pkg/subpath" or an absolute path.
|
|
1178
|
+
const fs = globalThis.__cirrusRealFs;
|
|
1179
|
+
if (fs && typeof name === 'string') {
|
|
1180
|
+
if (name.startsWith('/')) {
|
|
1181
|
+
// Absolute path request.
|
|
1182
|
+
if (fs.files.has(name)) return name;
|
|
1183
|
+
}
|
|
1184
|
+
// Package request.
|
|
1185
|
+
const parts = name.split('/');
|
|
1186
|
+
const pkgName = parts[0].startsWith('@') ? parts[0] + '/' + parts[1] : parts[0];
|
|
1187
|
+
const subpath = name.slice(pkgName.length + 1);
|
|
1188
|
+
// Walk all file paths looking for .../node_modules/<pkgName>/package.json
|
|
1189
|
+
const pkgSuffix = '/node_modules/' + pkgName + '/package.json';
|
|
1190
|
+
for (const p of fs.files.keys()) {
|
|
1191
|
+
if (p.endsWith(pkgSuffix)) {
|
|
1192
|
+
const dir = p.slice(0, -('package.json'.length));
|
|
1193
|
+
if (!subpath) return p;
|
|
1194
|
+
const sub = dir + subpath;
|
|
1195
|
+
if (fs.files.has(sub)) return sub;
|
|
1196
|
+
// Try with extension fallbacks.
|
|
1197
|
+
for (const ext of ['.js', '.mjs', '.cjs', '.json']) {
|
|
1198
|
+
if (fs.files.has(sub + ext)) return sub + ext;
|
|
1199
|
+
}
|
|
1200
|
+
if (fs.files.has(sub + '/index.js')) return sub + '/index.js';
|
|
1201
|
+
// Give up — but still return a plausible path; caller may
|
|
1202
|
+
// readFileSync on it and fail with our clearer error.
|
|
1203
|
+
return sub;
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
// Fallback: try workerds inner.resolve (likely throws).
|
|
1208
|
+
try { return inner.resolve ? inner.resolve(name) : name; }
|
|
1209
|
+
catch { return name; }
|
|
1210
|
+
};
|
|
1211
|
+
wrapped.cache = inner.cache || {};
|
|
1212
|
+
wrapped.extensions = inner.extensions || {};
|
|
1213
|
+
wrapped.main = inner.main || undefined;
|
|
1214
|
+
return wrapped;
|
|
1215
|
+
};
|
|
1216
|
+
|
|
1217
|
+
globalThis.__cirrusRealFs = {
|
|
1218
|
+
files: new Map([
|
|
1219
|
+
${body}
|
|
1220
|
+
]),
|
|
1221
|
+
dirs: new Set([${dirEntries}]),
|
|
1222
|
+
existingPaths: new Set(${existingPaths && existingPaths.length > 0
|
|
1223
|
+
? `[\n${existingPaths.map(p => ` ${JSON.stringify(p)}`).join(',\n')}\n]`
|
|
1224
|
+
: '[]'}),
|
|
1225
|
+
};
|
|
1226
|
+
globalThis.__cirrusRealFsStats = {
|
|
1227
|
+
fileCount: ${entries.length},
|
|
1228
|
+
dirCount: ${snapshotDirs.length},
|
|
1229
|
+
pathIndexCount: ${existingPaths ? existingPaths.length : 0},
|
|
1230
|
+
};
|
|
1231
|
+
|
|
1232
|
+
${rollupWasmBase64 ? `
|
|
1233
|
+
const __rollupWasmBase64 = ${JSON.stringify(rollupWasmBase64)};
|
|
1234
|
+
let __rollupWasmBytes = null;
|
|
1235
|
+
Object.defineProperty(globalThis.__cirrusRealFs, 'getWasmBytes', {
|
|
1236
|
+
value: () => {
|
|
1237
|
+
if (!__rollupWasmBytes) {
|
|
1238
|
+
const bin = atob(__rollupWasmBase64);
|
|
1239
|
+
const u8 = new Uint8Array(bin.length);
|
|
1240
|
+
for (let i = 0; i < bin.length; i++) u8[i] = bin.charCodeAt(i);
|
|
1241
|
+
__rollupWasmBytes = u8;
|
|
1242
|
+
}
|
|
1243
|
+
return __rollupWasmBytes;
|
|
1244
|
+
},
|
|
1245
|
+
});
|
|
1246
|
+
` : ''}
|
|
1247
|
+
|
|
1248
|
+
${cjsPrebuiltBundles && Object.keys(cjsPrebuiltBundles).length > 0 ? `
|
|
1249
|
+
// ── Pre-built CJS→ESM bundles ──────────────────────────────────
|
|
1250
|
+
// workerd forbids runtime new Function/eval at request-handler
|
|
1251
|
+
// time, so we cant transform CJS inside the facet. Instead we
|
|
1252
|
+
// ship the common React-ecosystem CJS packages as pre-built ESM
|
|
1253
|
+
// artifacts (src/cirrus-npm-cjs.generated.ts, bundled at
|
|
1254
|
+
// facet-build time by scripts/bundle-npm-cjs.mjs). The
|
|
1255
|
+
// vite:esbuild transform patch calls __cirrusNpmCjsMap(id) and,
|
|
1256
|
+
// when a match is found, returns the pre-built ESM code instead
|
|
1257
|
+
// of the CJS source in node_modules.
|
|
1258
|
+
const __cirrusNpmCjsTable = new Map([
|
|
1259
|
+
${Object.entries(cjsPrebuiltBundles).map(([pathPattern, code]) => ` [${JSON.stringify(pathPattern)}, ${JSON.stringify(code)}]`).join(',\n')}
|
|
1260
|
+
]);
|
|
1261
|
+
|
|
1262
|
+
/**
|
|
1263
|
+
* Match an fs path like /home/user/app/node_modules/react/index.js
|
|
1264
|
+
* against the pre-built bundle table. The keys in the table are
|
|
1265
|
+
* SUFFIXES — e.g. "/node_modules/react/index.js" — so a project
|
|
1266
|
+
* at any path resolves correctly.
|
|
1267
|
+
*/
|
|
1268
|
+
globalThis.__cirrusNpmCjsMap = function(id) {
|
|
1269
|
+
if (typeof id !== 'string') return null;
|
|
1270
|
+
// Strip query strings (Vite appends ?v=... for cache-busting).
|
|
1271
|
+
const cleanId = id.replace(/\\?.*$/, '');
|
|
1272
|
+
for (const [suffix, code] of __cirrusNpmCjsTable) {
|
|
1273
|
+
if (cleanId.endsWith(suffix)) return code;
|
|
1274
|
+
}
|
|
1275
|
+
return null;
|
|
1276
|
+
};
|
|
1277
|
+
` : ''}
|
|
1278
|
+
`.trim();
|
|
1279
|
+
}
|