@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,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* real-vite-bundle.generated.ts — AUTO-GENERATED by scripts/bundle-real-vite.mjs
|
|
3
|
+
* DO NOT EDIT.
|
|
4
|
+
*
|
|
5
|
+
* Bundled Vite 6.4.2 with native-binding stubs (rolldown,
|
|
6
|
+
* lightningcss, etc.). Consumed by src/cirrus-real.ts at facet spawn time.
|
|
7
|
+
*
|
|
8
|
+
* [sdk-phase-1] The large strings (REAL_VITE_BUNDLE, ROLLUP_WASM_BASE64)
|
|
9
|
+
* now ship via the ASSETS binding rather than inline. Use the async
|
|
10
|
+
* getters below. Constants + browser-runtime mjs files remain inline
|
|
11
|
+
* since they're small enough to not warrant a network round-trip.
|
|
12
|
+
*/
|
|
13
|
+
import { loadAssetText, loadAssetBytes } from './runtime/assets-loader.js';
|
|
14
|
+
export const REAL_VITE_VERSION = "6.4.2";
|
|
15
|
+
/** Asset path for the bundled Vite source. Use {@link getRealViteBundle}. */
|
|
16
|
+
export const REAL_VITE_BUNDLE_PATH = "/_assets/real-vite-bundle.js";
|
|
17
|
+
/** Asset path for the rollup wasm bytes. Use {@link getRollupWasmBase64}. */
|
|
18
|
+
export const ROLLUP_WASM_PATH = "/_assets/rollup.wasm";
|
|
19
|
+
/**
|
|
20
|
+
* Fetch the bundled Vite JS from the ASSETS binding. Cached per-isolate.
|
|
21
|
+
*
|
|
22
|
+
* @param env Object exposing the `ASSETS` binding (Fetcher).
|
|
23
|
+
* @returns The Vite bundle as a UTF-8 string.
|
|
24
|
+
* @throws {NimbusAssetLoadError} when the binding is missing or fetch fails.
|
|
25
|
+
*/
|
|
26
|
+
export function getRealViteBundle(env) {
|
|
27
|
+
return loadAssetText(env.ASSETS, REAL_VITE_BUNDLE_PATH);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Fetch the rollup wasm bytes + base64-encode for the synthetic-fs
|
|
31
|
+
* pre-seed. Cached per-isolate; the base64 string ends up the same on
|
|
32
|
+
* every call.
|
|
33
|
+
*
|
|
34
|
+
* @returns base64-encoded rollup wasm bytes.
|
|
35
|
+
*/
|
|
36
|
+
export async function getRollupWasmBase64(env) {
|
|
37
|
+
const bytes = await loadAssetBytes(env.ASSETS, ROLLUP_WASM_PATH);
|
|
38
|
+
// btoa(String.fromCharCode(...bytes)) blows the stack on 1 MB inputs.
|
|
39
|
+
// Build the binary string in 8 KiB chunks.
|
|
40
|
+
let binary = '';
|
|
41
|
+
const CHUNK = 8192;
|
|
42
|
+
for (let i = 0; i < bytes.length; i += CHUNK) {
|
|
43
|
+
binary += String.fromCharCode.apply(null, bytes.subarray(i, Math.min(i + CHUNK, bytes.length)));
|
|
44
|
+
}
|
|
45
|
+
return btoa(binary);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Vite's browser-side HMR runtime. Served to the browser at
|
|
49
|
+
* /@vite/client and /@vite/env during dev. Unlike the server
|
|
50
|
+
* bundle, these are tiny ESM files that run in-page — keep inline.
|
|
51
|
+
*/
|
|
52
|
+
export const VITE_CLIENT_MJS = "import '@vite/env';\n\nclass HMRContext {\n constructor(hmrClient, ownerPath) {\n this.hmrClient = hmrClient;\n this.ownerPath = ownerPath;\n if (!hmrClient.dataMap.has(ownerPath)) {\n hmrClient.dataMap.set(ownerPath, {});\n }\n const mod = hmrClient.hotModulesMap.get(ownerPath);\n if (mod) {\n mod.callbacks = [];\n }\n const staleListeners = hmrClient.ctxToListenersMap.get(ownerPath);\n if (staleListeners) {\n for (const [event, staleFns] of staleListeners) {\n const listeners = hmrClient.customListenersMap.get(event);\n if (listeners) {\n hmrClient.customListenersMap.set(\n event,\n listeners.filter((l) => !staleFns.includes(l))\n );\n }\n }\n }\n this.newListeners = /* @__PURE__ */ new Map();\n hmrClient.ctxToListenersMap.set(ownerPath, this.newListeners);\n }\n get data() {\n return this.hmrClient.dataMap.get(this.ownerPath);\n }\n accept(deps, callback) {\n if (typeof deps === \"function\" || !deps) {\n this.acceptDeps([this.ownerPath], ([mod]) => deps?.(mod));\n } else if (typeof deps === \"string\") {\n this.acceptDeps([deps], ([mod]) => callback?.(mod));\n } else if (Array.isArray(deps)) {\n this.acceptDeps(deps, callback);\n } else {\n throw new Error(`invalid hot.accept() usage.`);\n }\n }\n // export names (first arg) are irrelevant on the client side, they're\n // extracted in the server for propagation\n acceptExports(_, callback) {\n this.acceptDeps([this.ownerPath], ([mod]) => callback?.(mod));\n }\n dispose(cb) {\n this.hmrClient.disposeMap.set(this.ownerPath, cb);\n }\n prune(cb) {\n this.hmrClient.pruneMap.set(this.ownerPath, cb);\n }\n // Kept for backward compatibility (#11036)\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n decline() {\n }\n invalidate(message) {\n const firstInvalidatedBy = this.hmrClient.currentFirstInvalidatedBy ?? this.ownerPath;\n this.hmrClient.notifyListeners(\"vite:invalidate\", {\n path: this.ownerPath,\n message,\n firstInvalidatedBy\n });\n this.send(\"vite:invalidate\", {\n path: this.ownerPath,\n message,\n firstInvalidatedBy\n });\n this.hmrClient.logger.debug(\n `invalidate ${this.ownerPath}${message ? `: ${message}` : \"\"}`\n );\n }\n on(event, cb) {\n const addToMap = (map) => {\n const existing = map.get(event) || [];\n existing.push(cb);\n map.set(event, existing);\n };\n addToMap(this.hmrClient.customListenersMap);\n addToMap(this.newListeners);\n }\n off(event, cb) {\n const removeFromMap = (map) => {\n const existing = map.get(event);\n if (existing === void 0) {\n return;\n }\n const pruned = existing.filter((l) => l !== cb);\n if (pruned.length === 0) {\n map.delete(event);\n return;\n }\n map.set(event, pruned);\n };\n removeFromMap(this.hmrClient.customListenersMap);\n removeFromMap(this.newListeners);\n }\n send(event, data) {\n this.hmrClient.send({ type: \"custom\", event, data });\n }\n acceptDeps(deps, callback = () => {\n }) {\n const mod = this.hmrClient.hotModulesMap.get(this.ownerPath) || {\n id: this.ownerPath,\n callbacks: []\n };\n mod.callbacks.push({\n deps,\n fn: callback\n });\n this.hmrClient.hotModulesMap.set(this.ownerPath, mod);\n }\n}\nclass HMRClient {\n constructor(logger, transport, importUpdatedModule) {\n this.logger = logger;\n this.transport = transport;\n this.importUpdatedModule = importUpdatedModule;\n this.hotModulesMap = /* @__PURE__ */ new Map();\n this.disposeMap = /* @__PURE__ */ new Map();\n this.pruneMap = /* @__PURE__ */ new Map();\n this.dataMap = /* @__PURE__ */ new Map();\n this.customListenersMap = /* @__PURE__ */ new Map();\n this.ctxToListenersMap = /* @__PURE__ */ new Map();\n this.updateQueue = [];\n this.pendingUpdateQueue = false;\n }\n async notifyListeners(event, data) {\n const cbs = this.customListenersMap.get(event);\n if (cbs) {\n await Promise.allSettled(cbs.map((cb) => cb(data)));\n }\n }\n send(payload) {\n this.transport.send(payload).catch((err) => {\n this.logger.error(err);\n });\n }\n clear() {\n this.hotModulesMap.clear();\n this.disposeMap.clear();\n this.pruneMap.clear();\n this.dataMap.clear();\n this.customListenersMap.clear();\n this.ctxToListenersMap.clear();\n }\n // After an HMR update, some modules are no longer imported on the page\n // but they may have left behind side effects that need to be cleaned up\n // (e.g. style injections)\n async prunePaths(paths) {\n await Promise.all(\n paths.map((path) => {\n const disposer = this.disposeMap.get(path);\n if (disposer) return disposer(this.dataMap.get(path));\n })\n );\n paths.forEach((path) => {\n const fn = this.pruneMap.get(path);\n if (fn) {\n fn(this.dataMap.get(path));\n }\n });\n }\n warnFailedUpdate(err, path) {\n if (!(err instanceof Error) || !err.message.includes(\"fetch\")) {\n this.logger.error(err);\n }\n this.logger.error(\n `Failed to reload ${path}. This could be due to syntax errors or importing non-existent modules. (see errors above)`\n );\n }\n /**\n * buffer multiple hot updates triggered by the same src change\n * so that they are invoked in the same order they were sent.\n * (otherwise the order may be inconsistent because of the http request round trip)\n */\n async queueUpdate(payload) {\n this.updateQueue.push(this.fetchUpdate(payload));\n if (!this.pendingUpdateQueue) {\n this.pendingUpdateQueue = true;\n await Promise.resolve();\n this.pendingUpdateQueue = false;\n const loading = [...this.updateQueue];\n this.updateQueue = [];\n (await Promise.all(loading)).forEach((fn) => fn && fn());\n }\n }\n async fetchUpdate(update) {\n const { path, acceptedPath, firstInvalidatedBy } = update;\n const mod = this.hotModulesMap.get(path);\n if (!mod) {\n return;\n }\n let fetchedModule;\n const isSelfUpdate = path === acceptedPath;\n const qualifiedCallbacks = mod.callbacks.filter(\n ({ deps }) => deps.includes(acceptedPath)\n );\n if (isSelfUpdate || qualifiedCallbacks.length > 0) {\n const disposer = this.disposeMap.get(acceptedPath);\n if (disposer) await disposer(this.dataMap.get(acceptedPath));\n try {\n fetchedModule = await this.importUpdatedModule(update);\n } catch (e) {\n this.warnFailedUpdate(e, acceptedPath);\n }\n }\n return () => {\n try {\n this.currentFirstInvalidatedBy = firstInvalidatedBy;\n for (const { deps, fn } of qualifiedCallbacks) {\n fn(\n deps.map(\n (dep) => dep === acceptedPath ? fetchedModule : void 0\n )\n );\n }\n const loggedPath = isSelfUpdate ? path : `${acceptedPath} via ${path}`;\n this.logger.debug(`hot updated: ${loggedPath}`);\n } finally {\n this.currentFirstInvalidatedBy = void 0;\n }\n };\n }\n}\n\n/* @ts-self-types=\"./index.d.ts\" */\nlet urlAlphabet =\n 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict';\nlet nanoid = (size = 21) => {\n let id = '';\n let i = size | 0;\n while (i--) {\n id += urlAlphabet[(Math.random() * 64) | 0];\n }\n return id\n};\n\ntypeof process !== \"undefined\" && process.platform === \"win32\";\nfunction promiseWithResolvers() {\n let resolve;\n let reject;\n const promise = new Promise((_resolve, _reject) => {\n resolve = _resolve;\n reject = _reject;\n });\n return { promise, resolve, reject };\n}\n\nfunction reviveInvokeError(e) {\n const error = new Error(e.message || \"Unknown invoke error\");\n Object.assign(error, e, {\n // pass the whole error instead of just the stacktrace\n // so that it gets formatted nicely with console.log\n runnerError: new Error(\"RunnerError\")\n });\n return error;\n}\nconst createInvokeableTransport = (transport) => {\n if (transport.invoke) {\n return {\n ...transport,\n async invoke(name, data) {\n const result = await transport.invoke({\n type: \"custom\",\n event: \"vite:invoke\",\n data: {\n id: \"send\",\n name,\n data\n }\n });\n if (\"error\" in result) {\n throw reviveInvokeError(result.error);\n }\n return result.result;\n }\n };\n }\n if (!transport.send || !transport.connect) {\n throw new Error(\n \"transport must implement send and connect when invoke is not implemented\"\n );\n }\n const rpcPromises = /* @__PURE__ */ new Map();\n return {\n ...transport,\n connect({ onMessage, onDisconnection }) {\n return transport.connect({\n onMessage(payload) {\n if (payload.type === \"custom\" && payload.event === \"vite:invoke\") {\n const data = payload.data;\n if (data.id.startsWith(\"response:\")) {\n const invokeId = data.id.slice(\"response:\".length);\n const promise = rpcPromises.get(invokeId);\n if (!promise) return;\n if (promise.timeoutId) clearTimeout(promise.timeoutId);\n rpcPromises.delete(invokeId);\n const { error, result } = data.data;\n if (error) {\n promise.reject(error);\n } else {\n promise.resolve(result);\n }\n return;\n }\n }\n onMessage(payload);\n },\n onDisconnection\n });\n },\n disconnect() {\n rpcPromises.forEach((promise) => {\n promise.reject(\n new Error(\n `transport was disconnected, cannot call ${JSON.stringify(promise.name)}`\n )\n );\n });\n rpcPromises.clear();\n return transport.disconnect?.();\n },\n send(data) {\n return transport.send(data);\n },\n async invoke(name, data) {\n const promiseId = nanoid();\n const wrappedData = {\n type: \"custom\",\n event: \"vite:invoke\",\n data: {\n name,\n id: `send:${promiseId}`,\n data\n }\n };\n const sendPromise = transport.send(wrappedData);\n const { promise, resolve, reject } = promiseWithResolvers();\n const timeout = transport.timeout ?? 6e4;\n let timeoutId;\n if (timeout > 0) {\n timeoutId = setTimeout(() => {\n rpcPromises.delete(promiseId);\n reject(\n new Error(\n `transport invoke timed out after ${timeout}ms (data: ${JSON.stringify(wrappedData)})`\n )\n );\n }, timeout);\n timeoutId?.unref?.();\n }\n rpcPromises.set(promiseId, { resolve, reject, name, timeoutId });\n if (sendPromise) {\n sendPromise.catch((err) => {\n clearTimeout(timeoutId);\n rpcPromises.delete(promiseId);\n reject(err);\n });\n }\n try {\n return await promise;\n } catch (err) {\n throw reviveInvokeError(err);\n }\n }\n };\n};\nconst normalizeModuleRunnerTransport = (transport) => {\n const invokeableTransport = createInvokeableTransport(transport);\n let isConnected = !invokeableTransport.connect;\n let connectingPromise;\n return {\n ...transport,\n ...invokeableTransport.connect ? {\n async connect(onMessage) {\n if (isConnected) return;\n if (connectingPromise) {\n await connectingPromise;\n return;\n }\n const maybePromise = invokeableTransport.connect({\n onMessage: onMessage ?? (() => {\n }),\n onDisconnection() {\n isConnected = false;\n }\n });\n if (maybePromise) {\n connectingPromise = maybePromise;\n await connectingPromise;\n connectingPromise = void 0;\n }\n isConnected = true;\n }\n } : {},\n ...invokeableTransport.disconnect ? {\n async disconnect() {\n if (!isConnected) return;\n if (connectingPromise) {\n await connectingPromise;\n }\n isConnected = false;\n await invokeableTransport.disconnect();\n }\n } : {},\n async send(data) {\n if (!invokeableTransport.send) return;\n if (!isConnected) {\n if (connectingPromise) {\n await connectingPromise;\n } else {\n throw new Error(\"send was called before connect\");\n }\n }\n await invokeableTransport.send(data);\n },\n async invoke(name, data) {\n if (!isConnected) {\n if (connectingPromise) {\n await connectingPromise;\n } else {\n throw new Error(\"invoke was called before connect\");\n }\n }\n return invokeableTransport.invoke(name, data);\n }\n };\n};\nconst createWebSocketModuleRunnerTransport = (options) => {\n const pingInterval = options.pingInterval ?? 3e4;\n let ws;\n let pingIntervalId;\n return {\n async connect({ onMessage, onDisconnection }) {\n const socket = options.createConnection();\n socket.addEventListener(\"message\", async ({ data }) => {\n onMessage(JSON.parse(data));\n });\n let isOpened = socket.readyState === socket.OPEN;\n if (!isOpened) {\n await new Promise((resolve, reject) => {\n socket.addEventListener(\n \"open\",\n () => {\n isOpened = true;\n resolve();\n },\n { once: true }\n );\n socket.addEventListener(\"close\", async () => {\n if (!isOpened) {\n reject(new Error(\"WebSocket closed without opened.\"));\n return;\n }\n onMessage({\n type: \"custom\",\n event: \"vite:ws:disconnect\",\n data: { webSocket: socket }\n });\n onDisconnection();\n });\n });\n }\n onMessage({\n type: \"custom\",\n event: \"vite:ws:connect\",\n data: { webSocket: socket }\n });\n ws = socket;\n pingIntervalId = setInterval(() => {\n if (socket.readyState === socket.OPEN) {\n socket.send(JSON.stringify({ type: \"ping\" }));\n }\n }, pingInterval);\n },\n disconnect() {\n clearInterval(pingIntervalId);\n ws?.close();\n },\n send(data) {\n ws.send(JSON.stringify(data));\n }\n };\n};\n\nfunction createHMRHandler(handler) {\n const queue = new Queue();\n return (payload) => queue.enqueue(() => handler(payload));\n}\nclass Queue {\n constructor() {\n this.queue = [];\n this.pending = false;\n }\n enqueue(promise) {\n return new Promise((resolve, reject) => {\n this.queue.push({\n promise,\n resolve,\n reject\n });\n this.dequeue();\n });\n }\n dequeue() {\n if (this.pending) {\n return false;\n }\n const item = this.queue.shift();\n if (!item) {\n return false;\n }\n this.pending = true;\n item.promise().then(item.resolve).catch(item.reject).finally(() => {\n this.pending = false;\n this.dequeue();\n });\n return true;\n }\n}\n\nconst hmrConfigName = __HMR_CONFIG_NAME__;\nconst base$1 = __BASE__ || \"/\";\nfunction h(e, attrs = {}, ...children) {\n const elem = document.createElement(e);\n for (const [k, v] of Object.entries(attrs)) {\n elem.setAttribute(k, v);\n }\n elem.append(...children);\n return elem;\n}\nconst templateStyle = (\n /*css*/\n `\n:host {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 99999;\n --monospace: 'SFMono-Regular', Consolas,\n 'Liberation Mono', Menlo, Courier, monospace;\n --red: #ff5555;\n --yellow: #e2aa53;\n --purple: #cfa4ff;\n --cyan: #2dd9da;\n --dim: #c9c9c9;\n\n --window-background: #181818;\n --window-color: #d8d8d8;\n}\n\n.backdrop {\n position: fixed;\n z-index: 99999;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n overflow-y: scroll;\n margin: 0;\n background: rgba(0, 0, 0, 0.66);\n}\n\n.window {\n font-family: var(--monospace);\n line-height: 1.5;\n max-width: 80vw;\n color: var(--window-color);\n box-sizing: border-box;\n margin: 30px auto;\n padding: 2.5vh 4vw;\n position: relative;\n background: var(--window-background);\n border-radius: 6px 6px 8px 8px;\n box-shadow: 0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22);\n overflow: hidden;\n border-top: 8px solid var(--red);\n direction: ltr;\n text-align: left;\n}\n\npre {\n font-family: var(--monospace);\n font-size: 16px;\n margin-top: 0;\n margin-bottom: 1em;\n overflow-x: scroll;\n scrollbar-width: none;\n}\n\npre::-webkit-scrollbar {\n display: none;\n}\n\npre.frame::-webkit-scrollbar {\n display: block;\n height: 5px;\n}\n\npre.frame::-webkit-scrollbar-thumb {\n background: #999;\n border-radius: 5px;\n}\n\npre.frame {\n scrollbar-width: thin;\n}\n\n.message {\n line-height: 1.3;\n font-weight: 600;\n white-space: pre-wrap;\n}\n\n.message-body {\n color: var(--red);\n}\n\n.plugin {\n color: var(--purple);\n}\n\n.file {\n color: var(--cyan);\n margin-bottom: 0;\n white-space: pre-wrap;\n word-break: break-all;\n}\n\n.frame {\n color: var(--yellow);\n}\n\n.stack {\n font-size: 13px;\n color: var(--dim);\n}\n\n.tip {\n font-size: 13px;\n color: #999;\n border-top: 1px dotted #999;\n padding-top: 13px;\n line-height: 1.8;\n}\n\ncode {\n font-size: 13px;\n font-family: var(--monospace);\n color: var(--yellow);\n}\n\n.file-link {\n text-decoration: underline;\n cursor: pointer;\n}\n\nkbd {\n line-height: 1.5;\n font-family: ui-monospace, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 0.75rem;\n font-weight: 700;\n background-color: rgb(38, 40, 44);\n color: rgb(166, 167, 171);\n padding: 0.15rem 0.3rem;\n border-radius: 0.25rem;\n border-width: 0.0625rem 0.0625rem 0.1875rem;\n border-style: solid;\n border-color: rgb(54, 57, 64);\n border-image: initial;\n}\n`\n);\nconst createTemplate = () => h(\n \"div\",\n { class: \"backdrop\", part: \"backdrop\" },\n h(\n \"div\",\n { class: \"window\", part: \"window\" },\n h(\n \"pre\",\n { class: \"message\", part: \"message\" },\n h(\"span\", { class: \"plugin\", part: \"plugin\" }),\n h(\"span\", { class: \"message-body\", part: \"message-body\" })\n ),\n h(\"pre\", { class: \"file\", part: \"file\" }),\n h(\"pre\", { class: \"frame\", part: \"frame\" }),\n h(\"pre\", { class: \"stack\", part: \"stack\" }),\n h(\n \"div\",\n { class: \"tip\", part: \"tip\" },\n \"Click outside, press \",\n h(\"kbd\", {}, \"Esc\"),\n \" key, or fix the code to dismiss.\",\n h(\"br\"),\n \"You can also disable this overlay by setting \",\n h(\"code\", { part: \"config-option-name\" }, \"server.hmr.overlay\"),\n \" to \",\n h(\"code\", { part: \"config-option-value\" }, \"false\"),\n \" in \",\n h(\"code\", { part: \"config-file-name\" }, hmrConfigName),\n \".\"\n )\n ),\n h(\"style\", {}, templateStyle)\n);\nconst fileRE = /(?:[a-zA-Z]:\\\\|\\/).*?:\\d+:\\d+/g;\nconst codeframeRE = /^(?:>?\\s*\\d+\\s+\\|.*|\\s+\\|\\s*\\^.*)\\r?\\n/gm;\nconst { HTMLElement = class {\n} } = globalThis;\nclass ErrorOverlay extends HTMLElement {\n constructor(err, links = true) {\n super();\n this.root = this.attachShadow({ mode: \"open\" });\n this.root.appendChild(createTemplate());\n codeframeRE.lastIndex = 0;\n const hasFrame = err.frame && codeframeRE.test(err.frame);\n const message = hasFrame ? err.message.replace(codeframeRE, \"\") : err.message;\n if (err.plugin) {\n this.text(\".plugin\", `[plugin:${err.plugin}] `);\n }\n this.text(\".message-body\", message.trim());\n const [file] = (err.loc?.file || err.id || \"unknown file\").split(`?`);\n if (err.loc) {\n this.text(\".file\", `${file}:${err.loc.line}:${err.loc.column}`, links);\n } else if (err.id) {\n this.text(\".file\", file);\n }\n if (hasFrame) {\n this.text(\".frame\", err.frame.trim());\n }\n this.text(\".stack\", err.stack, links);\n this.root.querySelector(\".window\").addEventListener(\"click\", (e) => {\n e.stopPropagation();\n });\n this.addEventListener(\"click\", () => {\n this.close();\n });\n this.closeOnEsc = (e) => {\n if (e.key === \"Escape\" || e.code === \"Escape\") {\n this.close();\n }\n };\n document.addEventListener(\"keydown\", this.closeOnEsc);\n }\n text(selector, text, linkFiles = false) {\n const el = this.root.querySelector(selector);\n if (!linkFiles) {\n el.textContent = text;\n } else {\n let curIndex = 0;\n let match;\n fileRE.lastIndex = 0;\n while (match = fileRE.exec(text)) {\n const { 0: file, index } = match;\n const frag = text.slice(curIndex, index);\n el.appendChild(document.createTextNode(frag));\n const link = document.createElement(\"a\");\n link.textContent = file;\n link.className = \"file-link\";\n link.onclick = () => {\n fetch(\n new URL(\n `${base$1}__open-in-editor?file=${encodeURIComponent(file)}`,\n import.meta.url\n )\n );\n };\n el.appendChild(link);\n curIndex += frag.length + file.length;\n }\n }\n }\n close() {\n this.parentNode?.removeChild(this);\n document.removeEventListener(\"keydown\", this.closeOnEsc);\n }\n}\nconst overlayId = \"vite-error-overlay\";\nconst { customElements } = globalThis;\nif (customElements && !customElements.get(overlayId)) {\n customElements.define(overlayId, ErrorOverlay);\n}\n\nconsole.debug(\"[vite] connecting...\");\nconst importMetaUrl = new URL(import.meta.url);\nconst serverHost = __SERVER_HOST__;\nconst socketProtocol = __HMR_PROTOCOL__ || (importMetaUrl.protocol === \"https:\" ? \"wss\" : \"ws\");\nconst hmrPort = __HMR_PORT__;\nconst socketHost = `${__HMR_HOSTNAME__ || importMetaUrl.hostname}:${hmrPort || importMetaUrl.port}${__HMR_BASE__}`;\nconst directSocketHost = __HMR_DIRECT_TARGET__;\nconst base = __BASE__ || \"/\";\nconst hmrTimeout = __HMR_TIMEOUT__;\nconst wsToken = __WS_TOKEN__;\nconst transport = normalizeModuleRunnerTransport(\n (() => {\n let wsTransport = createWebSocketModuleRunnerTransport({\n createConnection: () => new WebSocket(\n `${socketProtocol}://${socketHost}?token=${wsToken}`,\n \"vite-hmr\"\n ),\n pingInterval: hmrTimeout\n });\n return {\n async connect(handlers) {\n try {\n await wsTransport.connect(handlers);\n } catch (e) {\n if (!hmrPort) {\n wsTransport = createWebSocketModuleRunnerTransport({\n createConnection: () => new WebSocket(\n `${socketProtocol}://${directSocketHost}?token=${wsToken}`,\n \"vite-hmr\"\n ),\n pingInterval: hmrTimeout\n });\n try {\n await wsTransport.connect(handlers);\n console.info(\n \"[vite] Direct websocket connection fallback. Check out https://vite.dev/config/server-options.html#server-hmr to remove the previous connection error.\"\n );\n } catch (e2) {\n if (e2 instanceof Error && e2.message.includes(\"WebSocket closed without opened.\")) {\n const currentScriptHostURL = new URL(import.meta.url);\n const currentScriptHost = currentScriptHostURL.host + currentScriptHostURL.pathname.replace(/@vite\\/client$/, \"\");\n console.error(\n `[vite] failed to connect to websocket.\nyour current setup:\n (browser) ${currentScriptHost} <--[HTTP]--> ${serverHost} (server)\n (browser) ${socketHost} <--[WebSocket (failing)]--> ${directSocketHost} (server)\nCheck out your Vite / network configuration and https://vite.dev/config/server-options.html#server-hmr .`\n );\n }\n }\n return;\n }\n console.error(`[vite] failed to connect to websocket (${e}). `);\n throw e;\n }\n },\n async disconnect() {\n await wsTransport.disconnect();\n },\n send(data) {\n wsTransport.send(data);\n }\n };\n })()\n);\nlet willUnload = false;\nif (typeof window !== \"undefined\") {\n window.addEventListener(\"beforeunload\", () => {\n willUnload = true;\n });\n}\nfunction cleanUrl(pathname) {\n const url = new URL(pathname, \"http://vite.dev\");\n url.searchParams.delete(\"direct\");\n return url.pathname + url.search;\n}\nlet isFirstUpdate = true;\nconst outdatedLinkTags = /* @__PURE__ */ new WeakSet();\nconst debounceReload = (time) => {\n let timer;\n return () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n timer = setTimeout(() => {\n location.reload();\n }, time);\n };\n};\nconst pageReload = debounceReload(50);\nconst hmrClient = new HMRClient(\n {\n error: (err) => console.error(\"[vite]\", err),\n debug: (...msg) => console.debug(\"[vite]\", ...msg)\n },\n transport,\n async function importUpdatedModule({\n acceptedPath,\n timestamp,\n explicitImportRequired,\n isWithinCircularImport\n }) {\n const [acceptedPathWithoutQuery, query] = acceptedPath.split(`?`);\n const importPromise = import(\n /* @vite-ignore */\n base + acceptedPathWithoutQuery.slice(1) + `?${explicitImportRequired ? \"import&\" : \"\"}t=${timestamp}${query ? `&${query}` : \"\"}`\n );\n if (isWithinCircularImport) {\n importPromise.catch(() => {\n console.info(\n `[hmr] ${acceptedPath} failed to apply HMR as it's within a circular import. Reloading page to reset the execution order. To debug and break the circular import, you can run \\`vite --debug hmr\\` to log the circular dependency path if a file change triggered it.`\n );\n pageReload();\n });\n }\n return await importPromise;\n }\n);\ntransport.connect(createHMRHandler(handleMessage));\nasync function handleMessage(payload) {\n switch (payload.type) {\n case \"connected\":\n console.debug(`[vite] connected.`);\n break;\n case \"update\":\n await hmrClient.notifyListeners(\"vite:beforeUpdate\", payload);\n if (hasDocument) {\n if (isFirstUpdate && hasErrorOverlay()) {\n location.reload();\n return;\n } else {\n if (enableOverlay) {\n clearErrorOverlay();\n }\n isFirstUpdate = false;\n }\n }\n await Promise.all(\n payload.updates.map(async (update) => {\n if (update.type === \"js-update\") {\n return hmrClient.queueUpdate(update);\n }\n const { path, timestamp } = update;\n const searchUrl = cleanUrl(path);\n const el = Array.from(\n document.querySelectorAll(\"link\")\n ).find(\n (e) => !outdatedLinkTags.has(e) && cleanUrl(e.href).includes(searchUrl)\n );\n if (!el) {\n return;\n }\n const newPath = `${base}${searchUrl.slice(1)}${searchUrl.includes(\"?\") ? \"&\" : \"?\"}t=${timestamp}`;\n return new Promise((resolve) => {\n const newLinkTag = el.cloneNode();\n newLinkTag.href = new URL(newPath, el.href).href;\n const removeOldEl = () => {\n el.remove();\n console.debug(`[vite] css hot updated: ${searchUrl}`);\n resolve();\n };\n newLinkTag.addEventListener(\"load\", removeOldEl);\n newLinkTag.addEventListener(\"error\", removeOldEl);\n outdatedLinkTags.add(el);\n el.after(newLinkTag);\n });\n })\n );\n await hmrClient.notifyListeners(\"vite:afterUpdate\", payload);\n break;\n case \"custom\": {\n await hmrClient.notifyListeners(payload.event, payload.data);\n if (payload.event === \"vite:ws:disconnect\") {\n if (hasDocument && !willUnload) {\n console.log(`[vite] server connection lost. Polling for restart...`);\n const socket = payload.data.webSocket;\n const url = new URL(socket.url);\n url.search = \"\";\n await waitForSuccessfulPing(url.href);\n location.reload();\n }\n }\n break;\n }\n case \"full-reload\":\n await hmrClient.notifyListeners(\"vite:beforeFullReload\", payload);\n if (hasDocument) {\n if (payload.path && payload.path.endsWith(\".html\")) {\n const pagePath = decodeURI(location.pathname);\n const payloadPath = base + payload.path.slice(1);\n if (pagePath === payloadPath || payload.path === \"/index.html\" || pagePath.endsWith(\"/\") && pagePath + \"index.html\" === payloadPath) {\n pageReload();\n }\n return;\n } else {\n pageReload();\n }\n }\n break;\n case \"prune\":\n await hmrClient.notifyListeners(\"vite:beforePrune\", payload);\n await hmrClient.prunePaths(payload.paths);\n break;\n case \"error\": {\n await hmrClient.notifyListeners(\"vite:error\", payload);\n if (hasDocument) {\n const err = payload.err;\n if (enableOverlay) {\n createErrorOverlay(err);\n } else {\n console.error(\n `[vite] Internal Server Error\n${err.message}\n${err.stack}`\n );\n }\n }\n break;\n }\n case \"ping\":\n break;\n default: {\n const check = payload;\n return check;\n }\n }\n}\nconst enableOverlay = __HMR_ENABLE_OVERLAY__;\nconst hasDocument = \"document\" in globalThis;\nfunction createErrorOverlay(err) {\n clearErrorOverlay();\n const { customElements } = globalThis;\n if (customElements) {\n const ErrorOverlayConstructor = customElements.get(overlayId);\n document.body.appendChild(new ErrorOverlayConstructor(err));\n }\n}\nfunction clearErrorOverlay() {\n document.querySelectorAll(overlayId).forEach((n) => n.close());\n}\nfunction hasErrorOverlay() {\n return document.querySelectorAll(overlayId).length;\n}\nasync function waitForSuccessfulPing(socketUrl, ms = 1e3) {\n async function ping() {\n const socket = new WebSocket(socketUrl, \"vite-ping\");\n return new Promise((resolve) => {\n function onOpen() {\n resolve(true);\n close();\n }\n function onError() {\n resolve(false);\n close();\n }\n function close() {\n socket.removeEventListener(\"open\", onOpen);\n socket.removeEventListener(\"error\", onError);\n socket.close();\n }\n socket.addEventListener(\"open\", onOpen);\n socket.addEventListener(\"error\", onError);\n });\n }\n if (await ping()) {\n return;\n }\n await wait(ms);\n while (true) {\n if (document.visibilityState === \"visible\") {\n if (await ping()) {\n break;\n }\n await wait(ms);\n } else {\n await waitForWindowShow();\n }\n }\n}\nfunction wait(ms) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\nfunction waitForWindowShow() {\n return new Promise((resolve) => {\n const onChange = async () => {\n if (document.visibilityState === \"visible\") {\n resolve();\n document.removeEventListener(\"visibilitychange\", onChange);\n }\n };\n document.addEventListener(\"visibilitychange\", onChange);\n });\n}\nconst sheetsMap = /* @__PURE__ */ new Map();\nif (\"document\" in globalThis) {\n document.querySelectorAll(\"style[data-vite-dev-id]\").forEach((el) => {\n sheetsMap.set(el.getAttribute(\"data-vite-dev-id\"), el);\n });\n}\nconst cspNonce = \"document\" in globalThis ? document.querySelector(\"meta[property=csp-nonce]\")?.nonce : void 0;\nlet lastInsertedStyle;\nfunction updateStyle(id, content) {\n let style = sheetsMap.get(id);\n if (!style) {\n style = document.createElement(\"style\");\n style.setAttribute(\"type\", \"text/css\");\n style.setAttribute(\"data-vite-dev-id\", id);\n style.textContent = content;\n if (cspNonce) {\n style.setAttribute(\"nonce\", cspNonce);\n }\n if (!lastInsertedStyle) {\n document.head.appendChild(style);\n setTimeout(() => {\n lastInsertedStyle = void 0;\n }, 0);\n } else {\n lastInsertedStyle.insertAdjacentElement(\"afterend\", style);\n }\n lastInsertedStyle = style;\n } else {\n style.textContent = content;\n }\n sheetsMap.set(id, style);\n}\nfunction removeStyle(id) {\n const style = sheetsMap.get(id);\n if (style) {\n document.head.removeChild(style);\n sheetsMap.delete(id);\n }\n}\nfunction createHotContext(ownerPath) {\n return new HMRContext(hmrClient, ownerPath);\n}\nfunction injectQuery(url, queryToInject) {\n if (url[0] !== \".\" && url[0] !== \"/\") {\n return url;\n }\n const pathname = url.replace(/[?#].*$/, \"\");\n const { search, hash } = new URL(url, \"http://vite.dev\");\n return `${pathname}?${queryToInject}${search ? `&` + search.slice(1) : \"\"}${hash || \"\"}`;\n}\n\nexport { ErrorOverlay, createHotContext, injectQuery, removeStyle, updateStyle };\n";
|
|
53
|
+
export const VITE_ENV_MJS = "const context = (() => {\n if (typeof globalThis !== \"undefined\") {\n return globalThis;\n } else if (typeof self !== \"undefined\") {\n return self;\n } else if (typeof window !== \"undefined\") {\n return window;\n } else {\n return Function(\"return this\")();\n }\n})();\nconst defines = __DEFINES__;\nObject.keys(defines).forEach((key) => {\n const segments = key.split(\".\");\n let target = context;\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i];\n if (i === segments.length - 1) {\n target[segment] = defines[key];\n } else {\n target = target[segment] || (target[segment] = {});\n }\n }\n});\n";
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* replica-routing.ts — W12 — DO read replica routing primitives.
|
|
3
|
+
*
|
|
4
|
+
* Pure module (no `cloudflare:workers` import) so it can be unit-tested
|
|
5
|
+
* under Bun. NimbusSession wraps these helpers in its constructor and
|
|
6
|
+
* `_handleFetch` preflight; everything else is plumbing.
|
|
7
|
+
*
|
|
8
|
+
* Background:
|
|
9
|
+
* - CF research §G.4 / §J.7.1: DO read replicas (wiki SPEC: STOR/Durable
|
|
10
|
+
* Objects read replication API). Replicas serve cross-region read-mostly
|
|
11
|
+
* traffic; writes always run on the primary. The runtime exposes:
|
|
12
|
+
*
|
|
13
|
+
* ctx.storage.enableReplicas() — wiki SPEC API
|
|
14
|
+
* ctx.storage.configureReadReplication(opts) — alternate API name
|
|
15
|
+
* observed in J.7.1 sketch
|
|
16
|
+
* ctx.storage.primary — RpcStub-like; undefined
|
|
17
|
+
* on the primary itself,
|
|
18
|
+
* defined on replicas
|
|
19
|
+
* ctx.storage.getCurrentBookmark() — opaque bookmark for
|
|
20
|
+
* read-your-writes
|
|
21
|
+
*
|
|
22
|
+
* We probe each defensively at runtime so this module is forward- and
|
|
23
|
+
* backward-compatible: pre-GA runtimes lacking the API surface get
|
|
24
|
+
* `state: 'unsupported'` and the DO behaves exactly as before W12.
|
|
25
|
+
*
|
|
26
|
+
* - CF docs (workers/configuration/placement/): Smart Placement applies
|
|
27
|
+
* to fetch handlers, NOT RPC. So Smart Placement on the gateway Worker
|
|
28
|
+
* pins it near the DO; RPC into the DO is unaffected. DOs themselves
|
|
29
|
+
* don't move.
|
|
30
|
+
*
|
|
31
|
+
* - ~lambros/Feedback for DO read replication API: replicas error with
|
|
32
|
+
* "Network connection lost" during high-volume writes. Mitigation:
|
|
33
|
+
* suspend replicas during npm install / git clone bursts (the
|
|
34
|
+
* suspension state lives in `replica-suspension.ts`).
|
|
35
|
+
*/
|
|
36
|
+
/** Result of `classifyReplicaPolicy(pathname, method)`. */
|
|
37
|
+
export type ReplicaPolicy =
|
|
38
|
+
/** Always safe on a replica (idempotent reads of soft state). */
|
|
39
|
+
'replica-ok'
|
|
40
|
+
/** Safe on a replica IFF the in-memory state needed is already warm. */
|
|
41
|
+
| 'replica-warm-only'
|
|
42
|
+
/** Replica must forward to primary. */
|
|
43
|
+
| 'primary-only'
|
|
44
|
+
/** Replica must forward; the route is a WS upgrade and the replica must
|
|
45
|
+
* not subscribe its own hibernation handler to a stream the primary
|
|
46
|
+
* appends to. */
|
|
47
|
+
| 'primary-only-ws';
|
|
48
|
+
/** Eventual-consistency tolerance in ms (replica-eligible routes only). */
|
|
49
|
+
export interface RoutePolicy {
|
|
50
|
+
policy: ReplicaPolicy;
|
|
51
|
+
/** Max acceptable replication lag for this route, in ms. `null` for
|
|
52
|
+
* primary-only routes (not replicable). */
|
|
53
|
+
toleranceMs: number | null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Pure routing decision. Mirrors the route table in W12-plan §2.
|
|
57
|
+
* Methods other than GET/HEAD on a replica-eligible route escape to
|
|
58
|
+
* primary-only — read replicas only make sense for reads.
|
|
59
|
+
*/
|
|
60
|
+
export declare function classifyReplicaPolicy(pathname: string, method: string): ReplicaPolicy;
|
|
61
|
+
/**
|
|
62
|
+
* Eventual-consistency tolerance per route (in ms).
|
|
63
|
+
*
|
|
64
|
+
* Returns `null` for primary-only routes (not replicable) and a numeric
|
|
65
|
+
* tolerance for replica-eligible routes. The probe
|
|
66
|
+
* `eventual-consistency-window-ms.mjs` enforces that every eligible route
|
|
67
|
+
* has a tolerance ≤ 2000ms.
|
|
68
|
+
*
|
|
69
|
+
* The 2-second budget aligns with D1 read-replication best practice
|
|
70
|
+
* (D1 docs § "Replica lag and consistency model"); DO replicas are
|
|
71
|
+
* the same architectural pattern.
|
|
72
|
+
*/
|
|
73
|
+
export declare function getEventualConsistencyToleranceMs(pathname: string): number | null;
|
|
74
|
+
/** Tolerance lookup table (for diagnostics / observability surfaces). */
|
|
75
|
+
export declare const REPLICA_POLICIES: Record<string, RoutePolicy>;
|
|
76
|
+
export type ReplicasState = 'enabled' | 'enabled-via-configure' | 'unsupported' | 'error';
|
|
77
|
+
export interface TryEnableReplicasResult {
|
|
78
|
+
state: ReplicasState;
|
|
79
|
+
error: string | null;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Best-effort: enable read replicas on this DO instance. Safe to call from
|
|
83
|
+
* the constructor — pre-GA runtimes that lack the API surface no-op.
|
|
84
|
+
*
|
|
85
|
+
* Operators reading `getReplicaState()` (exposed via /api/_diag/memory)
|
|
86
|
+
* see which path was taken.
|
|
87
|
+
*/
|
|
88
|
+
export declare function tryEnableReplicas(ctx: any): TryEnableReplicasResult;
|
|
89
|
+
export interface ReplicaStateInspect {
|
|
90
|
+
isReplica: boolean;
|
|
91
|
+
primary: any | null;
|
|
92
|
+
bookmark: string | null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Inspect this isolate's replica state.
|
|
96
|
+
*
|
|
97
|
+
* - `isReplica` is `true` when `ctx.storage.primary` is defined. (Per
|
|
98
|
+
* the wiki SPEC: the primary's `storage.primary` is `undefined`;
|
|
99
|
+
* replica isolates get an RPC stub to the primary here.)
|
|
100
|
+
* - `primary` is a stub-shaped object on replicas, `null` on primary.
|
|
101
|
+
* - `bookmark` is `getCurrentBookmark()` if the API is present; `null`
|
|
102
|
+
* otherwise. Used to thread read-your-writes via headers/cookies
|
|
103
|
+
* when the SPEC's `waitForBookmark` lands.
|
|
104
|
+
*/
|
|
105
|
+
export declare function inspectReplicaState(ctx: any): ReplicaStateInspect;
|
|
106
|
+
/**
|
|
107
|
+
* Capture the current bookmark immediately after a write completes on
|
|
108
|
+
* the primary. The caller (e.g. /api/write-file) can stash the result in
|
|
109
|
+
* a response header / cookie so the next read-your-writes call from the
|
|
110
|
+
* same client can wait for the replica to catch up before responding.
|
|
111
|
+
*
|
|
112
|
+
* Phase 1 of W12 surfaces this as observability only (visible via
|
|
113
|
+
* /api/_diag/memory.replica.bookmark). Phase 2 (W12.5 if measured demand)
|
|
114
|
+
* wires the wait-for-bookmark contract end-to-end.
|
|
115
|
+
*/
|
|
116
|
+
export declare function captureBookmarkAfterWrite(ctx: any): string | null;
|
|
117
|
+
export interface DelegationInputs {
|
|
118
|
+
isReplica: boolean;
|
|
119
|
+
policy: ReplicaPolicy;
|
|
120
|
+
/** Whether this isolate has the in-memory state needed to serve a
|
|
121
|
+
* `replica-warm-only` route (e.g. ViteDevServer.isRunning). */
|
|
122
|
+
isWarm: boolean;
|
|
123
|
+
/** Whether replicas are globally suspended (npm install / git clone
|
|
124
|
+
* in flight). When true, replicas always delegate. */
|
|
125
|
+
suspended?: boolean;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Pure decision: should this isolate forward the Request to the primary
|
|
129
|
+
* via `ctx.storage.primary.fetch(request)`?
|
|
130
|
+
*
|
|
131
|
+
* `false` means "handle locally" (works on both primary and replica).
|
|
132
|
+
* `true` means "delegate" (replica-only; the caller is responsible for
|
|
133
|
+
* actually invoking `ctx.storage.primary.fetch(...)`).
|
|
134
|
+
*/
|
|
135
|
+
export declare function shouldDelegateToPrimary(inputs: DelegationInputs): boolean;
|
|
136
|
+
/** Result of `handleReplicaPreflight`. */
|
|
137
|
+
export interface PreflightResult {
|
|
138
|
+
/** True iff the caller should NOT invoke the local route handlers and
|
|
139
|
+
* return `response` as-is. False means "fall through to local handling
|
|
140
|
+
* as today." */
|
|
141
|
+
delegated: boolean;
|
|
142
|
+
/** When `delegated === true`, the Response from the primary. When
|
|
143
|
+
* `delegated === false`, `null`. */
|
|
144
|
+
response: Response | null;
|
|
145
|
+
/** The decision inputs, surfaced for diagnostic logging / tests. */
|
|
146
|
+
decision: DelegationInputs & {
|
|
147
|
+
pathname: string;
|
|
148
|
+
method: string;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* High-level preflight: classify the request, decide whether to delegate,
|
|
153
|
+
* and (if so) actually call `ctx.storage.primary.fetch(request)` and
|
|
154
|
+
* return the response.
|
|
155
|
+
*
|
|
156
|
+
* Caller pattern in NimbusSession._handleFetch:
|
|
157
|
+
*
|
|
158
|
+
* const pre = await handleReplicaPreflight(this.ctx, request, {
|
|
159
|
+
* isWarm: this.viteDevServer?.isRunning ?? false,
|
|
160
|
+
* });
|
|
161
|
+
* if (pre.delegated) return pre.response!;
|
|
162
|
+
* // … existing route handlers …
|
|
163
|
+
*
|
|
164
|
+
* Note: the request is forwarded by reference (Request objects are
|
|
165
|
+
* single-consumption — the caller MUST NOT have read the body already).
|
|
166
|
+
*/
|
|
167
|
+
export declare function handleReplicaPreflight(ctx: any, request: Request, opts: {
|
|
168
|
+
isWarm: boolean;
|
|
169
|
+
suspended?: boolean;
|
|
170
|
+
}): Promise<PreflightResult>;
|
|
171
|
+
//# sourceMappingURL=routing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/replica/routing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,2DAA2D;AAC3D,MAAM,MAAM,aAAa;AACvB,iEAAiE;AAC/D,YAAY;AACd,wEAAwE;GACtE,mBAAmB;AACrB,uCAAuC;GACrC,cAAc;AAChB;;kBAEkB;GAChB,iBAAiB,CAAC;AAEtB,2EAA2E;AAC3E,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB;gDAC4C;IAC5C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAMD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,aAAa,CAkDf;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,iCAAiC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMjF;AAED,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAaxD,CAAC;AAMF,MAAM,MAAM,aAAa,GACrB,SAAS,GACT,uBAAuB,GACvB,aAAa,GACb,OAAO,CAAC;AAEZ,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,aAAa,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,uBAAuB,CAgBnE;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,GAAG,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,GAAG,GAAG,mBAAmB,CAgBjE;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,GAAG,IAAI,CAEjE;AAMD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,aAAa,CAAC;IACtB;oEACgE;IAChE,MAAM,EAAE,OAAO,CAAC;IAChB;2DACuD;IACvD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAoBzE;AAED,0CAA0C;AAC1C,MAAM,WAAW,eAAe;IAC9B;;qBAEiB;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB;yCACqC;IACrC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,oEAAoE;IACpE,QAAQ,EAAE,gBAAgB,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACnE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7C,OAAO,CAAC,eAAe,CAAC,CA6B1B"}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* replica-routing.ts — W12 — DO read replica routing primitives.
|
|
3
|
+
*
|
|
4
|
+
* Pure module (no `cloudflare:workers` import) so it can be unit-tested
|
|
5
|
+
* under Bun. NimbusSession wraps these helpers in its constructor and
|
|
6
|
+
* `_handleFetch` preflight; everything else is plumbing.
|
|
7
|
+
*
|
|
8
|
+
* Background:
|
|
9
|
+
* - CF research §G.4 / §J.7.1: DO read replicas (wiki SPEC: STOR/Durable
|
|
10
|
+
* Objects read replication API). Replicas serve cross-region read-mostly
|
|
11
|
+
* traffic; writes always run on the primary. The runtime exposes:
|
|
12
|
+
*
|
|
13
|
+
* ctx.storage.enableReplicas() — wiki SPEC API
|
|
14
|
+
* ctx.storage.configureReadReplication(opts) — alternate API name
|
|
15
|
+
* observed in J.7.1 sketch
|
|
16
|
+
* ctx.storage.primary — RpcStub-like; undefined
|
|
17
|
+
* on the primary itself,
|
|
18
|
+
* defined on replicas
|
|
19
|
+
* ctx.storage.getCurrentBookmark() — opaque bookmark for
|
|
20
|
+
* read-your-writes
|
|
21
|
+
*
|
|
22
|
+
* We probe each defensively at runtime so this module is forward- and
|
|
23
|
+
* backward-compatible: pre-GA runtimes lacking the API surface get
|
|
24
|
+
* `state: 'unsupported'` and the DO behaves exactly as before W12.
|
|
25
|
+
*
|
|
26
|
+
* - CF docs (workers/configuration/placement/): Smart Placement applies
|
|
27
|
+
* to fetch handlers, NOT RPC. So Smart Placement on the gateway Worker
|
|
28
|
+
* pins it near the DO; RPC into the DO is unaffected. DOs themselves
|
|
29
|
+
* don't move.
|
|
30
|
+
*
|
|
31
|
+
* - ~lambros/Feedback for DO read replication API: replicas error with
|
|
32
|
+
* "Network connection lost" during high-volume writes. Mitigation:
|
|
33
|
+
* suspend replicas during npm install / git clone bursts (the
|
|
34
|
+
* suspension state lives in `replica-suspension.ts`).
|
|
35
|
+
*/
|
|
36
|
+
const PROCESSES_LOGS_RE = /^\/api\/processes\/\d+\/logs$/;
|
|
37
|
+
const PORT_RE = /^\/port\/\d+(\/.*)?$/;
|
|
38
|
+
const TWO_SECONDS = 2000;
|
|
39
|
+
/**
|
|
40
|
+
* Pure routing decision. Mirrors the route table in W12-plan §2.
|
|
41
|
+
* Methods other than GET/HEAD on a replica-eligible route escape to
|
|
42
|
+
* primary-only — read replicas only make sense for reads.
|
|
43
|
+
*/
|
|
44
|
+
export function classifyReplicaPolicy(pathname, method) {
|
|
45
|
+
// ── WS upgrades — must land on primary so hibernation subscriptions
|
|
46
|
+
// follow the primary's append stream. (Replica acceptWebSocket
|
|
47
|
+
// would subscribe a doomed replica handler.)
|
|
48
|
+
if (pathname === '/ws')
|
|
49
|
+
return 'primary-only-ws';
|
|
50
|
+
if (PROCESSES_LOGS_RE.test(pathname))
|
|
51
|
+
return 'primary-only-ws';
|
|
52
|
+
if (pathname === '/preview/__nimbus_hmr' || pathname.startsWith('/preview/__nimbus_hmr/')) {
|
|
53
|
+
return 'primary-only-ws';
|
|
54
|
+
}
|
|
55
|
+
// ── Worker / port routes — facets are owned by the primary; no
|
|
56
|
+
// replica representation. Always primary-only.
|
|
57
|
+
//
|
|
58
|
+
// Primitives wave: `/__nimbus/worker/*` is the canonical route;
|
|
59
|
+
// `/worker/*` is the deprecated legacy form, kept here for back-
|
|
60
|
+
// compat (one release sunset; see routes.ts for the Deprecation
|
|
61
|
+
// header). Both classify the same way.
|
|
62
|
+
if (pathname === '/__nimbus/worker' || pathname.startsWith('/__nimbus/worker/'))
|
|
63
|
+
return 'primary-only';
|
|
64
|
+
if (pathname === '/worker' || pathname.startsWith('/worker/'))
|
|
65
|
+
return 'primary-only';
|
|
66
|
+
if (PORT_RE.test(pathname))
|
|
67
|
+
return 'primary-only';
|
|
68
|
+
// ── /preview/* — read-mostly after warm. Cold-warm distinction
|
|
69
|
+
// handled by shouldDelegateToPrimary's `isWarm` input.
|
|
70
|
+
if (pathname === '/preview' || pathname.startsWith('/preview/')) {
|
|
71
|
+
if (!isReadMethod(method))
|
|
72
|
+
return 'primary-only';
|
|
73
|
+
return 'replica-warm-only';
|
|
74
|
+
}
|
|
75
|
+
// ── /api/_test/* — test-only endpoints, predictable behaviour > latency.
|
|
76
|
+
if (pathname.startsWith('/api/_test/'))
|
|
77
|
+
return 'primary-only';
|
|
78
|
+
// ── /api/* read endpoints (replica-ok)
|
|
79
|
+
if (isReadMethod(method)) {
|
|
80
|
+
if (pathname === '/api/memory')
|
|
81
|
+
return 'replica-ok';
|
|
82
|
+
if (pathname === '/api/_diag/memory')
|
|
83
|
+
return 'replica-ok';
|
|
84
|
+
if (pathname.startsWith('/api/_diag/'))
|
|
85
|
+
return 'replica-ok';
|
|
86
|
+
if (pathname === '/api/processes')
|
|
87
|
+
return 'replica-ok';
|
|
88
|
+
if (pathname === '/api/stats')
|
|
89
|
+
return 'replica-ok';
|
|
90
|
+
}
|
|
91
|
+
// ── Known write endpoints — primary-only.
|
|
92
|
+
if (pathname === '/api/write-file')
|
|
93
|
+
return 'primary-only';
|
|
94
|
+
if (pathname === '/api/mkdir')
|
|
95
|
+
return 'primary-only';
|
|
96
|
+
if (pathname === '/api/start-vite')
|
|
97
|
+
return 'primary-only';
|
|
98
|
+
if (pathname === '/api/supervisor-rpc')
|
|
99
|
+
return 'primary-only';
|
|
100
|
+
// Default: anything we don't recognize on a replica goes to primary.
|
|
101
|
+
// Safety > latency. New routes added must be classified explicitly
|
|
102
|
+
// (and the eventual-consistency-window-ms.mjs probe enforces that).
|
|
103
|
+
return 'primary-only';
|
|
104
|
+
}
|
|
105
|
+
function isReadMethod(method) {
|
|
106
|
+
return method === 'GET' || method === 'HEAD';
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Eventual-consistency tolerance per route (in ms).
|
|
110
|
+
*
|
|
111
|
+
* Returns `null` for primary-only routes (not replicable) and a numeric
|
|
112
|
+
* tolerance for replica-eligible routes. The probe
|
|
113
|
+
* `eventual-consistency-window-ms.mjs` enforces that every eligible route
|
|
114
|
+
* has a tolerance ≤ 2000ms.
|
|
115
|
+
*
|
|
116
|
+
* The 2-second budget aligns with D1 read-replication best practice
|
|
117
|
+
* (D1 docs § "Replica lag and consistency model"); DO replicas are
|
|
118
|
+
* the same architectural pattern.
|
|
119
|
+
*/
|
|
120
|
+
export function getEventualConsistencyToleranceMs(pathname) {
|
|
121
|
+
// Re-classify with a synthetic GET to figure out replica eligibility.
|
|
122
|
+
const policy = classifyReplicaPolicy(pathname, 'GET');
|
|
123
|
+
if (policy === 'replica-ok')
|
|
124
|
+
return TWO_SECONDS;
|
|
125
|
+
if (policy === 'replica-warm-only')
|
|
126
|
+
return TWO_SECONDS;
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
/** Tolerance lookup table (for diagnostics / observability surfaces). */
|
|
130
|
+
export const REPLICA_POLICIES = {
|
|
131
|
+
'/api/memory': { policy: 'replica-ok', toleranceMs: TWO_SECONDS },
|
|
132
|
+
'/api/_diag/memory': { policy: 'replica-ok', toleranceMs: TWO_SECONDS },
|
|
133
|
+
'/api/processes': { policy: 'replica-ok', toleranceMs: TWO_SECONDS },
|
|
134
|
+
'/api/stats': { policy: 'replica-ok', toleranceMs: TWO_SECONDS },
|
|
135
|
+
'/preview/': { policy: 'replica-warm-only', toleranceMs: TWO_SECONDS },
|
|
136
|
+
'/ws': { policy: 'primary-only-ws', toleranceMs: null },
|
|
137
|
+
'/api/write-file': { policy: 'primary-only', toleranceMs: null },
|
|
138
|
+
'/api/mkdir': { policy: 'primary-only', toleranceMs: null },
|
|
139
|
+
'/api/start-vite': { policy: 'primary-only', toleranceMs: null },
|
|
140
|
+
'/api/supervisor-rpc': { policy: 'primary-only', toleranceMs: null },
|
|
141
|
+
'/worker/': { policy: 'primary-only', toleranceMs: null },
|
|
142
|
+
'/__nimbus/worker/': { policy: 'primary-only', toleranceMs: null },
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Best-effort: enable read replicas on this DO instance. Safe to call from
|
|
146
|
+
* the constructor — pre-GA runtimes that lack the API surface no-op.
|
|
147
|
+
*
|
|
148
|
+
* Operators reading `getReplicaState()` (exposed via /api/_diag/memory)
|
|
149
|
+
* see which path was taken.
|
|
150
|
+
*/
|
|
151
|
+
export function tryEnableReplicas(ctx) {
|
|
152
|
+
if (!ctx || !ctx.storage)
|
|
153
|
+
return { state: 'unsupported', error: null };
|
|
154
|
+
const s = ctx.storage;
|
|
155
|
+
try {
|
|
156
|
+
if (typeof s.enableReplicas === 'function') {
|
|
157
|
+
s.enableReplicas();
|
|
158
|
+
return { state: 'enabled', error: null };
|
|
159
|
+
}
|
|
160
|
+
if (typeof s.configureReadReplication === 'function') {
|
|
161
|
+
s.configureReadReplication({ mode: 'auto' });
|
|
162
|
+
return { state: 'enabled-via-configure', error: null };
|
|
163
|
+
}
|
|
164
|
+
return { state: 'unsupported', error: null };
|
|
165
|
+
}
|
|
166
|
+
catch (e) {
|
|
167
|
+
return { state: 'error', error: e?.message ?? String(e) };
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Inspect this isolate's replica state.
|
|
172
|
+
*
|
|
173
|
+
* - `isReplica` is `true` when `ctx.storage.primary` is defined. (Per
|
|
174
|
+
* the wiki SPEC: the primary's `storage.primary` is `undefined`;
|
|
175
|
+
* replica isolates get an RPC stub to the primary here.)
|
|
176
|
+
* - `primary` is a stub-shaped object on replicas, `null` on primary.
|
|
177
|
+
* - `bookmark` is `getCurrentBookmark()` if the API is present; `null`
|
|
178
|
+
* otherwise. Used to thread read-your-writes via headers/cookies
|
|
179
|
+
* when the SPEC's `waitForBookmark` lands.
|
|
180
|
+
*/
|
|
181
|
+
export function inspectReplicaState(ctx) {
|
|
182
|
+
if (!ctx || !ctx.storage)
|
|
183
|
+
return { isReplica: false, primary: null, bookmark: null };
|
|
184
|
+
const s = ctx.storage;
|
|
185
|
+
const isReplica = typeof s.primary !== 'undefined' && s.primary !== null;
|
|
186
|
+
let bookmark = null;
|
|
187
|
+
try {
|
|
188
|
+
if (typeof s.getCurrentBookmark === 'function') {
|
|
189
|
+
const v = s.getCurrentBookmark();
|
|
190
|
+
// The SPEC describes getCurrentBookmark as returning Promise<string>.
|
|
191
|
+
// J.7.1 uses it synchronously — accept either. We only surface
|
|
192
|
+
// string-on-fast-path; promises get null + the operator falls back
|
|
193
|
+
// to the async getReplicaState() variant if needed.
|
|
194
|
+
if (typeof v === 'string')
|
|
195
|
+
bookmark = v;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
catch { /* best-effort */ }
|
|
199
|
+
return { isReplica, primary: isReplica ? s.primary : null, bookmark };
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Capture the current bookmark immediately after a write completes on
|
|
203
|
+
* the primary. The caller (e.g. /api/write-file) can stash the result in
|
|
204
|
+
* a response header / cookie so the next read-your-writes call from the
|
|
205
|
+
* same client can wait for the replica to catch up before responding.
|
|
206
|
+
*
|
|
207
|
+
* Phase 1 of W12 surfaces this as observability only (visible via
|
|
208
|
+
* /api/_diag/memory.replica.bookmark). Phase 2 (W12.5 if measured demand)
|
|
209
|
+
* wires the wait-for-bookmark contract end-to-end.
|
|
210
|
+
*/
|
|
211
|
+
export function captureBookmarkAfterWrite(ctx) {
|
|
212
|
+
return inspectReplicaState(ctx).bookmark;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Pure decision: should this isolate forward the Request to the primary
|
|
216
|
+
* via `ctx.storage.primary.fetch(request)`?
|
|
217
|
+
*
|
|
218
|
+
* `false` means "handle locally" (works on both primary and replica).
|
|
219
|
+
* `true` means "delegate" (replica-only; the caller is responsible for
|
|
220
|
+
* actually invoking `ctx.storage.primary.fetch(...)`).
|
|
221
|
+
*/
|
|
222
|
+
export function shouldDelegateToPrimary(inputs) {
|
|
223
|
+
// Primary never delegates to itself.
|
|
224
|
+
if (!inputs.isReplica)
|
|
225
|
+
return false;
|
|
226
|
+
// Suspended (write-burst window) — replicas defer everything to primary
|
|
227
|
+
// to avoid the SPEC's "Network connection lost" replication error.
|
|
228
|
+
if (inputs.suspended === true)
|
|
229
|
+
return true;
|
|
230
|
+
switch (inputs.policy) {
|
|
231
|
+
case 'replica-ok':
|
|
232
|
+
return false;
|
|
233
|
+
case 'replica-warm-only':
|
|
234
|
+
return !inputs.isWarm;
|
|
235
|
+
case 'primary-only':
|
|
236
|
+
case 'primary-only-ws':
|
|
237
|
+
return true;
|
|
238
|
+
default:
|
|
239
|
+
// Defensive: unknown policies fail closed → primary-only.
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* High-level preflight: classify the request, decide whether to delegate,
|
|
245
|
+
* and (if so) actually call `ctx.storage.primary.fetch(request)` and
|
|
246
|
+
* return the response.
|
|
247
|
+
*
|
|
248
|
+
* Caller pattern in NimbusSession._handleFetch:
|
|
249
|
+
*
|
|
250
|
+
* const pre = await handleReplicaPreflight(this.ctx, request, {
|
|
251
|
+
* isWarm: this.viteDevServer?.isRunning ?? false,
|
|
252
|
+
* });
|
|
253
|
+
* if (pre.delegated) return pre.response!;
|
|
254
|
+
* // … existing route handlers …
|
|
255
|
+
*
|
|
256
|
+
* Note: the request is forwarded by reference (Request objects are
|
|
257
|
+
* single-consumption — the caller MUST NOT have read the body already).
|
|
258
|
+
*/
|
|
259
|
+
export async function handleReplicaPreflight(ctx, request, opts) {
|
|
260
|
+
const url = new URL(request.url);
|
|
261
|
+
const pathname = url.pathname;
|
|
262
|
+
const method = request.method;
|
|
263
|
+
const policy = classifyReplicaPolicy(pathname, method);
|
|
264
|
+
const inspect = inspectReplicaState(ctx);
|
|
265
|
+
const decision = {
|
|
266
|
+
isReplica: inspect.isReplica,
|
|
267
|
+
policy,
|
|
268
|
+
isWarm: opts.isWarm,
|
|
269
|
+
suspended: opts.suspended ?? false,
|
|
270
|
+
pathname,
|
|
271
|
+
method,
|
|
272
|
+
};
|
|
273
|
+
const delegate = shouldDelegateToPrimary(decision);
|
|
274
|
+
if (!delegate) {
|
|
275
|
+
return { delegated: false, response: null, decision };
|
|
276
|
+
}
|
|
277
|
+
const primary = inspect.primary;
|
|
278
|
+
if (!primary || typeof primary.fetch !== 'function') {
|
|
279
|
+
// We claimed isReplica but the primary stub isn't usable — fall back
|
|
280
|
+
// to local handling (correctness > performance). Document via
|
|
281
|
+
// decision.suspended for diagnostic surfaces.
|
|
282
|
+
return { delegated: false, response: null, decision };
|
|
283
|
+
}
|
|
284
|
+
// Single intra-region RPC hop. The replica was placed near the primary
|
|
285
|
+
// so this is fast; the user's RTT-to-replica-edge is short anyway.
|
|
286
|
+
const response = await primary.fetch(request);
|
|
287
|
+
return { delegated: true, response, decision };
|
|
288
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* replica-suspension.ts — W12 — global replica-suspension counter.
|
|
3
|
+
*
|
|
4
|
+
* Per [~lambros/Feedback for DO read replication API](https://wiki.cfdata.org/display/~lambros/Feedback+for+DO+read+replication+API+based+on+D1+read+replication+beta)
|
|
5
|
+
* (cited in CF research §G.4), DO read replicas error with "Network
|
|
6
|
+
* connection lost" during high-volume writes. The recommended mitigation
|
|
7
|
+
* is to disable replicas before a write burst (npm install, git clone)
|
|
8
|
+
* and re-enable after.
|
|
9
|
+
*
|
|
10
|
+
* This module exposes a refcount-style suspend/release API. The counter
|
|
11
|
+
* is checked by `shouldDelegateToPrimary` (in `replica-routing.ts`):
|
|
12
|
+
* when `replicasSuspended() === true`, the replica forwards everything
|
|
13
|
+
* to the primary regardless of route policy.
|
|
14
|
+
*
|
|
15
|
+
* Phase 1 of W12 ships the module + the in-DO consultation. Phase 2
|
|
16
|
+
* (W12.5 if measured demand) wires the npm-installer / git-clone hooks.
|
|
17
|
+
* Today's behaviour: counter stays at 0 → replicas serve normally; the
|
|
18
|
+
* SPEC error path is observed as a graceful-degrade (replica's primary
|
|
19
|
+
* stub returns the error and the user sees a 5xx, same as today's
|
|
20
|
+
* single-region behaviour).
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Increment the suspension count. Returns a release function that
|
|
24
|
+
* decrements once (subsequent calls are no-ops). Suspends are nestable;
|
|
25
|
+
* any holder keeping the count > 0 keeps replicas suspended.
|
|
26
|
+
*/
|
|
27
|
+
export declare function suspendReplicas(): () => void;
|
|
28
|
+
/** Are any holders currently suspending replicas? */
|
|
29
|
+
export declare function replicasSuspended(): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Test-only escape hatch. Resets the counter to 0. Production code MUST
|
|
32
|
+
* NOT call this — use only the suspend/release pair to keep semantics
|
|
33
|
+
* tight. Exported under a `_` prefix and namespaced for tests.
|
|
34
|
+
*/
|
|
35
|
+
export declare function _resetSuspensionForTests(): void;
|
|
36
|
+
//# sourceMappingURL=suspension.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suspension.d.ts","sourceRoot":"","sources":["../../src/replica/suspension.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,MAAM,IAAI,CAQ5C;AAED,qDAAqD;AACrD,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|