@mysten-incubation/devstack 0.0.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/LICENSE +189 -0
- package/README.md +94 -0
- package/dist/_virtual/_rolldown/runtime.mjs +13 -0
- package/dist/api/define-capabilities.d.mts +25 -0
- package/dist/api/define-capabilities.mjs +19 -0
- package/dist/api/define-capabilities.mjs.map +1 -0
- package/dist/api/define-devstack-with.d.mts +41 -0
- package/dist/api/define-devstack-with.mjs +24 -0
- package/dist/api/define-devstack-with.mjs.map +1 -0
- package/dist/api/define-devstack.d.mts +62 -0
- package/dist/api/define-devstack.mjs +108 -0
- package/dist/api/define-devstack.mjs.map +1 -0
- package/dist/api/define-plugin.d.mts +1 -0
- package/dist/api/inference-network.mjs +122 -0
- package/dist/api/inference-network.mjs.map +1 -0
- package/dist/api/mode-narrowed-factory.d.mts +26 -0
- package/dist/api/mode-narrowed-factory.mjs +8 -0
- package/dist/api/mode-narrowed-factory.mjs.map +1 -0
- package/dist/api/plugin-errors.mjs +10 -0
- package/dist/api/plugin-errors.mjs.map +1 -0
- package/dist/api/run-stack.d.mts +82 -0
- package/dist/api/run-stack.mjs +127 -0
- package/dist/api/run-stack.mjs.map +1 -0
- package/dist/build-integrations/playwright/config.d.mts +92 -0
- package/dist/build-integrations/playwright/config.mjs +71 -0
- package/dist/build-integrations/playwright/config.mjs.map +1 -0
- package/dist/build-integrations/playwright/errors.d.mts +82 -0
- package/dist/build-integrations/playwright/errors.mjs +43 -0
- package/dist/build-integrations/playwright/errors.mjs.map +1 -0
- package/dist/build-integrations/playwright/global-setup.d.mts +64 -0
- package/dist/build-integrations/playwright/global-setup.mjs +44 -0
- package/dist/build-integrations/playwright/global-setup.mjs.map +1 -0
- package/dist/build-integrations/playwright/index.d.mts +6 -0
- package/dist/build-integrations/playwright/index.mjs +6 -0
- package/dist/build-integrations/playwright/stack-context.d.mts +95 -0
- package/dist/build-integrations/playwright/stack-context.mjs +277 -0
- package/dist/build-integrations/playwright/stack-context.mjs.map +1 -0
- package/dist/build-integrations/playwright/wallet-context.d.mts +87 -0
- package/dist/build-integrations/playwright/wallet-context.mjs +148 -0
- package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -0
- package/dist/build-integrations/runtime/cold-start-url.d.mts +67 -0
- package/dist/build-integrations/runtime/cold-start-url.mjs +56 -0
- package/dist/build-integrations/runtime/cold-start-url.mjs.map +1 -0
- package/dist/build-integrations/runtime/dapp-kit-slot.mjs +10 -0
- package/dist/build-integrations/runtime/dapp-kit-slot.mjs.map +1 -0
- package/dist/build-integrations/runtime/discover.d.mts +78 -0
- package/dist/build-integrations/runtime/discover.mjs +124 -0
- package/dist/build-integrations/runtime/discover.mjs.map +1 -0
- package/dist/build-integrations/runtime/endpoint-registry.d.mts +26 -0
- package/dist/build-integrations/runtime/endpoint-registry.mjs +41 -0
- package/dist/build-integrations/runtime/endpoint-registry.mjs.map +1 -0
- package/dist/build-integrations/runtime/errors.d.mts +64 -0
- package/dist/build-integrations/runtime/errors.mjs +51 -0
- package/dist/build-integrations/runtime/errors.mjs.map +1 -0
- package/dist/build-integrations/runtime/index.d.mts +7 -0
- package/dist/build-integrations/runtime/index.mjs +6 -0
- package/dist/build-integrations/runtime/read-stack-context.d.mts +38 -0
- package/dist/build-integrations/runtime/read-stack-context.mjs +130 -0
- package/dist/build-integrations/runtime/read-stack-context.mjs.map +1 -0
- package/dist/build-integrations/runtime/stack-context.d.mts +53 -0
- package/dist/build-integrations/vitest/config.d.mts +62 -0
- package/dist/build-integrations/vitest/config.mjs +80 -0
- package/dist/build-integrations/vitest/config.mjs.map +1 -0
- package/dist/build-integrations/vitest/env.d.mts +48 -0
- package/dist/build-integrations/vitest/env.mjs +50 -0
- package/dist/build-integrations/vitest/env.mjs.map +1 -0
- package/dist/build-integrations/vitest/errors.d.mts +44 -0
- package/dist/build-integrations/vitest/errors.mjs +18 -0
- package/dist/build-integrations/vitest/errors.mjs.map +1 -0
- package/dist/build-integrations/vitest/index.d.mts +6 -0
- package/dist/build-integrations/vitest/index.mjs +6 -0
- package/dist/build-integrations/vitest/setup.d.mts +53 -0
- package/dist/build-integrations/vitest/setup.mjs +56 -0
- package/dist/build-integrations/vitest/setup.mjs.map +1 -0
- package/dist/build-integrations/vitest/stack-context.d.mts +58 -0
- package/dist/build-integrations/vitest/stack-context.mjs +67 -0
- package/dist/build-integrations/vitest/stack-context.mjs.map +1 -0
- package/dist/cli/main.d.mts +5 -0
- package/dist/cli/main.mjs +586 -0
- package/dist/cli/main.mjs.map +1 -0
- package/dist/cli/prune-direct.mjs +216 -0
- package/dist/cli/prune-direct.mjs.map +1 -0
- package/dist/cli/snapshot-reader.mjs +73 -0
- package/dist/cli/snapshot-reader.mjs.map +1 -0
- package/dist/cli/up-lifecycle.mjs +28 -0
- package/dist/cli/up-lifecycle.mjs.map +1 -0
- package/dist/contracts/capability-decl.d.mts +42 -0
- package/dist/contracts/chain-probe.d.mts +26 -0
- package/dist/contracts/chain-probe.mjs +8 -0
- package/dist/contracts/chain-probe.mjs.map +1 -0
- package/dist/contracts/codegenable.d.mts +43 -0
- package/dist/contracts/container-runtime.d.mts +245 -0
- package/dist/contracts/liveness-classifier.d.mts +19 -0
- package/dist/contracts/network-resolver.d.mts +15 -0
- package/dist/contracts/network-resolver.mjs +7 -0
- package/dist/contracts/network-resolver.mjs.map +1 -0
- package/dist/contracts/projection.d.mts +15 -0
- package/dist/contracts/routable.d.mts +53 -0
- package/dist/contracts/snapshotable.d.mts +39 -0
- package/dist/contracts/strategy-contributor.d.mts +26 -0
- package/dist/index.d.mts +89 -0
- package/dist/index.mjs +37 -0
- package/dist/orchestrators/codegen/bindings.d.mts +2 -0
- package/dist/orchestrators/codegen/bindings.mjs +340 -0
- package/dist/orchestrators/codegen/bindings.mjs.map +1 -0
- package/dist/orchestrators/codegen/emit.mjs +56 -0
- package/dist/orchestrators/codegen/emit.mjs.map +1 -0
- package/dist/orchestrators/codegen/errors.d.mts +1 -0
- package/dist/orchestrators/codegen/errors.mjs +66 -0
- package/dist/orchestrators/codegen/errors.mjs.map +1 -0
- package/dist/orchestrators/codegen/extras.mjs +16 -0
- package/dist/orchestrators/codegen/extras.mjs.map +1 -0
- package/dist/orchestrators/codegen/format.mjs +109 -0
- package/dist/orchestrators/codegen/format.mjs.map +1 -0
- package/dist/orchestrators/codegen/gitignore.mjs +67 -0
- package/dist/orchestrators/codegen/gitignore.mjs.map +1 -0
- package/dist/orchestrators/codegen/paths.d.mts +1 -0
- package/dist/orchestrators/codegen/paths.mjs +33 -0
- package/dist/orchestrators/codegen/paths.mjs.map +1 -0
- package/dist/orchestrators/codegen/permissions.mjs +6 -0
- package/dist/orchestrators/codegen/permissions.mjs.map +1 -0
- package/dist/orchestrators/codegen/service.d.mts +1 -0
- package/dist/orchestrators/codegen/service.mjs +276 -0
- package/dist/orchestrators/codegen/service.mjs.map +1 -0
- package/dist/orchestrators/router/cleanup.mjs +58 -0
- package/dist/orchestrators/router/cleanup.mjs.map +1 -0
- package/dist/orchestrators/router/cors.mjs +31 -0
- package/dist/orchestrators/router/cors.mjs.map +1 -0
- package/dist/orchestrators/router/entrypoints.d.mts +1 -0
- package/dist/orchestrators/router/entrypoints.mjs +80 -0
- package/dist/orchestrators/router/entrypoints.mjs.map +1 -0
- package/dist/orchestrators/router/errors.d.mts +1 -0
- package/dist/orchestrators/router/errors.mjs +103 -0
- package/dist/orchestrators/router/errors.mjs.map +1 -0
- package/dist/orchestrators/router/file-provider.d.mts +1 -0
- package/dist/orchestrators/router/file-provider.mjs +320 -0
- package/dist/orchestrators/router/file-provider.mjs.map +1 -0
- package/dist/orchestrators/router/hostname.d.mts +1 -0
- package/dist/orchestrators/router/hostname.mjs +107 -0
- package/dist/orchestrators/router/hostname.mjs.map +1 -0
- package/dist/orchestrators/router/index.d.mts +1 -0
- package/dist/orchestrators/router/profile.d.mts +1 -0
- package/dist/orchestrators/router/profile.mjs +109 -0
- package/dist/orchestrators/router/profile.mjs.map +1 -0
- package/dist/orchestrators/router/service.d.mts +3 -0
- package/dist/orchestrators/router/service.mjs +421 -0
- package/dist/orchestrators/router/service.mjs.map +1 -0
- package/dist/orchestrators/router/traefik-container.d.mts +1 -0
- package/dist/orchestrators/router/traefik-container.mjs +229 -0
- package/dist/orchestrators/router/traefik-container.mjs.map +1 -0
- package/dist/orchestrators/runtime-composition.d.mts +10 -0
- package/dist/orchestrators/runtime-composition.mjs +168 -0
- package/dist/orchestrators/runtime-composition.mjs.map +1 -0
- package/dist/orchestrators/snapshot/capture.d.mts +1 -0
- package/dist/orchestrators/snapshot/capture.mjs +350 -0
- package/dist/orchestrators/snapshot/capture.mjs.map +1 -0
- package/dist/orchestrators/snapshot/descriptor.d.mts +1 -0
- package/dist/orchestrators/snapshot/descriptor.mjs +109 -0
- package/dist/orchestrators/snapshot/descriptor.mjs.map +1 -0
- package/dist/orchestrators/snapshot/identity-guard.d.mts +1 -0
- package/dist/orchestrators/snapshot/identity-guard.mjs +132 -0
- package/dist/orchestrators/snapshot/identity-guard.mjs.map +1 -0
- package/dist/orchestrators/snapshot/image-bundle-tags.mjs +207 -0
- package/dist/orchestrators/snapshot/image-bundle-tags.mjs.map +1 -0
- package/dist/orchestrators/snapshot/index.d.mts +1 -0
- package/dist/orchestrators/snapshot/integrity.d.mts +1 -0
- package/dist/orchestrators/snapshot/integrity.mjs +74 -0
- package/dist/orchestrators/snapshot/integrity.mjs.map +1 -0
- package/dist/orchestrators/snapshot/prune.d.mts +1 -0
- package/dist/orchestrators/snapshot/prune.mjs +110 -0
- package/dist/orchestrators/snapshot/prune.mjs.map +1 -0
- package/dist/orchestrators/snapshot/restore.d.mts +1 -0
- package/dist/orchestrators/snapshot/restore.mjs +404 -0
- package/dist/orchestrators/snapshot/restore.mjs.map +1 -0
- package/dist/orchestrators/snapshot/service.d.mts +1 -0
- package/dist/orchestrators/snapshot/service.mjs +296 -0
- package/dist/orchestrators/snapshot/service.mjs.map +1 -0
- package/dist/orchestrators/snapshot/state-document.mjs +18 -0
- package/dist/orchestrators/snapshot/state-document.mjs.map +1 -0
- package/dist/orchestrators/snapshot/wipe.d.mts +1 -0
- package/dist/orchestrators/snapshot/wipe.mjs +59 -0
- package/dist/orchestrators/snapshot/wipe.mjs.map +1 -0
- package/dist/plugins/account/codegen.d.mts +12 -0
- package/dist/plugins/account/codegen.mjs +22 -0
- package/dist/plugins/account/codegen.mjs.map +1 -0
- package/dist/plugins/account/errors.d.mts +44 -0
- package/dist/plugins/account/errors.mjs +16 -0
- package/dist/plugins/account/errors.mjs.map +1 -0
- package/dist/plugins/account/funding.d.mts +94 -0
- package/dist/plugins/account/funding.mjs +199 -0
- package/dist/plugins/account/funding.mjs.map +1 -0
- package/dist/plugins/account/index.d.mts +54 -0
- package/dist/plugins/account/index.mjs +151 -0
- package/dist/plugins/account/index.mjs.map +1 -0
- package/dist/plugins/account/keypair.d.mts +32 -0
- package/dist/plugins/account/keypair.mjs +99 -0
- package/dist/plugins/account/keypair.mjs.map +1 -0
- package/dist/plugins/account/lease.mjs +21 -0
- package/dist/plugins/account/lease.mjs.map +1 -0
- package/dist/plugins/account/registry.d.mts +33 -0
- package/dist/plugins/account/registry.mjs +36 -0
- package/dist/plugins/account/registry.mjs.map +1 -0
- package/dist/plugins/account/service.d.mts +104 -0
- package/dist/plugins/account/service.mjs +405 -0
- package/dist/plugins/account/service.mjs.map +1 -0
- package/dist/plugins/account/snapshot.mjs +33 -0
- package/dist/plugins/account/snapshot.mjs.map +1 -0
- package/dist/plugins/account/variants/env.mjs +24 -0
- package/dist/plugins/account/variants/env.mjs.map +1 -0
- package/dist/plugins/account/variants/ephemeral.mjs +72 -0
- package/dist/plugins/account/variants/ephemeral.mjs.map +1 -0
- package/dist/plugins/account/variants/impersonate.d.mts +16 -0
- package/dist/plugins/account/variants/impersonate.mjs +48 -0
- package/dist/plugins/account/variants/impersonate.mjs.map +1 -0
- package/dist/plugins/account/variants/inline.mjs +13 -0
- package/dist/plugins/account/variants/inline.mjs.map +1 -0
- package/dist/plugins/account/variants/keystore.mjs +93 -0
- package/dist/plugins/account/variants/keystore.mjs.map +1 -0
- package/dist/plugins/account/variants/signer.mjs +31 -0
- package/dist/plugins/account/variants/signer.mjs.map +1 -0
- package/dist/plugins/action/build-context.d.mts +41 -0
- package/dist/plugins/action/discriminator.d.mts +20 -0
- package/dist/plugins/action/discriminator.mjs +13 -0
- package/dist/plugins/action/discriminator.mjs.map +1 -0
- package/dist/plugins/action/errors.d.mts +31 -0
- package/dist/plugins/action/errors.mjs +13 -0
- package/dist/plugins/action/errors.mjs.map +1 -0
- package/dist/plugins/action/execute.d.mts +2 -0
- package/dist/plugins/action/execute.mjs +145 -0
- package/dist/plugins/action/execute.mjs.map +1 -0
- package/dist/plugins/action/index.d.mts +56 -0
- package/dist/plugins/action/index.mjs +82 -0
- package/dist/plugins/action/index.mjs.map +1 -0
- package/dist/plugins/action/service.d.mts +26 -0
- package/dist/plugins/action/service.mjs +84 -0
- package/dist/plugins/action/service.mjs.map +1 -0
- package/dist/plugins/coin/address-resolution.d.mts +34 -0
- package/dist/plugins/coin/address-resolution.mjs +80 -0
- package/dist/plugins/coin/address-resolution.mjs.map +1 -0
- package/dist/plugins/coin/codegen.d.mts +16 -0
- package/dist/plugins/coin/codegen.mjs +21 -0
- package/dist/plugins/coin/codegen.mjs.map +1 -0
- package/dist/plugins/coin/discovery.d.mts +26 -0
- package/dist/plugins/coin/discovery.mjs +112 -0
- package/dist/plugins/coin/discovery.mjs.map +1 -0
- package/dist/plugins/coin/errors.d.mts +48 -0
- package/dist/plugins/coin/errors.mjs +13 -0
- package/dist/plugins/coin/errors.mjs.map +1 -0
- package/dist/plugins/coin/index.d.mts +95 -0
- package/dist/plugins/coin/index.mjs +172 -0
- package/dist/plugins/coin/index.mjs.map +1 -0
- package/dist/plugins/coin/metadata.d.mts +15 -0
- package/dist/plugins/coin/metadata.mjs +99 -0
- package/dist/plugins/coin/metadata.mjs.map +1 -0
- package/dist/plugins/coin/mint.d.mts +34 -0
- package/dist/plugins/coin/mint.mjs +164 -0
- package/dist/plugins/coin/mint.mjs.map +1 -0
- package/dist/plugins/coin/registry.d.mts +1 -0
- package/dist/plugins/coin/registry.mjs +37 -0
- package/dist/plugins/coin/registry.mjs.map +1 -0
- package/dist/plugins/coin/service.d.mts +47 -0
- package/dist/plugins/coin/service.mjs +51 -0
- package/dist/plugins/coin/service.mjs.map +1 -0
- package/dist/plugins/coin/snapshot.mjs +19 -0
- package/dist/plugins/coin/snapshot.mjs.map +1 -0
- package/dist/plugins/coin/type-strings.mjs +49 -0
- package/dist/plugins/coin/type-strings.mjs.map +1 -0
- package/dist/plugins/deepbook/codegen.d.mts +39 -0
- package/dist/plugins/deepbook/codegen.mjs +15 -0
- package/dist/plugins/deepbook/codegen.mjs.map +1 -0
- package/dist/plugins/deepbook/deploy.mjs +437 -0
- package/dist/plugins/deepbook/deploy.mjs.map +1 -0
- package/dist/plugins/deepbook/errors.d.mts +29 -0
- package/dist/plugins/deepbook/errors.mjs +26 -0
- package/dist/plugins/deepbook/errors.mjs.map +1 -0
- package/dist/plugins/deepbook/faucet-strategy.d.mts +8 -0
- package/dist/plugins/deepbook/faucet-strategy.mjs +81 -0
- package/dist/plugins/deepbook/faucet-strategy.mjs.map +1 -0
- package/dist/plugins/deepbook/index.d.mts +171 -0
- package/dist/plugins/deepbook/index.mjs +359 -0
- package/dist/plugins/deepbook/index.mjs.map +1 -0
- package/dist/plugins/deepbook/plugin-key.mjs +7 -0
- package/dist/plugins/deepbook/plugin-key.mjs.map +1 -0
- package/dist/plugins/deepbook/pyth/index.mjs +226 -0
- package/dist/plugins/deepbook/pyth/index.mjs.map +1 -0
- package/dist/plugins/deepbook/routable.mjs +21 -0
- package/dist/plugins/deepbook/routable.mjs.map +1 -0
- package/dist/plugins/deepbook/snapshot.mjs +49 -0
- package/dist/plugins/deepbook/snapshot.mjs.map +1 -0
- package/dist/plugins/deepbook/types.d.mts +125 -0
- package/dist/plugins/deepbook/types.mjs +12 -0
- package/dist/plugins/deepbook/types.mjs.map +1 -0
- package/dist/plugins/faucet/dispatcher.d.mts +9 -0
- package/dist/plugins/faucet/dispatcher.mjs +13 -0
- package/dist/plugins/faucet/dispatcher.mjs.map +1 -0
- package/dist/plugins/faucet/errors.d.mts +86 -0
- package/dist/plugins/faucet/errors.mjs +19 -0
- package/dist/plugins/faucet/errors.mjs.map +1 -0
- package/dist/plugins/faucet/http.mjs +127 -0
- package/dist/plugins/faucet/http.mjs.map +1 -0
- package/dist/plugins/faucet/index.d.mts +43 -0
- package/dist/plugins/faucet/index.mjs +42 -0
- package/dist/plugins/faucet/index.mjs.map +1 -0
- package/dist/plugins/faucet/service.d.mts +20 -0
- package/dist/plugins/faucet/strategies/sui-local.d.mts +23 -0
- package/dist/plugins/faucet/strategies/sui-local.mjs +29 -0
- package/dist/plugins/faucet/strategies/sui-local.mjs.map +1 -0
- package/dist/plugins/host-service/errors.d.mts +27 -0
- package/dist/plugins/host-service/errors.mjs +14 -0
- package/dist/plugins/host-service/errors.mjs.map +1 -0
- package/dist/plugins/host-service/index.d.mts +10 -0
- package/dist/plugins/host-service/index.mjs +48 -0
- package/dist/plugins/host-service/index.mjs.map +1 -0
- package/dist/plugins/host-service/routable.mjs +24 -0
- package/dist/plugins/host-service/routable.mjs.map +1 -0
- package/dist/plugins/host-service/service.d.mts +49 -0
- package/dist/plugins/host-service/service.mjs +375 -0
- package/dist/plugins/host-service/service.mjs.map +1 -0
- package/dist/plugins/package/build.d.mts +1 -0
- package/dist/plugins/package/build.mjs +24 -0
- package/dist/plugins/package/build.mjs.map +1 -0
- package/dist/plugins/package/codegen.d.mts +19 -0
- package/dist/plugins/package/codegen.mjs +41 -0
- package/dist/plugins/package/codegen.mjs.map +1 -0
- package/dist/plugins/package/dep-resolution.mjs +10 -0
- package/dist/plugins/package/dep-resolution.mjs.map +1 -0
- package/dist/plugins/package/errors.d.mts +34 -0
- package/dist/plugins/package/errors.mjs +13 -0
- package/dist/plugins/package/errors.mjs.map +1 -0
- package/dist/plugins/package/index.d.mts +109 -0
- package/dist/plugins/package/index.mjs +207 -0
- package/dist/plugins/package/index.mjs.map +1 -0
- package/dist/plugins/package/mode-known.mjs +41 -0
- package/dist/plugins/package/mode-known.mjs.map +1 -0
- package/dist/plugins/package/mode-local.d.mts +1 -0
- package/dist/plugins/package/mode-local.mjs +183 -0
- package/dist/plugins/package/mode-local.mjs.map +1 -0
- package/dist/plugins/package/publish-executor.mjs +202 -0
- package/dist/plugins/package/publish-executor.mjs.map +1 -0
- package/dist/plugins/package/publish-output.d.mts +28 -0
- package/dist/plugins/package/publish-output.mjs +45 -0
- package/dist/plugins/package/publish-output.mjs.map +1 -0
- package/dist/plugins/package/registry.d.mts +25 -0
- package/dist/plugins/package/registry.mjs +30 -0
- package/dist/plugins/package/registry.mjs.map +1 -0
- package/dist/plugins/package/service.mjs +20 -0
- package/dist/plugins/package/service.mjs.map +1 -0
- package/dist/plugins/package/snapshot.mjs +25 -0
- package/dist/plugins/package/snapshot.mjs.map +1 -0
- package/dist/plugins/postgres/codegen.mjs +42 -0
- package/dist/plugins/postgres/codegen.mjs.map +1 -0
- package/dist/plugins/postgres/connection.d.mts +33 -0
- package/dist/plugins/postgres/connection.mjs +19 -0
- package/dist/plugins/postgres/connection.mjs.map +1 -0
- package/dist/plugins/postgres/db-ensure.mjs +100 -0
- package/dist/plugins/postgres/db-ensure.mjs.map +1 -0
- package/dist/plugins/postgres/errors.d.mts +55 -0
- package/dist/plugins/postgres/errors.mjs +29 -0
- package/dist/plugins/postgres/errors.mjs.map +1 -0
- package/dist/plugins/postgres/index.d.mts +37 -0
- package/dist/plugins/postgres/index.mjs +75 -0
- package/dist/plugins/postgres/index.mjs.map +1 -0
- package/dist/plugins/postgres/routable.mjs +33 -0
- package/dist/plugins/postgres/routable.mjs.map +1 -0
- package/dist/plugins/postgres/service.d.mts +50 -0
- package/dist/plugins/postgres/service.mjs +145 -0
- package/dist/plugins/postgres/service.mjs.map +1 -0
- package/dist/plugins/postgres/snapshot.d.mts +1 -0
- package/dist/plugins/postgres/snapshot.mjs +32 -0
- package/dist/plugins/postgres/snapshot.mjs.map +1 -0
- package/dist/plugins/router-entrypoints.mjs +21 -0
- package/dist/plugins/router-entrypoints.mjs.map +1 -0
- package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs +59 -0
- package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs.map +1 -0
- package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs +132 -0
- package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs.map +1 -0
- package/dist/plugins/seal/codegen.d.mts +19 -0
- package/dist/plugins/seal/codegen.mjs +16 -0
- package/dist/plugins/seal/codegen.mjs.map +1 -0
- package/dist/plugins/seal/config-render.mjs +82 -0
- package/dist/plugins/seal/config-render.mjs.map +1 -0
- package/dist/plugins/seal/deploy.mjs +198 -0
- package/dist/plugins/seal/deploy.mjs.map +1 -0
- package/dist/plugins/seal/errors.d.mts +52 -0
- package/dist/plugins/seal/errors.mjs +19 -0
- package/dist/plugins/seal/errors.mjs.map +1 -0
- package/dist/plugins/seal/index.d.mts +161 -0
- package/dist/plugins/seal/index.mjs +235 -0
- package/dist/plugins/seal/index.mjs.map +1 -0
- package/dist/plugins/seal/key-manager.d.mts +22 -0
- package/dist/plugins/seal/key-manager.mjs +22 -0
- package/dist/plugins/seal/key-manager.mjs.map +1 -0
- package/dist/plugins/seal/key-server.mjs +175 -0
- package/dist/plugins/seal/key-server.mjs.map +1 -0
- package/dist/plugins/seal/keygen.mjs +96 -0
- package/dist/plugins/seal/keygen.mjs.map +1 -0
- package/dist/plugins/seal/mode/fork-known.d.mts +8 -0
- package/dist/plugins/seal/mode/fork-known.mjs +23 -0
- package/dist/plugins/seal/mode/fork-known.mjs.map +1 -0
- package/dist/plugins/seal/mode/live.d.mts +18 -0
- package/dist/plugins/seal/mode/live.mjs +64 -0
- package/dist/plugins/seal/mode/live.mjs.map +1 -0
- package/dist/plugins/seal/mode/local-keygen.mjs +180 -0
- package/dist/plugins/seal/mode/local-keygen.mjs.map +1 -0
- package/dist/plugins/seal/plugin-key.mjs +7 -0
- package/dist/plugins/seal/plugin-key.mjs.map +1 -0
- package/dist/plugins/seal/registry-publish.d.mts +43 -0
- package/dist/plugins/seal/registry-publish.mjs +9 -0
- package/dist/plugins/seal/registry-publish.mjs.map +1 -0
- package/dist/plugins/seal/routable.mjs +57 -0
- package/dist/plugins/seal/routable.mjs.map +1 -0
- package/dist/plugins/seal/service.mjs +17 -0
- package/dist/plugins/seal/service.mjs.map +1 -0
- package/dist/plugins/seal/snapshot.mjs +51 -0
- package/dist/plugins/seal/snapshot.mjs.map +1 -0
- package/dist/plugins/sui/auto-tick.mjs +45 -0
- package/dist/plugins/sui/auto-tick.mjs.map +1 -0
- package/dist/plugins/sui/chain-build-container.d.mts +1 -0
- package/dist/plugins/sui/chain-probe.d.mts +85 -0
- package/dist/plugins/sui/chain-probe.mjs +104 -0
- package/dist/plugins/sui/chain-probe.mjs.map +1 -0
- package/dist/plugins/sui/codegen.d.mts +14 -0
- package/dist/plugins/sui/codegen.mjs +26 -0
- package/dist/plugins/sui/codegen.mjs.map +1 -0
- package/dist/plugins/sui/errors.d.mts +74 -0
- package/dist/plugins/sui/errors.mjs +28 -0
- package/dist/plugins/sui/errors.mjs.map +1 -0
- package/dist/plugins/sui/fork-orchestration.mjs +24 -0
- package/dist/plugins/sui/fork-orchestration.mjs.map +1 -0
- package/dist/plugins/sui/fork-transaction.mjs +96 -0
- package/dist/plugins/sui/fork-transaction.mjs.map +1 -0
- package/dist/plugins/sui/index.d.mts +318 -0
- package/dist/plugins/sui/index.mjs +182 -0
- package/dist/plugins/sui/index.mjs.map +1 -0
- package/dist/plugins/sui/mode/external.mjs +60 -0
- package/dist/plugins/sui/mode/external.mjs.map +1 -0
- package/dist/plugins/sui/mode/fork.mjs +283 -0
- package/dist/plugins/sui/mode/fork.mjs.map +1 -0
- package/dist/plugins/sui/mode/live.mjs +103 -0
- package/dist/plugins/sui/mode/live.mjs.map +1 -0
- package/dist/plugins/sui/mode/local.mjs +293 -0
- package/dist/plugins/sui/mode/local.mjs.map +1 -0
- package/dist/plugins/sui/mode/shared-boot.mjs +254 -0
- package/dist/plugins/sui/mode/shared-boot.mjs.map +1 -0
- package/dist/plugins/sui/mode/shared.d.mts +103 -0
- package/dist/plugins/sui/mode/shared.mjs +12 -0
- package/dist/plugins/sui/mode/shared.mjs.map +1 -0
- package/dist/plugins/sui/mode/spec.d.mts +94 -0
- package/dist/plugins/sui/network-resolver.d.mts +23 -0
- package/dist/plugins/sui/routable.mjs +88 -0
- package/dist/plugins/sui/routable.mjs.map +1 -0
- package/dist/plugins/sui/seed-objects.d.mts +18 -0
- package/dist/plugins/sui/seed-objects.mjs +25 -0
- package/dist/plugins/sui/seed-objects.mjs.map +1 -0
- package/dist/plugins/sui/service.mjs +38 -0
- package/dist/plugins/sui/service.mjs.map +1 -0
- package/dist/plugins/sui/snapshot.mjs +53 -0
- package/dist/plugins/sui/snapshot.mjs.map +1 -0
- package/dist/plugins/wallet/codegen.d.mts +33 -0
- package/dist/plugins/wallet/codegen.mjs +34 -0
- package/dist/plugins/wallet/codegen.mjs.map +1 -0
- package/dist/plugins/wallet/errors.d.mts +66 -0
- package/dist/plugins/wallet/errors.mjs +16 -0
- package/dist/plugins/wallet/errors.mjs.map +1 -0
- package/dist/plugins/wallet/index.d.mts +63 -0
- package/dist/plugins/wallet/index.mjs +126 -0
- package/dist/plugins/wallet/index.mjs.map +1 -0
- package/dist/plugins/wallet/origin-policy.d.mts +1 -0
- package/dist/plugins/wallet/origin-policy.mjs +65 -0
- package/dist/plugins/wallet/origin-policy.mjs.map +1 -0
- package/dist/plugins/wallet/pairing.d.mts +11 -0
- package/dist/plugins/wallet/pairing.mjs +125 -0
- package/dist/plugins/wallet/pairing.mjs.map +1 -0
- package/dist/plugins/wallet/protocol.d.mts +1 -0
- package/dist/plugins/wallet/protocol.mjs +96 -0
- package/dist/plugins/wallet/protocol.mjs.map +1 -0
- package/dist/plugins/wallet/routable.mjs +32 -0
- package/dist/plugins/wallet/routable.mjs.map +1 -0
- package/dist/plugins/wallet/server.d.mts +12 -0
- package/dist/plugins/wallet/server.mjs +317 -0
- package/dist/plugins/wallet/server.mjs.map +1 -0
- package/dist/plugins/wallet/service.d.mts +68 -0
- package/dist/plugins/wallet/service.mjs +97 -0
- package/dist/plugins/wallet/service.mjs.map +1 -0
- package/dist/plugins/wallet/snapshot.d.mts +1 -0
- package/dist/plugins/wallet/snapshot.mjs +14 -0
- package/dist/plugins/wallet/snapshot.mjs.map +1 -0
- package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs +42 -0
- package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs.map +1 -0
- package/dist/plugins/walrus/codegen.d.mts +38 -0
- package/dist/plugins/walrus/codegen.mjs +34 -0
- package/dist/plugins/walrus/codegen.mjs.map +1 -0
- package/dist/plugins/walrus/deploy-paths.mjs +14 -0
- package/dist/plugins/walrus/deploy-paths.mjs.map +1 -0
- package/dist/plugins/walrus/deploy.d.mts +1 -0
- package/dist/plugins/walrus/deploy.mjs +224 -0
- package/dist/plugins/walrus/deploy.mjs.map +1 -0
- package/dist/plugins/walrus/errors.d.mts +38 -0
- package/dist/plugins/walrus/errors.mjs +26 -0
- package/dist/plugins/walrus/errors.mjs.map +1 -0
- package/dist/plugins/walrus/faucet-strategy.d.mts +12 -0
- package/dist/plugins/walrus/faucet-strategy.mjs +62 -0
- package/dist/plugins/walrus/faucet-strategy.mjs.map +1 -0
- package/dist/plugins/walrus/index.d.mts +177 -0
- package/dist/plugins/walrus/index.mjs +284 -0
- package/dist/plugins/walrus/index.mjs.map +1 -0
- package/dist/plugins/walrus/mode/known-deploy.d.mts +25 -0
- package/dist/plugins/walrus/mode/known-deploy.mjs +71 -0
- package/dist/plugins/walrus/mode/known-deploy.mjs.map +1 -0
- package/dist/plugins/walrus/mode/local-cluster.d.mts +34 -0
- package/dist/plugins/walrus/mode/local-cluster.mjs +153 -0
- package/dist/plugins/walrus/mode/local-cluster.mjs.map +1 -0
- package/dist/plugins/walrus/plugin-key.mjs +7 -0
- package/dist/plugins/walrus/plugin-key.mjs.map +1 -0
- package/dist/plugins/walrus/registry-publish.d.mts +24 -0
- package/dist/plugins/walrus/registry-publish.mjs +7 -0
- package/dist/plugins/walrus/registry-publish.mjs.map +1 -0
- package/dist/plugins/walrus/routable.mjs +99 -0
- package/dist/plugins/walrus/routable.mjs.map +1 -0
- package/dist/plugins/walrus/service.mjs +20 -0
- package/dist/plugins/walrus/service.mjs.map +1 -0
- package/dist/plugins/walrus/snapshot.mjs +53 -0
- package/dist/plugins/walrus/snapshot.mjs.map +1 -0
- package/dist/plugins/walrus/storage-nodes.d.mts +15 -0
- package/dist/plugins/walrus/storage-nodes.mjs +154 -0
- package/dist/plugins/walrus/storage-nodes.mjs.map +1 -0
- package/dist/plugins/walrus/wal-swap.d.mts +2 -0
- package/dist/plugins/walrus/wal-swap.mjs +58 -0
- package/dist/plugins/walrus/wal-swap.mjs.map +1 -0
- package/dist/primitives/artifact-publisher.d.mts +12 -0
- package/dist/primitives/cache.d.mts +1 -0
- package/dist/runtime/built-in-plugin-layers.mjs +49 -0
- package/dist/runtime/built-in-plugin-layers.mjs.map +1 -0
- package/dist/runtime/docker/client.d.mts +2 -0
- package/dist/runtime/docker/client.mjs +54 -0
- package/dist/runtime/docker/client.mjs.map +1 -0
- package/dist/runtime/docker/container.d.mts +1 -0
- package/dist/runtime/docker/container.mjs +562 -0
- package/dist/runtime/docker/container.mjs.map +1 -0
- package/dist/runtime/docker/errors.d.mts +1 -0
- package/dist/runtime/docker/errors.mjs +187 -0
- package/dist/runtime/docker/errors.mjs.map +1 -0
- package/dist/runtime/docker/exec.d.mts +1 -0
- package/dist/runtime/docker/exec.mjs +63 -0
- package/dist/runtime/docker/exec.mjs.map +1 -0
- package/dist/runtime/docker/image.d.mts +1 -0
- package/dist/runtime/docker/image.mjs +278 -0
- package/dist/runtime/docker/image.mjs.map +1 -0
- package/dist/runtime/docker/index.d.mts +1 -0
- package/dist/runtime/docker/inventory.d.mts +1 -0
- package/dist/runtime/docker/inventory.mjs +167 -0
- package/dist/runtime/docker/inventory.mjs.map +1 -0
- package/dist/runtime/docker/labels.d.mts +1 -0
- package/dist/runtime/docker/labels.mjs +97 -0
- package/dist/runtime/docker/labels.mjs.map +1 -0
- package/dist/runtime/docker/logs.d.mts +1 -0
- package/dist/runtime/docker/logs.mjs +34 -0
- package/dist/runtime/docker/logs.mjs.map +1 -0
- package/dist/runtime/docker/network.d.mts +1 -0
- package/dist/runtime/docker/network.mjs +168 -0
- package/dist/runtime/docker/network.mjs.map +1 -0
- package/dist/runtime/docker/service.d.mts +9 -0
- package/dist/runtime/docker/service.mjs +266 -0
- package/dist/runtime/docker/service.mjs.map +1 -0
- package/dist/runtime/docker/sweep.d.mts +1 -0
- package/dist/runtime/docker/sweep.mjs +220 -0
- package/dist/runtime/docker/sweep.mjs.map +1 -0
- package/dist/runtime/docker/volume.d.mts +1 -0
- package/dist/runtime/docker/volume.mjs +24 -0
- package/dist/runtime/docker/volume.mjs.map +1 -0
- package/dist/runtime/docker/wrap.d.mts +1 -0
- package/dist/runtime/docker/wrap.mjs +131 -0
- package/dist/runtime/docker/wrap.mjs.map +1 -0
- package/dist/substrate/brand.d.mts +24 -0
- package/dist/substrate/brand.mjs +14 -0
- package/dist/substrate/brand.mjs.map +1 -0
- package/dist/substrate/cross-process.d.mts +1 -0
- package/dist/substrate/cross-process.mjs +28 -0
- package/dist/substrate/cross-process.mjs.map +1 -0
- package/dist/substrate/events.d.mts +117 -0
- package/dist/substrate/identity.d.mts +13 -0
- package/dist/substrate/lifecycle.d.mts +12 -0
- package/dist/substrate/manifest.d.mts +39 -0
- package/dist/substrate/manifest.mjs +33 -0
- package/dist/substrate/manifest.mjs.map +1 -0
- package/dist/substrate/network.d.mts +34 -0
- package/dist/substrate/options.d.mts +23 -0
- package/dist/substrate/plugin.d.mts +101 -0
- package/dist/substrate/plugin.mjs +61 -0
- package/dist/substrate/plugin.mjs.map +1 -0
- package/dist/substrate/projection.d.mts +100 -0
- package/dist/substrate/runtime/artifact-publisher/index.mjs +76 -0
- package/dist/substrate/runtime/artifact-publisher/index.mjs.map +1 -0
- package/dist/substrate/runtime/atomic-write.mjs +106 -0
- package/dist/substrate/runtime/atomic-write.mjs.map +1 -0
- package/dist/substrate/runtime/cache/index.d.mts +1 -0
- package/dist/substrate/runtime/cache/schema.d.mts +1 -0
- package/dist/substrate/runtime/cache/schema.mjs +22 -0
- package/dist/substrate/runtime/cache/schema.mjs.map +1 -0
- package/dist/substrate/runtime/cache/service.d.mts +1 -0
- package/dist/substrate/runtime/cache/service.mjs +89 -0
- package/dist/substrate/runtime/cache/service.mjs.map +1 -0
- package/dist/substrate/runtime/capability-sinks/index.d.mts +1 -0
- package/dist/substrate/runtime/capability-sinks/layer.d.mts +1 -0
- package/dist/substrate/runtime/capability-sinks/layer.mjs +31 -0
- package/dist/substrate/runtime/capability-sinks/layer.mjs.map +1 -0
- package/dist/substrate/runtime/capability-sinks/service.d.mts +36 -0
- package/dist/substrate/runtime/capability-sinks/service.mjs +74 -0
- package/dist/substrate/runtime/capability-sinks/service.mjs.map +1 -0
- package/dist/substrate/runtime/config-validation.d.mts +38 -0
- package/dist/substrate/runtime/config-validation.mjs +137 -0
- package/dist/substrate/runtime/config-validation.mjs.map +1 -0
- package/dist/substrate/runtime/context-helpers.mjs +32 -0
- package/dist/substrate/runtime/context-helpers.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/command-channel/channel.mjs +128 -0
- package/dist/substrate/runtime/cross-process/command-channel/channel.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs +136 -0
- package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs +49 -0
- package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/command-channel/runtime-control-lock.mjs +9 -0
- package/dist/substrate/runtime/cross-process/command-channel/runtime-control-lock.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/liveness.mjs +119 -0
- package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/roster.mjs +275 -0
- package/dist/substrate/runtime/cross-process/roster.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/snapshot-reservation.d.mts +1 -0
- package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs +117 -0
- package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/stack-lock.d.mts +1 -0
- package/dist/substrate/runtime/cross-process/stack-lock.mjs +142 -0
- package/dist/substrate/runtime/cross-process/stack-lock.mjs.map +1 -0
- package/dist/substrate/runtime/current-plugin.mjs +15 -0
- package/dist/substrate/runtime/current-plugin.mjs.map +1 -0
- package/dist/substrate/runtime/errors.d.mts +1 -0
- package/dist/substrate/runtime/errors.mjs +76 -0
- package/dist/substrate/runtime/errors.mjs.map +1 -0
- package/dist/substrate/runtime/host-tree-tar/index.mjs +364 -0
- package/dist/substrate/runtime/host-tree-tar/index.mjs.map +1 -0
- package/dist/substrate/runtime/http-probe.d.mts +35 -0
- package/dist/substrate/runtime/http-probe.mjs +65 -0
- package/dist/substrate/runtime/http-probe.mjs.map +1 -0
- package/dist/substrate/runtime/lease-broker/index.d.mts +1 -0
- package/dist/substrate/runtime/lease-broker/service.d.mts +64 -0
- package/dist/substrate/runtime/lease-broker/service.mjs +155 -0
- package/dist/substrate/runtime/lease-broker/service.mjs.map +1 -0
- package/dist/substrate/runtime/lifecycle/dep-graph.d.mts +1 -0
- package/dist/substrate/runtime/lifecycle/dep-graph.mjs +138 -0
- package/dist/substrate/runtime/lifecycle/dep-graph.mjs.map +1 -0
- package/dist/substrate/runtime/lifecycle/index.d.mts +1 -0
- package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs +31 -0
- package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs.map +1 -0
- package/dist/substrate/runtime/lifecycle/plugin-registry.d.mts +1 -0
- package/dist/substrate/runtime/lifecycle/plugin-registry.mjs +133 -0
- package/dist/substrate/runtime/lifecycle/plugin-registry.mjs.map +1 -0
- package/dist/substrate/runtime/lifecycle/ready-gate.d.mts +1 -0
- package/dist/substrate/runtime/lifecycle/ready-gate.mjs +34 -0
- package/dist/substrate/runtime/lifecycle/ready-gate.mjs.map +1 -0
- package/dist/substrate/runtime/lifecycle/selective-restart.d.mts +1 -0
- package/dist/substrate/runtime/lifecycle/selective-restart.mjs +43 -0
- package/dist/substrate/runtime/lifecycle/selective-restart.mjs.map +1 -0
- package/dist/substrate/runtime/lifecycle/signals.d.mts +1 -0
- package/dist/substrate/runtime/lifecycle/signals.mjs +64 -0
- package/dist/substrate/runtime/lifecycle/signals.mjs.map +1 -0
- package/dist/substrate/runtime/lifecycle/state-machine.d.mts +1 -0
- package/dist/substrate/runtime/lifecycle/state-machine.mjs +38 -0
- package/dist/substrate/runtime/lifecycle/state-machine.mjs.map +1 -0
- package/dist/substrate/runtime/lifecycle/watch-attribution.d.mts +1 -0
- package/dist/substrate/runtime/lifecycle/watch-attribution.mjs +27 -0
- package/dist/substrate/runtime/lifecycle/watch-attribution.mjs.map +1 -0
- package/dist/substrate/runtime/managed-container.d.mts +30 -0
- package/dist/substrate/runtime/managed-container.mjs +32 -0
- package/dist/substrate/runtime/managed-container.mjs.map +1 -0
- package/dist/substrate/runtime/manifest/manifest.mjs +73 -0
- package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -0
- package/dist/substrate/runtime/mode-errors.d.mts +36 -0
- package/dist/substrate/runtime/observability/cascade-formatter.d.mts +1 -0
- package/dist/substrate/runtime/observability/cascade-formatter.mjs +135 -0
- package/dist/substrate/runtime/observability/cascade-formatter.mjs.map +1 -0
- package/dist/substrate/runtime/observability/formatter-registry.d.mts +1 -0
- package/dist/substrate/runtime/observability/formatter-registry.mjs +65 -0
- package/dist/substrate/runtime/observability/formatter-registry.mjs.map +1 -0
- package/dist/substrate/runtime/observability/index.d.mts +3 -0
- package/dist/substrate/runtime/observability/logger.d.mts +58 -0
- package/dist/substrate/runtime/observability/logger.mjs +89 -0
- package/dist/substrate/runtime/observability/logger.mjs.map +1 -0
- package/dist/substrate/runtime/observability/pretty-error.d.mts +1 -0
- package/dist/substrate/runtime/observability/pretty-error.mjs +119 -0
- package/dist/substrate/runtime/observability/pretty-error.mjs.map +1 -0
- package/dist/substrate/runtime/observability/process-lines.d.mts +31 -0
- package/dist/substrate/runtime/observability/process-lines.mjs +40 -0
- package/dist/substrate/runtime/observability/process-lines.mjs.map +1 -0
- package/dist/substrate/runtime/observability/redaction.d.mts +28 -0
- package/dist/substrate/runtime/observability/redaction.mjs +45 -0
- package/dist/substrate/runtime/observability/redaction.mjs.map +1 -0
- package/dist/substrate/runtime/observability/spans.d.mts +1 -0
- package/dist/substrate/runtime/observability/spans.mjs +87 -0
- package/dist/substrate/runtime/observability/spans.mjs.map +1 -0
- package/dist/substrate/runtime/observability/subprocess-capture.d.mts +2 -0
- package/dist/substrate/runtime/observability/subprocess-capture.mjs +82 -0
- package/dist/substrate/runtime/observability/subprocess-capture.mjs.map +1 -0
- package/dist/substrate/runtime/paths.d.mts +17 -0
- package/dist/substrate/runtime/paths.mjs +61 -0
- package/dist/substrate/runtime/paths.mjs.map +1 -0
- package/dist/substrate/runtime/port-broker/index.d.mts +1 -0
- package/dist/substrate/runtime/port-broker/service.d.mts +1 -0
- package/dist/substrate/runtime/port-broker/service.mjs +319 -0
- package/dist/substrate/runtime/port-broker/service.mjs.map +1 -0
- package/dist/substrate/runtime/post-acquire-tasks.d.mts +1 -0
- package/dist/substrate/runtime/post-acquire-tasks.mjs +34 -0
- package/dist/substrate/runtime/post-acquire-tasks.mjs.map +1 -0
- package/dist/substrate/runtime/probes.d.mts +51 -0
- package/dist/substrate/runtime/probes.mjs +84 -0
- package/dist/substrate/runtime/probes.mjs.map +1 -0
- package/dist/substrate/runtime/process-supervisor.d.mts +57 -0
- package/dist/substrate/runtime/process-supervisor.mjs +73 -0
- package/dist/substrate/runtime/process-supervisor.mjs.map +1 -0
- package/dist/substrate/runtime/projection/operational-endpoints.mjs +44 -0
- package/dist/substrate/runtime/projection/operational-endpoints.mjs.map +1 -0
- package/dist/substrate/runtime/projection/persisted.mjs +195 -0
- package/dist/substrate/runtime/projection/persisted.mjs.map +1 -0
- package/dist/substrate/runtime/projection/state-ref.mjs +48 -0
- package/dist/substrate/runtime/projection/state-ref.mjs.map +1 -0
- package/dist/substrate/runtime/projection/update.mjs +200 -0
- package/dist/substrate/runtime/projection/update.mjs.map +1 -0
- package/dist/substrate/runtime/retry-policy.d.mts +18 -0
- package/dist/substrate/runtime/retry-policy.mjs +16 -0
- package/dist/substrate/runtime/retry-policy.mjs.map +1 -0
- package/dist/substrate/runtime/run.mjs +86 -0
- package/dist/substrate/runtime/run.mjs.map +1 -0
- package/dist/substrate/runtime/runtime-decode.d.mts +32 -0
- package/dist/substrate/runtime/runtime-decode.mjs +53 -0
- package/dist/substrate/runtime/runtime-decode.mjs.map +1 -0
- package/dist/substrate/runtime/scoped-http-server.mjs +36 -0
- package/dist/substrate/runtime/scoped-http-server.mjs.map +1 -0
- package/dist/substrate/runtime/scoped-ref-map/service.mjs +83 -0
- package/dist/substrate/runtime/scoped-ref-map/service.mjs.map +1 -0
- package/dist/substrate/runtime/stage-and-swap/index.d.mts +1 -0
- package/dist/substrate/runtime/stage-and-swap/index.mjs +131 -0
- package/dist/substrate/runtime/stage-and-swap/index.mjs.map +1 -0
- package/dist/substrate/runtime/state-store/schema.mjs +36 -0
- package/dist/substrate/runtime/state-store/schema.mjs.map +1 -0
- package/dist/substrate/runtime/strategy-registry/chain-probe-for.d.mts +1 -0
- package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs +22 -0
- package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs.map +1 -0
- package/dist/substrate/runtime/strategy-registry/faucet-capability-for.d.mts +1 -0
- package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs +30 -0
- package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs.map +1 -0
- package/dist/substrate/runtime/strategy-registry/index.d.mts +1 -0
- package/dist/substrate/runtime/strategy-registry/service.d.mts +1 -0
- package/dist/substrate/runtime/strategy-registry/service.mjs +67 -0
- package/dist/substrate/runtime/strategy-registry/service.mjs.map +1 -0
- package/dist/substrate/runtime/sui-execute/index.d.mts +11 -0
- package/dist/substrate/runtime/sui-execute/index.mjs +144 -0
- package/dist/substrate/runtime/sui-execute/index.mjs.map +1 -0
- package/dist/substrate/runtime/sui-move-build/index.d.mts +1 -0
- package/dist/substrate/runtime/sui-move-build/index.mjs +283 -0
- package/dist/substrate/runtime/sui-move-build/index.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor.d.mts +1 -0
- package/dist/substrate/runtime/supervisor.mjs +831 -0
- package/dist/substrate/runtime/supervisor.mjs.map +1 -0
- package/dist/surfaces/cli/command-tree.mjs +276 -0
- package/dist/surfaces/cli/command-tree.mjs.map +1 -0
- package/dist/surfaces/cli/commands/config.mjs +31 -0
- package/dist/surfaces/cli/commands/config.mjs.map +1 -0
- package/dist/surfaces/cli/commands/confirm-node.mjs +26 -0
- package/dist/surfaces/cli/commands/confirm-node.mjs.map +1 -0
- package/dist/surfaces/cli/commands/confirm.mjs +26 -0
- package/dist/surfaces/cli/commands/confirm.mjs.map +1 -0
- package/dist/surfaces/cli/commands/doctor-probes.mjs +452 -0
- package/dist/surfaces/cli/commands/doctor-probes.mjs.map +1 -0
- package/dist/surfaces/cli/commands/doctor.mjs +38 -0
- package/dist/surfaces/cli/commands/doctor.mjs.map +1 -0
- package/dist/surfaces/cli/commands/prune-picker.mjs +347 -0
- package/dist/surfaces/cli/commands/prune-picker.mjs.map +1 -0
- package/dist/surfaces/cli/commands/prune.mjs +178 -0
- package/dist/surfaces/cli/commands/prune.mjs.map +1 -0
- package/dist/surfaces/cli/commands/snapshot.mjs +141 -0
- package/dist/surfaces/cli/commands/snapshot.mjs.map +1 -0
- package/dist/surfaces/cli/commands/status.mjs +95 -0
- package/dist/surfaces/cli/commands/status.mjs.map +1 -0
- package/dist/surfaces/cli/commands/supervisor-presence.mjs +33 -0
- package/dist/surfaces/cli/commands/supervisor-presence.mjs.map +1 -0
- package/dist/surfaces/cli/commands/wipe.mjs +28 -0
- package/dist/surfaces/cli/commands/wipe.mjs.map +1 -0
- package/dist/surfaces/cli/envelope.mjs +43 -0
- package/dist/surfaces/cli/envelope.mjs.map +1 -0
- package/dist/surfaces/cli/errors.mjs +110 -0
- package/dist/surfaces/cli/errors.mjs.map +1 -0
- package/dist/surfaces/cli/flags.mjs +56 -0
- package/dist/surfaces/cli/flags.mjs.map +1 -0
- package/dist/surfaces/cli/index.mjs +418 -0
- package/dist/surfaces/cli/index.mjs.map +1 -0
- package/dist/surfaces/cli/output.mjs +115 -0
- package/dist/surfaces/cli/output.mjs.map +1 -0
- package/dist/surfaces/cli/sysexits.mjs +139 -0
- package/dist/surfaces/cli/sysexits.mjs.map +1 -0
- package/dist/surfaces/tui/app.mjs +104 -0
- package/dist/surfaces/tui/app.mjs.map +1 -0
- package/dist/surfaces/tui/dashboard.mjs +261 -0
- package/dist/surfaces/tui/dashboard.mjs.map +1 -0
- package/dist/surfaces/tui/display-derivation.mjs +395 -0
- package/dist/surfaces/tui/display-derivation.mjs.map +1 -0
- package/dist/surfaces/tui/errors.mjs +11 -0
- package/dist/surfaces/tui/errors.mjs.map +1 -0
- package/dist/surfaces/tui/event-log.mjs +155 -0
- package/dist/surfaces/tui/event-log.mjs.map +1 -0
- package/dist/surfaces/tui/heartbeat.mjs +33 -0
- package/dist/surfaces/tui/heartbeat.mjs.map +1 -0
- package/dist/surfaces/tui/index.mjs +50 -0
- package/dist/surfaces/tui/index.mjs.map +1 -0
- package/dist/surfaces/tui/input.mjs +104 -0
- package/dist/surfaces/tui/input.mjs.map +1 -0
- package/dist/surfaces/tui/mode-detect.mjs +32 -0
- package/dist/surfaces/tui/mode-detect.mjs.map +1 -0
- package/dist/surfaces/tui/mount-ink.mjs +31 -0
- package/dist/surfaces/tui/mount-ink.mjs.map +1 -0
- package/dist/surfaces/tui/plain-renderer.mjs +170 -0
- package/dist/surfaces/tui/plain-renderer.mjs.map +1 -0
- package/dist/surfaces/tui/resource-table.mjs +507 -0
- package/dist/surfaces/tui/resource-table.mjs.map +1 -0
- package/images/_shared/signal-forward.sh +77 -0
- package/images/postgres/Dockerfile +32 -0
- package/images/seal/Dockerfile +68 -0
- package/images/seal/entrypoint.sh +65 -0
- package/images/sui/Dockerfile +73 -0
- package/images/sui/entrypoint.sh +244 -0
- package/images/sui-fork/Dockerfile +53 -0
- package/images/sui-fork/entrypoint.sh +51 -0
- package/images/walrus/Dockerfile +122 -0
- package/images/walrus/deploy-walrus.sh +305 -0
- package/images/walrus/run-walrus.sh +53 -0
- package/package.json +94 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/substrate/runtime/host-tree-tar/index.ts"],"sourcesContent":["// host-tree-tar — stream a host filesystem subtree as a tar archive.\n//\n// Architecture §\"Substrate primitives roster\" (Open slot O21):\n// snapshot orchestrator hard-fails today on the `tarHostTree` /\n// `untarHostTree` stubs. This primitive fills the slot.\n//\n// Design:\n// - Stream-based — `tarHostTree` returns a `Stream<Uint8Array>`;\n// `untarHostTree` consumes one. The entire tree NEVER materialises\n// in memory (snapshot trees can hold gigabytes of cache state).\n// - Mode-preserving — the snapshot orchestrator carries 0o600 /\n// 0o700 mode bits on secret material (postgres keys, account\n// keystores). System `tar -p` (extract) and `tar --no-recursion`\n// (control) preserve them natively. We do NOT roll our own\n// archive writer (a TypeScript-side reimplementation would have\n// to track POSIX mode flags + extended attributes; system tar is\n// correct by default).\n// - Subprocess-based — spawn `tar` (BSD-tar on macOS, GNU-tar on\n// Linux); both honour the flags used here (`-c` / `-x` / `-f -`).\n// Exit code != 0 surfaces as `TarSpawnFailed`.\n//\n// Boundary:\n// - Substrate-level: this is a generic filesystem primitive; no\n// plugin names referenced.\n// - The caller controls which subtrees are archived (snapshot\n// orchestrator passes a list of relative paths under a parent\n// dir). Permission preservation is unconditional.\n\nimport { spawn } from 'node:child_process';\n\nimport { Effect, Schema, Scope, Stream } from 'effect';\n\nimport {\n\tawaitProcessExit,\n\tdescribeProcessExitStatus,\n\ttype ManagedProcessChild,\n\ttype ManagedProcessExitStatus,\n} from '../process-supervisor.ts';\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\n/** Tagged failure during tar / untar. `stage` discriminates the\n * precise step (spawn vs stream-read vs exit-code).\n *\n * `cause` carries the underlying error verbatim; the cascade\n * formatter walks it. */\nexport class HostTreeTarError extends Schema.TaggedErrorClass<HostTreeTarError>()(\n\t'HostTreeTarError',\n\t{\n\t\tstage: Schema.Literals([\n\t\t\t'spawn',\n\t\t\t'stream-stdout',\n\t\t\t'stream-stdin',\n\t\t\t'exit-code',\n\t\t\t'entry-validation',\n\t\t\t'no-subtrees',\n\t\t]),\n\t\toperation: Schema.Literals(['tar', 'untar']),\n\t\tdetail: Schema.String,\n\t\t/** Captured stderr from the `tar` subprocess (last ~4 KB). */\n\t\tstderrTail: Schema.optional(Schema.String),\n\t\texitCode: Schema.optional(Schema.Number),\n\t\tcause: Schema.optional(Schema.Defect),\n\t},\n) {}\n\n// ---------------------------------------------------------------------------\n// Tar one or more subtrees → Stream<Uint8Array>\n// ---------------------------------------------------------------------------\n\n/** Spec for `tarHostTree`.\n *\n * - `parentDir`: directory the relative paths are anchored under.\n * `tar -C <parentDir>` runs the archive with this as cwd, so the\n * archive entries are stored relative to `parentDir`.\n * - `relPaths`: subtree paths relative to `parentDir`. Empty list\n * fails fast (`stage: 'no-subtrees'`) — the caller is responsible\n * for the host-tree-included guard. */\nexport interface TarHostTreeSpec {\n\treadonly parentDir: string;\n\treadonly relPaths: ReadonlyArray<string>;\n}\n\nconst TAR_STDERR_TAIL_BYTES = 4096;\n\nconst collectStderrTail = (chunks: Array<Uint8Array>): string => {\n\tif (chunks.length === 0) return '';\n\tlet total = 0;\n\tfor (let i = chunks.length - 1; i >= 0; i--) {\n\t\ttotal += chunks[i]!.length;\n\t\tif (total >= TAR_STDERR_TAIL_BYTES) break;\n\t}\n\tconst bytes = Buffer.concat(chunks);\n\treturn bytes.subarray(Math.max(0, bytes.length - TAR_STDERR_TAIL_BYTES)).toString('utf8');\n};\n\nconst tarExitError = (\n\toperation: 'tar' | 'untar',\n\tstatus: ManagedProcessExitStatus,\n\tstderrChunks: Array<Uint8Array>,\n): HostTreeTarError =>\n\tnew HostTreeTarError({\n\t\tstage: 'exit-code',\n\t\toperation,\n\t\texitCode: status.code ?? -1,\n\t\tdetail: `'tar' exited with ${describeProcessExitStatus(status)}`,\n\t\tstderrTail: collectStderrTail(stderrChunks),\n\t});\n\nconst TAR_BLOCK_SIZE = 512;\nconst MAX_TAR_EXTENDED_PATH_BYTES = 1024 * 1024;\n\nconst bytesToString = (bytes: Uint8Array): string => {\n\tconst nul = bytes.indexOf(0);\n\tconst end = nul === -1 ? bytes.length : nul;\n\treturn Buffer.from(bytes.subarray(0, end)).toString('utf8');\n};\n\nconst concatBytes = (a: Uint8Array, b: Uint8Array): Uint8Array => {\n\tif (a.length === 0) return b;\n\tif (b.length === 0) return a;\n\tconst out = new Uint8Array(a.length + b.length);\n\tout.set(a, 0);\n\tout.set(b, a.length);\n\treturn out;\n};\n\nconst consumeBytes = (buffer: Uint8Array, count: number): Uint8Array => buffer.subarray(count);\n\nconst isZeroBlock = (block: Uint8Array): boolean => block.every((byte) => byte === 0);\n\nconst parseTarSize = (header: Uint8Array): number | null => {\n\tconst raw = bytesToString(header.subarray(124, 136)).trim();\n\tif (raw === '') return 0;\n\tif (!/^[0-7]+$/.test(raw)) return null;\n\tconst parsed = Number.parseInt(raw, 8);\n\treturn Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : null;\n};\n\nconst tarPathFromHeader = (header: Uint8Array): string => {\n\tconst name = bytesToString(header.subarray(0, 100));\n\tconst prefix = bytesToString(header.subarray(345, 500));\n\treturn prefix === '' ? name : `${prefix}/${name}`;\n};\n\nconst tarLinkPathFromHeader = (header: Uint8Array): string =>\n\tbytesToString(header.subarray(157, 257));\n\nconst trimExtendedPath = (bytes: Uint8Array): string => {\n\tconst value = Buffer.from(bytes).toString('utf8').replace(/\\n$/g, '');\n\tlet end = value.length;\n\twhile (end > 0 && value.charCodeAt(end - 1) === 0) end -= 1;\n\treturn value.slice(0, end);\n};\n\nconst isSafeArchivePath = (entryPath: string): boolean => {\n\tif (\n\t\tentryPath === '' ||\n\t\tentryPath === '.' ||\n\t\tentryPath.includes('\\0') ||\n\t\tentryPath.includes('\\\\') ||\n\t\tentryPath.startsWith('/') ||\n\t\t/^[A-Za-z]:/.test(entryPath)\n\t) {\n\t\treturn false;\n\t}\n\tconst meaningfulSegments = entryPath\n\t\t.split('/')\n\t\t.filter((segment) => segment !== '' && segment !== '.');\n\treturn meaningfulSegments.length > 0 && !meaningfulSegments.includes('..');\n};\n\nconst parsePaxRecords = (bytes: Uint8Array): Record<string, string> => {\n\tconst text = Buffer.from(bytes).toString('utf8');\n\tconst records: Record<string, string> = {};\n\tlet offset = 0;\n\twhile (offset < text.length) {\n\t\tconst space = text.indexOf(' ', offset);\n\t\tif (space === -1) break;\n\t\tconst lengthText = text.slice(offset, space);\n\t\tconst recordLength = Number.parseInt(lengthText, 10);\n\t\tif (!Number.isSafeInteger(recordLength) || recordLength <= 0) break;\n\t\tconst record = text.slice(space + 1, offset + recordLength).replace(/\\n$/g, '');\n\t\tconst eq = record.indexOf('=');\n\t\tif (eq > 0) {\n\t\t\trecords[record.slice(0, eq)] = record.slice(eq + 1);\n\t\t}\n\t\toffset += recordLength;\n\t}\n\treturn records;\n};\n\ninterface TarContentState {\n\treadonly kind: 'pax-local' | 'pax-global' | 'gnu-path' | 'gnu-link';\n\treadonly size: number;\n\treadonly paddedSize: number;\n\treadonly chunks: Array<Uint8Array>;\n\treadonly contentBytesRead: number;\n\treadonly totalBytesRead: number;\n}\n\ninterface TarValidationState {\n\tbuffer: Uint8Array;\n\tskipRemaining: number;\n\tcontent: TarContentState | null;\n\tpendingPath: string | null;\n\tpendingLinkPath: string | null;\n}\n\nconst tarValidationError = (detail: string): HostTreeTarError =>\n\tnew HostTreeTarError({\n\t\tstage: 'entry-validation',\n\t\toperation: 'untar',\n\t\tdetail,\n\t});\n\nconst applyExtendedContent = (\n\tstate: TarValidationState,\n\tcontent: TarContentState,\n): HostTreeTarError | null => {\n\tconst bytes =\n\t\tcontent.chunks.length === 1\n\t\t\t? content.chunks[0]!\n\t\t\t: Buffer.concat(content.chunks.map((chunk) => Buffer.from(chunk)));\n\tif (content.kind === 'gnu-path') {\n\t\tstate.pendingPath = trimExtendedPath(bytes);\n\t\treturn null;\n\t}\n\tif (content.kind === 'gnu-link') {\n\t\tstate.pendingLinkPath = trimExtendedPath(bytes);\n\t\treturn null;\n\t}\n\tconst records = parsePaxRecords(bytes);\n\tif (\n\t\tcontent.kind === 'pax-global' &&\n\t\t(records.path !== undefined || records.linkpath !== undefined)\n\t) {\n\t\treturn tarValidationError('global pax path/linkpath records are not supported in snapshots');\n\t}\n\tif (content.kind === 'pax-local') {\n\t\tif (records.path !== undefined) state.pendingPath = records.path;\n\t\tif (records.linkpath !== undefined) state.pendingLinkPath = records.linkpath;\n\t}\n\treturn null;\n};\n\nconst processTarValidationChunk = (\n\tstate: TarValidationState,\n\tchunk: Uint8Array,\n): HostTreeTarError | null => {\n\tstate.buffer = concatBytes(state.buffer, chunk);\n\twhile (state.buffer.length > 0) {\n\t\tif (state.content !== null) {\n\t\t\tconst content = state.content;\n\t\t\tconst remaining = content.paddedSize - content.totalBytesRead;\n\t\t\tconst take = Math.min(remaining, state.buffer.length);\n\t\t\tconst contentTake = Math.max(0, Math.min(take, content.size - content.contentBytesRead));\n\t\t\tif (contentTake > 0) {\n\t\t\t\tcontent.chunks.push(state.buffer.subarray(0, contentTake));\n\t\t\t}\n\t\t\tstate.content = {\n\t\t\t\t...content,\n\t\t\t\tcontentBytesRead: content.contentBytesRead + contentTake,\n\t\t\t\ttotalBytesRead: content.totalBytesRead + take,\n\t\t\t};\n\t\t\tstate.buffer = consumeBytes(state.buffer, take);\n\t\t\tif (state.content.totalBytesRead === state.content.paddedSize) {\n\t\t\t\tconst completed = state.content;\n\t\t\t\tstate.content = null;\n\t\t\t\tconst error = applyExtendedContent(state, completed);\n\t\t\t\tif (error !== null) return error;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (state.skipRemaining > 0) {\n\t\t\tconst take = Math.min(state.skipRemaining, state.buffer.length);\n\t\t\tstate.skipRemaining -= take;\n\t\t\tstate.buffer = consumeBytes(state.buffer, take);\n\t\t\tcontinue;\n\t\t}\n\t\tif (state.buffer.length < TAR_BLOCK_SIZE) return null;\n\t\tconst header = state.buffer.subarray(0, TAR_BLOCK_SIZE);\n\t\tstate.buffer = consumeBytes(state.buffer, TAR_BLOCK_SIZE);\n\t\tif (isZeroBlock(header)) continue;\n\n\t\tconst size = parseTarSize(header);\n\t\tif (size === null) return tarValidationError('tar entry has an invalid size header');\n\t\tconst paddedSize = Math.ceil(size / TAR_BLOCK_SIZE) * TAR_BLOCK_SIZE;\n\t\tconst typeflag = String.fromCharCode(header[156] ?? 0).replace('\\0', '');\n\t\tif (typeflag === 'x' || typeflag === 'g' || typeflag === 'L' || typeflag === 'K') {\n\t\t\tif (size > MAX_TAR_EXTENDED_PATH_BYTES) {\n\t\t\t\treturn tarValidationError('tar extended path record is too large');\n\t\t\t}\n\t\t\tstate.content = {\n\t\t\t\tkind:\n\t\t\t\t\ttypeflag === 'x'\n\t\t\t\t\t\t? 'pax-local'\n\t\t\t\t\t\t: typeflag === 'g'\n\t\t\t\t\t\t\t? 'pax-global'\n\t\t\t\t\t\t\t: typeflag === 'L'\n\t\t\t\t\t\t\t\t? 'gnu-path'\n\t\t\t\t\t\t\t\t: 'gnu-link',\n\t\t\t\tsize,\n\t\t\t\tpaddedSize,\n\t\t\t\tchunks: [],\n\t\t\t\tcontentBytesRead: 0,\n\t\t\t\ttotalBytesRead: 0,\n\t\t\t};\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst entryPath = state.pendingPath ?? tarPathFromHeader(header);\n\t\tstate.pendingPath = null;\n\t\tif (!isSafeArchivePath(entryPath)) {\n\t\t\treturn tarValidationError(`unsafe tar entry path: ${entryPath}`);\n\t\t}\n\t\tconst linkPath = state.pendingLinkPath ?? tarLinkPathFromHeader(header);\n\t\tstate.pendingLinkPath = null;\n\t\tif ((typeflag === '1' || typeflag === '2') && !isSafeArchivePath(linkPath)) {\n\t\t\treturn tarValidationError(`unsafe tar link target: ${linkPath}`);\n\t\t}\n\t\tstate.skipRemaining = paddedSize;\n\t}\n\treturn null;\n};\n\nconst finishTarValidation = (state: TarValidationState): HostTreeTarError | null => {\n\tif (state.content !== null) return tarValidationError('tar ended inside an extended header');\n\tif (state.skipRemaining !== 0) return tarValidationError('tar ended inside file content');\n\tif (state.buffer.length !== 0 && !isZeroBlock(state.buffer)) {\n\t\treturn tarValidationError('tar ended with a partial header');\n\t}\n\treturn null;\n};\n\nexport const validateHostTreeTarEntries = <R>(\n\tstream: Stream.Stream<Uint8Array, HostTreeTarError, R>,\n): Effect.Effect<void, HostTreeTarError, R> =>\n\tEffect.gen(function* () {\n\t\tconst state: TarValidationState = {\n\t\t\tbuffer: new Uint8Array(0),\n\t\t\tskipRemaining: 0,\n\t\t\tcontent: null,\n\t\t\tpendingPath: null,\n\t\t\tpendingLinkPath: null,\n\t\t};\n\t\tyield* Stream.runForEach(stream, (chunk) => {\n\t\t\tconst error = processTarValidationChunk(state, chunk);\n\t\t\treturn error === null ? Effect.void : Effect.fail(error);\n\t\t});\n\t\tconst finalError = finishTarValidation(state);\n\t\tif (finalError !== null) return yield* Effect.fail(finalError);\n\t});\n\n/**\n * Stream the tar archive of `relPaths` (relative to `parentDir`) as a\n * `Stream<Uint8Array>`. Mode bits are preserved.\n *\n * The subprocess is bound to the consuming Scope: closing the scope\n * before the stream finishes kills the subprocess and surfaces\n * `stream-stdout` if the consumer was mid-read.\n *\n * Caller consumes via `Stream.run(...)` — e.g. pipe to a file via\n * `Stream.run(stream, Sink.fromWritable(() => createWriteStream(...)))`\n * or to an in-memory chunk array for the integrity hash.\n */\nexport const tarHostTree = (\n\tspec: TarHostTreeSpec,\n): Stream.Stream<Uint8Array, HostTreeTarError, never> =>\n\t// `Stream.unwrap` provides the channel's surrounding scope to the\n\t// inner Effect (see `effect/src/Channel.ts:7918` —\n\t// `Scope.provide(scope)`), so `Effect.addFinalizer` below binds to\n\t// the stream's lifecycle: the subprocess kill-on-close fires when\n\t// the stream terminates. The R-channel `Exclude<R, Scope>` reads\n\t// \"scope satisfied by the stream\" — not \"scope dropped\".\n\tStream.unwrap(\n\t\tEffect.gen(function* () {\n\t\t\tif (spec.relPaths.length === 0) {\n\t\t\t\treturn Stream.fail(\n\t\t\t\t\tnew HostTreeTarError({\n\t\t\t\t\t\tstage: 'no-subtrees',\n\t\t\t\t\t\toperation: 'tar',\n\t\t\t\t\t\tdetail: 'tarHostTree called with empty relPaths list',\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// `-c` create, `-f -` write to stdout, `-C <dir>` cd-before,\n\t\t\t// `-p` preserve permissions (matches BSD-tar + GNU-tar). The\n\t\t\t// subprocess emits its own bytes; we don't apply any\n\t\t\t// transcoding.\n\t\t\tconst args = ['-c', '-f', '-', '-C', spec.parentDir, '-p', ...spec.relPaths];\n\t\t\tconst child = yield* Effect.try({\n\t\t\t\ttry: () =>\n\t\t\t\t\tspawn('tar', args, {\n\t\t\t\t\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\t\t\t\t}),\n\t\t\t\tcatch: (cause) =>\n\t\t\t\t\tnew HostTreeTarError({\n\t\t\t\t\t\tstage: 'spawn',\n\t\t\t\t\t\toperation: 'tar',\n\t\t\t\t\t\tdetail: `failed to spawn 'tar ${args.join(' ')}'`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t}),\n\t\t\t});\n\n\t\t\t// Stderr collection lives outside the data stream — we\n\t\t\t// accumulate the tail so an exit-code failure carries\n\t\t\t// actionable context. The stderr listener is removed on\n\t\t\t// scope close.\n\t\t\tconst stderrChunks: Array<Uint8Array> = [];\n\t\t\tconst onStderr = (chunk: Buffer): void => {\n\t\t\t\tstderrChunks.push(chunk);\n\t\t\t\tif (stderrChunks.length > 256) stderrChunks.splice(0, stderrChunks.length - 256);\n\t\t\t};\n\t\t\tchild.stderr?.on('data', onStderr);\n\n\t\t\t// Finalise the subprocess on scope close: kill if alive,\n\t\t\t// drop listeners either way.\n\t\t\tyield* Effect.addFinalizer(() =>\n\t\t\t\tEffect.sync(() => {\n\t\t\t\t\tchild.stderr?.off('data', onStderr);\n\t\t\t\t\tif (child.exitCode === null && child.signalCode === null) {\n\t\t\t\t\t\tchild.kill('SIGKILL');\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\t// Wrap stdout (a Node Readable) as a Stream<Uint8Array>.\n\t\t\t// `Stream.fromReadable` is the substrate-blessed shape.\n\t\t\tconst stdout = child.stdout;\n\t\t\tif (stdout === null) {\n\t\t\t\treturn Stream.fail(\n\t\t\t\t\tnew HostTreeTarError({\n\t\t\t\t\t\tstage: 'spawn',\n\t\t\t\t\t\toperation: 'tar',\n\t\t\t\t\t\tdetail: `'tar' subprocess produced no stdout pipe`,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Node `Readable` is an `AsyncIterable<Buffer>`; `Buffer`\n\t\t\t// extends `Uint8Array` structurally. The cast asserts the\n\t\t\t// nominal-vs-structural gap at the Node boundary and stays\n\t\t\t// off the user-facing API.\n\t\t\tconst dataStream = Stream.fromAsyncIterable(\n\t\t\t\tstdout as unknown as AsyncIterable<Uint8Array>,\n\t\t\t\t(cause) =>\n\t\t\t\t\tnew HostTreeTarError({\n\t\t\t\t\t\tstage: 'stream-stdout',\n\t\t\t\t\t\toperation: 'tar',\n\t\t\t\t\t\tdetail: `read from tar stdout failed`,\n\t\t\t\t\t\tcause,\n\t\t\t\t\t}),\n\t\t\t);\n\n\t\t\t// After stdout closes, await the subprocess exit and surface\n\t\t\t// non-zero codes with the captured stderr tail. This appends\n\t\t\t// a \"tail\" sub-stream that emits zero bytes but can fail —\n\t\t\t// the consumer's `Stream.run` sees the exit-code failure\n\t\t\t// uniformly with stream-read failures.\n\t\t\tconst exitGate: Stream.Stream<Uint8Array, HostTreeTarError, never> = Stream.fromEffect(\n\t\t\t\tEffect.promise(() => awaitProcessExit(child as ManagedProcessChild)).pipe(\n\t\t\t\t\tEffect.flatMap((status) =>\n\t\t\t\t\t\tstatus.code === 0 && status.signal === null\n\t\t\t\t\t\t\t? Effect.succeed(new Uint8Array(0))\n\t\t\t\t\t\t\t: Effect.fail(tarExitError('tar', status, stderrChunks)),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t).pipe(Stream.filter((bytes) => bytes.length > 0));\n\n\t\t\treturn Stream.concat(dataStream, exitGate);\n\t\t}),\n\t);\n\n// ---------------------------------------------------------------------------\n// Untar a Stream<Uint8Array> into a target directory\n// ---------------------------------------------------------------------------\n\nexport interface UntarHostTreeSpec {\n\treadonly target: string;\n}\n\n/**\n * Extract a tar `Stream<Uint8Array>` into `target`, preserving mode\n * bits. The target directory MUST already exist; the caller is\n * responsible (stage-and-swap creates the staging directory before\n * calling).\n *\n * The subprocess consumes from the stream and writes into `target`;\n * scope close kills the subprocess. The Effect resolves when `tar`\n * exits cleanly (code 0).\n */\nexport const untarHostTree = <R>(\n\tstream: Stream.Stream<Uint8Array, HostTreeTarError, R>,\n\tspec: UntarHostTreeSpec,\n): Effect.Effect<void, HostTreeTarError, R | Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst args = ['-x', '-f', '-', '-C', spec.target, '-p'];\n\t\tconst child = yield* Effect.try({\n\t\t\ttry: () =>\n\t\t\t\tspawn('tar', args, {\n\t\t\t\t\tstdio: ['pipe', 'ignore', 'pipe'],\n\t\t\t\t}),\n\t\t\tcatch: (cause) =>\n\t\t\t\tnew HostTreeTarError({\n\t\t\t\t\tstage: 'spawn',\n\t\t\t\t\toperation: 'untar',\n\t\t\t\t\tdetail: `failed to spawn 'tar ${args.join(' ')}'`,\n\t\t\t\t\tcause,\n\t\t\t\t}),\n\t\t});\n\n\t\tconst stderrChunks: Array<Uint8Array> = [];\n\t\tconst onStderr = (chunk: Buffer): void => {\n\t\t\tstderrChunks.push(chunk);\n\t\t\tif (stderrChunks.length > 256) stderrChunks.splice(0, stderrChunks.length - 256);\n\t\t};\n\t\tchild.stderr?.on('data', onStderr);\n\n\t\tyield* Effect.addFinalizer(() =>\n\t\t\tEffect.sync(() => {\n\t\t\t\tchild.stderr?.off('data', onStderr);\n\t\t\t\tif (child.exitCode === null && child.signalCode === null) {\n\t\t\t\t\tchild.kill('SIGKILL');\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\n\t\tconst stdin = child.stdin;\n\t\tif (stdin === null) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew HostTreeTarError({\n\t\t\t\t\tstage: 'spawn',\n\t\t\t\t\toperation: 'untar',\n\t\t\t\t\tdetail: `'tar' subprocess produced no stdin pipe`,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\tconst validationState: TarValidationState = {\n\t\t\tbuffer: new Uint8Array(0),\n\t\t\tskipRemaining: 0,\n\t\t\tcontent: null,\n\t\t\tpendingPath: null,\n\t\t\tpendingLinkPath: null,\n\t\t};\n\n\t\tconst writeChunk = (chunk: Uint8Array): Effect.Effect<void, HostTreeTarError> =>\n\t\t\tEffect.callback<void, HostTreeTarError>((resume) => {\n\t\t\t\tlet settled = false;\n\t\t\t\tconst settle = (effect: Effect.Effect<void, HostTreeTarError>): void => {\n\t\t\t\t\tif (!settled) {\n\t\t\t\t\t\tsettled = true;\n\t\t\t\t\t\tresume(effect);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tconst onDrain = (): void => settle(Effect.void);\n\t\t\t\tconst ok = stdin.write(chunk, (cause) => {\n\t\t\t\t\tstdin.off('drain', onDrain);\n\t\t\t\t\tif (cause) {\n\t\t\t\t\t\tsettle(\n\t\t\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\t\t\tnew HostTreeTarError({\n\t\t\t\t\t\t\t\t\tstage: 'stream-stdin',\n\t\t\t\t\t\t\t\t\toperation: 'untar',\n\t\t\t\t\t\t\t\t\tdetail: `write to tar stdin failed`,\n\t\t\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsettle(Effect.void);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (!ok) {\n\t\t\t\t\tstdin.once('drain', onDrain);\n\t\t\t\t}\n\t\t\t});\n\n\t\t// Pump the source stream into tar's stdin. Each chunk is\n\t\t// validated before it is handed to the tar subprocess, so unsafe\n\t\t// archive paths are rejected at the extraction boundary even if a\n\t\t// caller skipped any earlier preflight validation.\n\t\tyield* Stream.runForEach(stream, (chunk) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst validationError = processTarValidationChunk(validationState, chunk);\n\t\t\t\tif (validationError !== null) {\n\t\t\t\t\treturn yield* Effect.fail(validationError);\n\t\t\t\t}\n\t\t\t\tyield* writeChunk(chunk);\n\t\t\t}),\n\t\t).pipe(\n\t\t\tEffect.catch((cause) =>\n\t\t\t\tcause instanceof HostTreeTarError\n\t\t\t\t\t? Effect.fail(cause)\n\t\t\t\t\t: Effect.fail(\n\t\t\t\t\t\t\tnew HostTreeTarError({\n\t\t\t\t\t\t\t\tstage: 'stream-stdin',\n\t\t\t\t\t\t\t\toperation: 'untar',\n\t\t\t\t\t\t\t\tdetail: `source stream raised before EOF`,\n\t\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t),\n\t\t);\n\n\t\tconst finalValidationError = finishTarValidation(validationState);\n\t\tif (finalValidationError !== null) {\n\t\t\treturn yield* Effect.fail(finalValidationError);\n\t\t}\n\n\t\t// Close stdin so tar sees EOF and exits.\n\t\tyield* Effect.sync(() => stdin.end());\n\n\t\t// Await exit; non-zero surfaces with stderr tail.\n\t\tconst status = yield* Effect.promise(() => awaitProcessExit(child as ManagedProcessChild));\n\t\tif (status.code !== 0 || status.signal !== null) {\n\t\t\treturn yield* Effect.fail(tarExitError('untar', status, stderrChunks));\n\t\t}\n\t}).pipe(Effect.withSpan('substrate.host-tree-tar.untar'));\n"],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import * as _$effect_Types0 from "effect/Types";
|
|
3
|
+
import * as _$effect_Cause0 from "effect/Cause";
|
|
4
|
+
|
|
5
|
+
//#region src/substrate/runtime/http-probe.d.ts
|
|
6
|
+
declare namespace http_probe_d_exports {
|
|
7
|
+
export { HttpProbeError, HttpProbeFetch, HttpProbeOptions, HttpProbeValidator, waitForHttpEndpoint };
|
|
8
|
+
}
|
|
9
|
+
type HttpProbeFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
10
|
+
type HttpProbeValidator = (response: Response) => boolean | Promise<boolean>;
|
|
11
|
+
interface HttpProbeOptions {
|
|
12
|
+
readonly endpoint: string | URL;
|
|
13
|
+
readonly timeoutMs: number;
|
|
14
|
+
readonly intervalMs?: number;
|
|
15
|
+
readonly requestTimeoutMs?: number;
|
|
16
|
+
readonly requestInit?: Omit<RequestInit, 'signal'>;
|
|
17
|
+
readonly validate?: HttpProbeValidator;
|
|
18
|
+
readonly fetch?: HttpProbeFetch;
|
|
19
|
+
}
|
|
20
|
+
declare const HttpProbeError_base: new <A extends Record<string, any> = {}>(args: _$effect_Types0.VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => _$effect_Cause0.YieldableError & {
|
|
21
|
+
readonly _tag: "HttpProbeError";
|
|
22
|
+
} & Readonly<A>;
|
|
23
|
+
declare class HttpProbeError extends HttpProbeError_base<{
|
|
24
|
+
readonly endpoint: string;
|
|
25
|
+
readonly timeoutMs: number;
|
|
26
|
+
readonly intervalMs: number;
|
|
27
|
+
readonly requestTimeoutMs: number;
|
|
28
|
+
readonly message: string;
|
|
29
|
+
readonly lastStatus?: number;
|
|
30
|
+
readonly lastError?: unknown;
|
|
31
|
+
}> {}
|
|
32
|
+
declare const waitForHttpEndpoint: (options: HttpProbeOptions) => Effect.Effect<void, HttpProbeError>;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { http_probe_d_exports };
|
|
35
|
+
//# sourceMappingURL=http-probe.d.mts.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { __exportAll } from "../../_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
import { ProbeTimeoutError, waitForProbe } from "./probes.mjs";
|
|
3
|
+
import { Data, Effect } from "effect";
|
|
4
|
+
//#region src/substrate/runtime/http-probe.ts
|
|
5
|
+
var http_probe_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
+
HttpProbeError: () => HttpProbeError,
|
|
7
|
+
waitForHttpEndpoint: () => waitForHttpEndpoint
|
|
8
|
+
});
|
|
9
|
+
var HttpProbeError = class extends Data.TaggedError("HttpProbeError") {};
|
|
10
|
+
const DEFAULT_INTERVAL_MS = 250;
|
|
11
|
+
const waitForHttpEndpoint = (options) => Effect.gen(function* () {
|
|
12
|
+
const endpoint = String(options.endpoint);
|
|
13
|
+
const timeoutMs = options.timeoutMs;
|
|
14
|
+
const intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;
|
|
15
|
+
const requestTimeoutMs = options.requestTimeoutMs ?? intervalMs;
|
|
16
|
+
const validate = options.validate ?? ((response) => response.ok);
|
|
17
|
+
const fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
18
|
+
let lastStatus;
|
|
19
|
+
return yield* waitForProbe({
|
|
20
|
+
label: endpoint,
|
|
21
|
+
timeoutMs,
|
|
22
|
+
intervalMs,
|
|
23
|
+
attemptTimeoutMs: requestTimeoutMs,
|
|
24
|
+
probe: () => Effect.tryPromise({
|
|
25
|
+
try: (signal) => fetchImpl(options.endpoint, {
|
|
26
|
+
method: "GET",
|
|
27
|
+
...options.requestInit,
|
|
28
|
+
signal
|
|
29
|
+
}),
|
|
30
|
+
catch: (cause) => cause
|
|
31
|
+
}).pipe(Effect.flatMap((response) => {
|
|
32
|
+
lastStatus = response.status;
|
|
33
|
+
return Effect.tryPromise({
|
|
34
|
+
try: () => Promise.resolve(validate(response)),
|
|
35
|
+
catch: (cause) => cause
|
|
36
|
+
}).pipe(Effect.map((ready) => ready ? true : {
|
|
37
|
+
ready: false,
|
|
38
|
+
detail: { status: response.status }
|
|
39
|
+
}));
|
|
40
|
+
}))
|
|
41
|
+
}).pipe(Effect.mapError((cause) => {
|
|
42
|
+
if (cause instanceof ProbeTimeoutError) return new HttpProbeError({
|
|
43
|
+
endpoint,
|
|
44
|
+
timeoutMs,
|
|
45
|
+
intervalMs,
|
|
46
|
+
requestTimeoutMs,
|
|
47
|
+
message: `HTTP endpoint ${endpoint} did not become ready within ${timeoutMs}ms`,
|
|
48
|
+
...lastStatus === void 0 ? {} : { lastStatus },
|
|
49
|
+
...cause.lastError === void 0 ? {} : { lastError: cause.lastError }
|
|
50
|
+
});
|
|
51
|
+
return new HttpProbeError({
|
|
52
|
+
endpoint,
|
|
53
|
+
timeoutMs,
|
|
54
|
+
intervalMs,
|
|
55
|
+
requestTimeoutMs,
|
|
56
|
+
message: `HTTP endpoint ${endpoint} probe failed`,
|
|
57
|
+
...lastStatus === void 0 ? {} : { lastStatus },
|
|
58
|
+
lastError: cause
|
|
59
|
+
});
|
|
60
|
+
}));
|
|
61
|
+
});
|
|
62
|
+
//#endregion
|
|
63
|
+
export { http_probe_exports, waitForHttpEndpoint };
|
|
64
|
+
|
|
65
|
+
//# sourceMappingURL=http-probe.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-probe.mjs","names":[],"sources":["../../../src/substrate/runtime/http-probe.ts"],"sourcesContent":["import { Data, Effect } from 'effect';\n\nimport { ProbeTimeoutError, waitForProbe } from './probes.ts';\n\nexport type HttpProbeFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\n\nexport type HttpProbeValidator = (response: Response) => boolean | Promise<boolean>;\n\nexport interface HttpProbeOptions {\n\treadonly endpoint: string | URL;\n\treadonly timeoutMs: number;\n\treadonly intervalMs?: number;\n\treadonly requestTimeoutMs?: number;\n\treadonly requestInit?: Omit<RequestInit, 'signal'>;\n\treadonly validate?: HttpProbeValidator;\n\treadonly fetch?: HttpProbeFetch;\n}\n\nexport class HttpProbeError extends Data.TaggedError('HttpProbeError')<{\n\treadonly endpoint: string;\n\treadonly timeoutMs: number;\n\treadonly intervalMs: number;\n\treadonly requestTimeoutMs: number;\n\treadonly message: string;\n\treadonly lastStatus?: number;\n\treadonly lastError?: unknown;\n}> {}\n\nconst DEFAULT_INTERVAL_MS = 250;\n\nexport const waitForHttpEndpoint = (\n\toptions: HttpProbeOptions,\n): Effect.Effect<void, HttpProbeError> =>\n\tEffect.gen(function* () {\n\t\tconst endpoint = String(options.endpoint);\n\t\tconst timeoutMs = options.timeoutMs;\n\t\tconst intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;\n\t\tconst requestTimeoutMs = options.requestTimeoutMs ?? intervalMs;\n\t\tconst validate = options.validate ?? ((response: Response) => response.ok);\n\t\tconst fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);\n\t\tlet lastStatus: number | undefined;\n\n\t\treturn yield* waitForProbe({\n\t\t\tlabel: endpoint,\n\t\t\ttimeoutMs,\n\t\t\tintervalMs,\n\t\t\tattemptTimeoutMs: requestTimeoutMs,\n\t\t\tprobe: () =>\n\t\t\t\tEffect.tryPromise({\n\t\t\t\t\ttry: (signal) =>\n\t\t\t\t\t\tfetchImpl(options.endpoint, {\n\t\t\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\t\t\t...options.requestInit,\n\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t}),\n\t\t\t\t\tcatch: (cause) => cause,\n\t\t\t\t}).pipe(\n\t\t\t\t\tEffect.flatMap((response) => {\n\t\t\t\t\t\tlastStatus = response.status;\n\t\t\t\t\t\treturn Effect.tryPromise({\n\t\t\t\t\t\t\ttry: () => Promise.resolve(validate(response)),\n\t\t\t\t\t\t\tcatch: (cause) => cause,\n\t\t\t\t\t\t}).pipe(\n\t\t\t\t\t\t\tEffect.map((ready) =>\n\t\t\t\t\t\t\t\tready ? true : { ready: false, detail: { status: response.status } },\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t}).pipe(\n\t\t\tEffect.mapError((cause) => {\n\t\t\t\tif (cause instanceof ProbeTimeoutError) {\n\t\t\t\t\treturn new HttpProbeError({\n\t\t\t\t\t\tendpoint,\n\t\t\t\t\t\ttimeoutMs,\n\t\t\t\t\t\tintervalMs,\n\t\t\t\t\t\trequestTimeoutMs,\n\t\t\t\t\t\tmessage: `HTTP endpoint ${endpoint} did not become ready within ${timeoutMs}ms`,\n\t\t\t\t\t\t...(lastStatus === undefined ? {} : { lastStatus }),\n\t\t\t\t\t\t...(cause.lastError === undefined ? {} : { lastError: cause.lastError }),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn new HttpProbeError({\n\t\t\t\t\tendpoint,\n\t\t\t\t\ttimeoutMs,\n\t\t\t\t\tintervalMs,\n\t\t\t\t\trequestTimeoutMs,\n\t\t\t\t\tmessage: `HTTP endpoint ${endpoint} probe failed`,\n\t\t\t\t\t...(lastStatus === undefined ? {} : { lastStatus }),\n\t\t\t\t\tlastError: cause,\n\t\t\t\t});\n\t\t\t}),\n\t\t);\n\t});\n"],"mappings":";;;;;;;;AAkBA,IAAa,iBAAb,cAAoC,KAAK,YAAY,iBAAiB,CAQnE;AAEH,MAAM,sBAAsB;AAE5B,MAAa,uBACZ,YAEA,OAAO,IAAI,aAAa;CACvB,MAAM,WAAW,OAAO,QAAQ,SAAS;CACzC,MAAM,YAAY,QAAQ;CAC1B,MAAM,aAAa,QAAQ,cAAc;CACzC,MAAM,mBAAmB,QAAQ,oBAAoB;CACrD,MAAM,WAAW,QAAQ,cAAc,aAAuB,SAAS;CACvE,MAAM,YAAY,QAAQ,SAAS,WAAW,MAAM,KAAK,WAAW;CACpE,IAAI;AAEJ,QAAO,OAAO,aAAa;EAC1B,OAAO;EACP;EACA;EACA,kBAAkB;EAClB,aACC,OAAO,WAAW;GACjB,MAAM,WACL,UAAU,QAAQ,UAAU;IAC3B,QAAQ;IACR,GAAG,QAAQ;IACX;IACA,CAAC;GACH,QAAQ,UAAU;GAClB,CAAC,CAAC,KACF,OAAO,SAAS,aAAa;AAC5B,gBAAa,SAAS;AACtB,UAAO,OAAO,WAAW;IACxB,WAAW,QAAQ,QAAQ,SAAS,SAAS,CAAC;IAC9C,QAAQ,UAAU;IAClB,CAAC,CAAC,KACF,OAAO,KAAK,UACX,QAAQ,OAAO;IAAE,OAAO;IAAO,QAAQ,EAAE,QAAQ,SAAS,QAAQ;IAAE,CACpE,CACD;IACA,CACF;EACF,CAAC,CAAC,KACF,OAAO,UAAU,UAAU;AAC1B,MAAI,iBAAiB,kBACpB,QAAO,IAAI,eAAe;GACzB;GACA;GACA;GACA;GACA,SAAS,iBAAiB,SAAS,+BAA+B,UAAU;GAC5E,GAAI,eAAe,KAAA,IAAY,EAAE,GAAG,EAAE,YAAY;GAClD,GAAI,MAAM,cAAc,KAAA,IAAY,EAAE,GAAG,EAAE,WAAW,MAAM,WAAW;GACvE,CAAC;AAEH,SAAO,IAAI,eAAe;GACzB;GACA;GACA;GACA;GACA,SAAS,iBAAiB,SAAS;GACnC,GAAI,eAAe,KAAA,IAAY,EAAE,GAAG,EAAE,YAAY;GAClD,WAAW;GACX,CAAC;GACD,CACF;EACA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { Lease, LeaseBroker, LeaseKey, Owner } from "./service.mjs";
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Brand } from "../../brand.mjs";
|
|
2
|
+
import { Context, Effect, Layer, Scope } from "effect";
|
|
3
|
+
|
|
4
|
+
//#region src/substrate/runtime/lease-broker/service.d.ts
|
|
5
|
+
/** Opaque resource identifier. Substrate-blind: the broker treats
|
|
6
|
+
* this as a string for map keying and never inspects it. Plugin
|
|
7
|
+
* authors choose the encoding (`account:<addr>`, `gpu:<slot>`, etc.). */
|
|
8
|
+
type LeaseKey = Brand<string, 'LeaseKey'>;
|
|
9
|
+
/** Free-form owner identity, used for diagnostics (`holders()` output,
|
|
10
|
+
* span attributes). The broker does NOT use this for re-entrancy:
|
|
11
|
+
* two `acquire` calls from the same owner against the same key will
|
|
12
|
+
* deadlock the second call. */
|
|
13
|
+
type Owner = string;
|
|
14
|
+
/** Lease handle. Carries only the diagnostic pair; the release is the
|
|
15
|
+
* scope finalizer, not a method.
|
|
16
|
+
*
|
|
17
|
+
* Why no `release()`: every consumer we have today wraps the lease
|
|
18
|
+
* in `Effect.scoped` and lets the scope finalizer fire. Exposing an
|
|
19
|
+
* explicit `release()` would invite double-release, release-while-
|
|
20
|
+
* scope-still-open, and the "I released early but forgot to clear
|
|
21
|
+
* the variable" footgun. The scope IS the lifetime. */
|
|
22
|
+
interface Lease {
|
|
23
|
+
readonly key: LeaseKey;
|
|
24
|
+
readonly owner: Owner;
|
|
25
|
+
}
|
|
26
|
+
/** Service shape — what plugins yield from Context. */
|
|
27
|
+
interface LeaseBroker {
|
|
28
|
+
/**
|
|
29
|
+
* Acquire the lease for `key`, attributed to `owner`. Blocks if the
|
|
30
|
+
* lease is already held, waiting in FIFO order behind earlier
|
|
31
|
+
* waiters. Cancellable: an interrupt while waiting unwinds without
|
|
32
|
+
* acquiring.
|
|
33
|
+
*
|
|
34
|
+
* Scope-bound release: the broker installs an uninterruptible
|
|
35
|
+
* finalizer on the surrounding scope. Calling `Effect.scoped` over
|
|
36
|
+
* an `acquire(...)` is the canonical shape.
|
|
37
|
+
*
|
|
38
|
+
* Non-reentrant: `acquire` from the same owner against a key the
|
|
39
|
+
* owner already holds will deadlock. Per-address sequence-number
|
|
40
|
+
* semantics require at-most-one in-flight; nesting is the caller's
|
|
41
|
+
* bug.
|
|
42
|
+
*/
|
|
43
|
+
readonly acquire: (key: LeaseKey, owner: Owner) => Effect.Effect<Lease, never, Scope.Scope>;
|
|
44
|
+
/**
|
|
45
|
+
* Non-blocking variant. Returns `null` if the lease is held by any
|
|
46
|
+
* owner (including the calling owner); otherwise atomically claims
|
|
47
|
+
* the lease and returns the handle. The atomic-claim CAS is the
|
|
48
|
+
* same as `acquire`'s first step — the only difference is the
|
|
49
|
+
* `null` return vs. enqueue.
|
|
50
|
+
*
|
|
51
|
+
* Scope-bound release: same finalizer install as `acquire` when
|
|
52
|
+
* the claim wins.
|
|
53
|
+
*/
|
|
54
|
+
readonly tryAcquire: (key: LeaseKey, owner: Owner) => Effect.Effect<Lease | null, never, Scope.Scope>;
|
|
55
|
+
/**
|
|
56
|
+
* Snapshot of current holders, keyed by `LeaseKey`. For diagnostics
|
|
57
|
+
* (renderer, debug logs); the result is a point-in-time read and
|
|
58
|
+
* may be stale by the time it's inspected.
|
|
59
|
+
*/
|
|
60
|
+
readonly holders: () => Effect.Effect<ReadonlyMap<LeaseKey, Owner>>;
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { Lease, LeaseBroker, LeaseKey, Owner };
|
|
64
|
+
//# sourceMappingURL=service.d.mts.map
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { Context, Deferred, Effect, Layer, Ref } from "effect";
|
|
2
|
+
//#region src/substrate/runtime/lease-broker/service.ts
|
|
3
|
+
/** Construct a `LeaseKey` from a free-form string. The boundary at
|
|
4
|
+
* which unbranded strings become branded; downstream code only sees
|
|
5
|
+
* branded values. */
|
|
6
|
+
const leaseKey = (s) => s;
|
|
7
|
+
var LeaseBrokerService = class extends Context.Service()("@devstack-rewrite/substrate/LeaseBroker") {};
|
|
8
|
+
/**
|
|
9
|
+
* In-process Layer. One broker per stack scope; closing the layer's
|
|
10
|
+
* scope drops every entry. Parallel stacks each get their own broker
|
|
11
|
+
* — the broker is name-blind, so cross-stack coordination on the
|
|
12
|
+
* same logical key (e.g. an address that two stacks share) is NOT
|
|
13
|
+
* provided here. A cross-process layer can be slotted in later as a
|
|
14
|
+
* sibling factory; today's consumers are in-process only.
|
|
15
|
+
*/
|
|
16
|
+
const layerLeaseBroker = Layer.effect(LeaseBrokerService, Effect.gen(function* () {
|
|
17
|
+
const state = yield* Ref.make(/* @__PURE__ */ new Map());
|
|
18
|
+
/** Atomic finalizer body: clear `key`'s holder slot and, if any
|
|
19
|
+
* waiter is queued, promote the head waiter to holder. Returns
|
|
20
|
+
* the promoted waiter (so the caller can resolve their signal)
|
|
21
|
+
* or `null` when the key is fully released. Uninterruptible by
|
|
22
|
+
* construction — invoked from inside `Effect.addFinalizer` which
|
|
23
|
+
* the runtime wraps uninterruptibly. */
|
|
24
|
+
const releaseAndPromote = (key) => Ref.modify(state, (current) => {
|
|
25
|
+
const entry = current.get(key);
|
|
26
|
+
if (!entry) return [null, current];
|
|
27
|
+
const head = entry.waiters[0];
|
|
28
|
+
if (head === void 0) {
|
|
29
|
+
const next = new Map(current);
|
|
30
|
+
next.delete(key);
|
|
31
|
+
return [null, next];
|
|
32
|
+
}
|
|
33
|
+
const rest = entry.waiters.slice(1);
|
|
34
|
+
const next = new Map(current);
|
|
35
|
+
next.set(key, {
|
|
36
|
+
holder: head.owner,
|
|
37
|
+
waiters: rest
|
|
38
|
+
});
|
|
39
|
+
return [head, next];
|
|
40
|
+
});
|
|
41
|
+
/** Remove `waiter` from `key`'s waiter list. Called when an
|
|
42
|
+
* enqueued waiter is interrupted while parked on its signal. */
|
|
43
|
+
const removeWaiterIfQueued = (key, waiter) => Ref.update(state, (current) => {
|
|
44
|
+
const entry = current.get(key);
|
|
45
|
+
if (!entry) return current;
|
|
46
|
+
const filtered = entry.waiters.filter((w) => w !== waiter);
|
|
47
|
+
if (filtered.length === entry.waiters.length) return current;
|
|
48
|
+
const next = new Map(current);
|
|
49
|
+
next.set(key, {
|
|
50
|
+
holder: entry.holder,
|
|
51
|
+
waiters: filtered
|
|
52
|
+
});
|
|
53
|
+
return next;
|
|
54
|
+
});
|
|
55
|
+
/** Cleanup on cancellation of a waiting `acquire`: if we were
|
|
56
|
+
* still queued, drop ourselves; if we were already promoted to
|
|
57
|
+
* holder by a release that raced with our interrupt, release on
|
|
58
|
+
* our behalf so the lease doesn't leak. */
|
|
59
|
+
const cleanupCancelledWait = (key, waiter) => Effect.gen(function* () {
|
|
60
|
+
if (yield* Ref.modify(state, (current) => {
|
|
61
|
+
const entry = current.get(key);
|
|
62
|
+
if (!entry) return [false, current];
|
|
63
|
+
if (entry.holder === waiter.owner && entry.waiters.indexOf(waiter) === -1) return [true, current];
|
|
64
|
+
return [false, current];
|
|
65
|
+
})) {
|
|
66
|
+
const promoted = yield* releaseAndPromote(key);
|
|
67
|
+
if (promoted !== null) yield* Deferred.succeed(promoted.signal, void 0);
|
|
68
|
+
} else yield* removeWaiterIfQueued(key, waiter);
|
|
69
|
+
});
|
|
70
|
+
/** Install the scope-bound release finalizer. Uninterruptible —
|
|
71
|
+
* losing the release on a Ctrl-C double-tap would leak the
|
|
72
|
+
* lease and stall everything queued behind it. */
|
|
73
|
+
const installReleaseFinalizer = (key) => Effect.addFinalizer(() => Effect.gen(function* () {
|
|
74
|
+
const promoted = yield* releaseAndPromote(key);
|
|
75
|
+
if (promoted !== null) yield* Deferred.succeed(promoted.signal, void 0);
|
|
76
|
+
}).pipe(Effect.uninterruptible));
|
|
77
|
+
const acquire = (key, owner) => Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
|
|
78
|
+
const signal = yield* Deferred.make();
|
|
79
|
+
const waiter = {
|
|
80
|
+
owner,
|
|
81
|
+
signal
|
|
82
|
+
};
|
|
83
|
+
const becameHolder = yield* Ref.modify(state, (current) => {
|
|
84
|
+
const entry = current.get(key);
|
|
85
|
+
if (!entry) {
|
|
86
|
+
const next = new Map(current);
|
|
87
|
+
next.set(key, {
|
|
88
|
+
holder: owner,
|
|
89
|
+
waiters: []
|
|
90
|
+
});
|
|
91
|
+
return [true, next];
|
|
92
|
+
}
|
|
93
|
+
const next = new Map(current);
|
|
94
|
+
next.set(key, {
|
|
95
|
+
holder: entry.holder,
|
|
96
|
+
waiters: [...entry.waiters, waiter]
|
|
97
|
+
});
|
|
98
|
+
return [false, next];
|
|
99
|
+
});
|
|
100
|
+
if (!becameHolder) yield* restore(Deferred.await(signal)).pipe(Effect.onInterrupt(() => cleanupCancelledWait(key, waiter).pipe(Effect.uninterruptible)));
|
|
101
|
+
yield* installReleaseFinalizer(key);
|
|
102
|
+
yield* Effect.annotateCurrentSpan({
|
|
103
|
+
"leaseBroker.key": key,
|
|
104
|
+
"leaseBroker.owner": owner,
|
|
105
|
+
"leaseBroker.contended": !becameHolder
|
|
106
|
+
});
|
|
107
|
+
return {
|
|
108
|
+
key,
|
|
109
|
+
owner
|
|
110
|
+
};
|
|
111
|
+
})).pipe(Effect.withSpan("substrate.leaseBroker.acquire"));
|
|
112
|
+
const tryAcquire = (key, owner) => Effect.gen(function* () {
|
|
113
|
+
if (!(yield* Ref.modify(state, (current) => {
|
|
114
|
+
if (current.has(key)) return [false, current];
|
|
115
|
+
const next = new Map(current);
|
|
116
|
+
next.set(key, {
|
|
117
|
+
holder: owner,
|
|
118
|
+
waiters: []
|
|
119
|
+
});
|
|
120
|
+
return [true, next];
|
|
121
|
+
}))) {
|
|
122
|
+
yield* Effect.annotateCurrentSpan({
|
|
123
|
+
"leaseBroker.key": key,
|
|
124
|
+
"leaseBroker.owner": owner,
|
|
125
|
+
"leaseBroker.claimed": false
|
|
126
|
+
});
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
yield* installReleaseFinalizer(key);
|
|
130
|
+
yield* Effect.annotateCurrentSpan({
|
|
131
|
+
"leaseBroker.key": key,
|
|
132
|
+
"leaseBroker.owner": owner,
|
|
133
|
+
"leaseBroker.claimed": true
|
|
134
|
+
});
|
|
135
|
+
return {
|
|
136
|
+
key,
|
|
137
|
+
owner
|
|
138
|
+
};
|
|
139
|
+
}).pipe(Effect.uninterruptible, Effect.withSpan("substrate.leaseBroker.tryAcquire"));
|
|
140
|
+
const holders = () => Effect.gen(function* () {
|
|
141
|
+
const current = yield* Ref.get(state);
|
|
142
|
+
const out = /* @__PURE__ */ new Map();
|
|
143
|
+
for (const [k, entry] of current) out.set(k, entry.holder);
|
|
144
|
+
return out;
|
|
145
|
+
});
|
|
146
|
+
return LeaseBrokerService.of({
|
|
147
|
+
acquire,
|
|
148
|
+
tryAcquire,
|
|
149
|
+
holders
|
|
150
|
+
});
|
|
151
|
+
}));
|
|
152
|
+
//#endregion
|
|
153
|
+
export { LeaseBrokerService, layerLeaseBroker, leaseKey };
|
|
154
|
+
|
|
155
|
+
//# sourceMappingURL=service.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.mjs","names":[],"sources":["../../../../src/substrate/runtime/lease-broker/service.ts"],"sourcesContent":["// Lease broker — substrate-level service interface.\n//\n// Architecture (`notes/redesign/architecture.md` § \"L0 substrate\n// primitives\"): the substrate owns a generic lease primitive keyed by\n// an opaque resource identifier. Any caller that needs at-most-one-\n// in-flight serialization on a resource yields this service and calls\n// `acquire(key, owner)`. The first canonical consumer is the per-\n// address sequence-number lock (`plugins/account/address-lock.ts`,\n// today plugin-local; PR3 lifts it to consume this primitive);\n// callers in the same shape — sign+execute pipelines, per-connection\n// gate, per-slot work queue — share the same seam.\n//\n// Substrate name-blindness: the broker has no concept of what a\n// `LeaseKey` represents. The plugin author chooses the key shape; the\n// broker treats it as an opaque string with a brand. A wallet might\n// key by `account:<address>`, a GPU-bound plugin by `gpu:<slot>` —\n// the broker doesn't care.\n//\n// Lifetime: scope-bound. `acquire` returns a `Lease` handle whose\n// release fires when the surrounding `Effect.Scope` closes. There is\n// no `release()` method on `Lease` — the only release path is the\n// scope finalizer, which makes \"I forgot to release\" structurally\n// impossible.\n//\n// Mechanics: per-key state in a single `Ref<State>`. The blocking\n// queue is a FIFO of `Waiter`s carrying a `Deferred` that the\n// outgoing holder's finalizer resolves AFTER atomically installing\n// the next holder. `tryAcquire` does the same atomic-claim CAS as\n// `acquire`'s first step, but skips the wait — returning `null` if\n// the key is held.\n\nimport { Context, Deferred, Effect, Layer, Ref, Scope } from 'effect';\n\nimport type { Brand } from '../../brand.ts';\n\n// ----------------------------------------------------------------------\n// Public shape\n// ----------------------------------------------------------------------\n\n/** Opaque resource identifier. Substrate-blind: the broker treats\n * this as a string for map keying and never inspects it. Plugin\n * authors choose the encoding (`account:<addr>`, `gpu:<slot>`, etc.). */\nexport type LeaseKey = Brand<string, 'LeaseKey'>;\n\n/** Construct a `LeaseKey` from a free-form string. The boundary at\n * which unbranded strings become branded; downstream code only sees\n * branded values. */\nexport const leaseKey = (s: string): LeaseKey => s as LeaseKey;\n\n/** Free-form owner identity, used for diagnostics (`holders()` output,\n * span attributes). The broker does NOT use this for re-entrancy:\n * two `acquire` calls from the same owner against the same key will\n * deadlock the second call. */\nexport type Owner = string;\n\n/** Lease handle. Carries only the diagnostic pair; the release is the\n * scope finalizer, not a method.\n *\n * Why no `release()`: every consumer we have today wraps the lease\n * in `Effect.scoped` and lets the scope finalizer fire. Exposing an\n * explicit `release()` would invite double-release, release-while-\n * scope-still-open, and the \"I released early but forgot to clear\n * the variable\" footgun. The scope IS the lifetime. */\nexport interface Lease {\n\treadonly key: LeaseKey;\n\treadonly owner: Owner;\n}\n\n/** Service shape — what plugins yield from Context. */\nexport interface LeaseBroker {\n\t/**\n\t * Acquire the lease for `key`, attributed to `owner`. Blocks if the\n\t * lease is already held, waiting in FIFO order behind earlier\n\t * waiters. Cancellable: an interrupt while waiting unwinds without\n\t * acquiring.\n\t *\n\t * Scope-bound release: the broker installs an uninterruptible\n\t * finalizer on the surrounding scope. Calling `Effect.scoped` over\n\t * an `acquire(...)` is the canonical shape.\n\t *\n\t * Non-reentrant: `acquire` from the same owner against a key the\n\t * owner already holds will deadlock. Per-address sequence-number\n\t * semantics require at-most-one in-flight; nesting is the caller's\n\t * bug.\n\t */\n\treadonly acquire: (key: LeaseKey, owner: Owner) => Effect.Effect<Lease, never, Scope.Scope>;\n\n\t/**\n\t * Non-blocking variant. Returns `null` if the lease is held by any\n\t * owner (including the calling owner); otherwise atomically claims\n\t * the lease and returns the handle. The atomic-claim CAS is the\n\t * same as `acquire`'s first step — the only difference is the\n\t * `null` return vs. enqueue.\n\t *\n\t * Scope-bound release: same finalizer install as `acquire` when\n\t * the claim wins.\n\t */\n\treadonly tryAcquire: (\n\t\tkey: LeaseKey,\n\t\towner: Owner,\n\t) => Effect.Effect<Lease | null, never, Scope.Scope>;\n\n\t/**\n\t * Snapshot of current holders, keyed by `LeaseKey`. For diagnostics\n\t * (renderer, debug logs); the result is a point-in-time read and\n\t * may be stale by the time it's inspected.\n\t */\n\treadonly holders: () => Effect.Effect<ReadonlyMap<LeaseKey, Owner>>;\n}\n\n// ----------------------------------------------------------------------\n// Internal state\n// ----------------------------------------------------------------------\n\n/** A fiber parked on `Deferred.await` waiting to become the next\n * holder. The outgoing holder's finalizer transfers ownership by\n * setting `holder = waiter.owner` on the per-key entry AND resolving\n * the deferred — the awoken waiter doesn't re-CAS.\n *\n * `Waiter` reference identity is the cancellation key: an interrupted\n * waiter removes itself by reference-equality. */\ninterface Waiter {\n\treadonly owner: Owner;\n\treadonly signal: Deferred.Deferred<void>;\n}\n\ninterface KeyEntry {\n\treadonly holder: Owner;\n\treadonly waiters: ReadonlyArray<Waiter>;\n}\n\ntype State = ReadonlyMap<LeaseKey, KeyEntry>;\n\n// ----------------------------------------------------------------------\n// Service tag + Layer\n// ----------------------------------------------------------------------\n\nexport class LeaseBrokerService extends Context.Service<LeaseBrokerService, LeaseBroker>()(\n\t'@devstack-rewrite/substrate/LeaseBroker',\n) {}\n\n/**\n * In-process Layer. One broker per stack scope; closing the layer's\n * scope drops every entry. Parallel stacks each get their own broker\n * — the broker is name-blind, so cross-stack coordination on the\n * same logical key (e.g. an address that two stacks share) is NOT\n * provided here. A cross-process layer can be slotted in later as a\n * sibling factory; today's consumers are in-process only.\n */\nexport const layerLeaseBroker: Layer.Layer<LeaseBrokerService> = Layer.effect(\n\tLeaseBrokerService,\n\tEffect.gen(function* () {\n\t\tconst state = yield* Ref.make<State>(new Map());\n\n\t\t/** Atomic finalizer body: clear `key`'s holder slot and, if any\n\t\t * waiter is queued, promote the head waiter to holder. Returns\n\t\t * the promoted waiter (so the caller can resolve their signal)\n\t\t * or `null` when the key is fully released. Uninterruptible by\n\t\t * construction — invoked from inside `Effect.addFinalizer` which\n\t\t * the runtime wraps uninterruptibly. */\n\t\tconst releaseAndPromote = (key: LeaseKey): Effect.Effect<Waiter | null> =>\n\t\t\tRef.modify<State, Waiter | null>(state, (current) => {\n\t\t\t\tconst entry = current.get(key);\n\t\t\t\tif (!entry) return [null, current];\n\t\t\t\tconst head = entry.waiters[0];\n\t\t\t\tif (head === undefined) {\n\t\t\t\t\tconst next = new Map(current);\n\t\t\t\t\tnext.delete(key);\n\t\t\t\t\treturn [null, next];\n\t\t\t\t}\n\t\t\t\tconst rest = entry.waiters.slice(1);\n\t\t\t\tconst next = new Map(current);\n\t\t\t\tnext.set(key, { holder: head.owner, waiters: rest });\n\t\t\t\treturn [head, next];\n\t\t\t});\n\n\t\t/** Remove `waiter` from `key`'s waiter list. Called when an\n\t\t * enqueued waiter is interrupted while parked on its signal. */\n\t\tconst removeWaiterIfQueued = (key: LeaseKey, waiter: Waiter): Effect.Effect<void> =>\n\t\t\tRef.update(state, (current) => {\n\t\t\t\tconst entry = current.get(key);\n\t\t\t\tif (!entry) return current;\n\t\t\t\tconst filtered = entry.waiters.filter((w) => w !== waiter);\n\t\t\t\tif (filtered.length === entry.waiters.length) return current;\n\t\t\t\tconst next = new Map(current);\n\t\t\t\tnext.set(key, { holder: entry.holder, waiters: filtered });\n\t\t\t\treturn next;\n\t\t\t});\n\n\t\t/** Cleanup on cancellation of a waiting `acquire`: if we were\n\t\t * still queued, drop ourselves; if we were already promoted to\n\t\t * holder by a release that raced with our interrupt, release on\n\t\t * our behalf so the lease doesn't leak. */\n\t\tconst cleanupCancelledWait = (key: LeaseKey, waiter: Waiter): Effect.Effect<void> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst becameHolder = yield* Ref.modify<State, boolean>(state, (current) => {\n\t\t\t\t\tconst entry = current.get(key);\n\t\t\t\t\tif (!entry) return [false, current];\n\t\t\t\t\tif (entry.holder === waiter.owner && entry.waiters.indexOf(waiter) === -1) {\n\t\t\t\t\t\t// Promoted-but-not-awaited: we were handed the lease\n\t\t\t\t\t\t// in releaseAndPromote but interrupted before the\n\t\t\t\t\t\t// `Deferred.await` returned. Take responsibility for\n\t\t\t\t\t\t// releasing it.\n\t\t\t\t\t\treturn [true, current];\n\t\t\t\t\t}\n\t\t\t\t\treturn [false, current];\n\t\t\t\t});\n\t\t\t\tif (becameHolder) {\n\t\t\t\t\tconst promoted = yield* releaseAndPromote(key);\n\t\t\t\t\tif (promoted !== null) {\n\t\t\t\t\t\tyield* Deferred.succeed(promoted.signal, undefined);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tyield* removeWaiterIfQueued(key, waiter);\n\t\t\t\t}\n\t\t\t});\n\n\t\t/** Install the scope-bound release finalizer. Uninterruptible —\n\t\t * losing the release on a Ctrl-C double-tap would leak the\n\t\t * lease and stall everything queued behind it. */\n\t\tconst installReleaseFinalizer = (key: LeaseKey): Effect.Effect<void, never, Scope.Scope> =>\n\t\t\tEffect.addFinalizer(() =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst promoted = yield* releaseAndPromote(key);\n\t\t\t\t\tif (promoted !== null) {\n\t\t\t\t\t\tyield* Deferred.succeed(promoted.signal, undefined);\n\t\t\t\t\t}\n\t\t\t\t}).pipe(Effect.uninterruptible),\n\t\t\t);\n\n\t\tconst acquire: LeaseBroker['acquire'] = (key, owner) =>\n\t\t\tEffect.uninterruptibleMask((restore) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst signal = yield* Deferred.make<void>();\n\t\t\t\t\tconst waiter: Waiter = { owner, signal };\n\n\t\t\t\t\tconst becameHolder = yield* Ref.modify<State, boolean>(state, (current) => {\n\t\t\t\t\t\tconst entry = current.get(key);\n\t\t\t\t\t\tif (!entry) {\n\t\t\t\t\t\t\tconst next = new Map(current);\n\t\t\t\t\t\t\tnext.set(key, { holder: owner, waiters: [] });\n\t\t\t\t\t\t\treturn [true, next];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst next = new Map(current);\n\t\t\t\t\t\tnext.set(key, {\n\t\t\t\t\t\t\tholder: entry.holder,\n\t\t\t\t\t\t\twaiters: [...entry.waiters, waiter],\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn [false, next];\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!becameHolder) {\n\t\t\t\t\t\tyield* restore(Deferred.await(signal)).pipe(\n\t\t\t\t\t\t\tEffect.onInterrupt(() =>\n\t\t\t\t\t\t\t\tcleanupCancelledWait(key, waiter).pipe(Effect.uninterruptible),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tyield* installReleaseFinalizer(key);\n\t\t\t\t\tyield* Effect.annotateCurrentSpan({\n\t\t\t\t\t\t'leaseBroker.key': key,\n\t\t\t\t\t\t'leaseBroker.owner': owner,\n\t\t\t\t\t\t'leaseBroker.contended': !becameHolder,\n\t\t\t\t\t});\n\t\t\t\t\treturn { key, owner } satisfies Lease;\n\t\t\t\t}),\n\t\t\t).pipe(Effect.withSpan('substrate.leaseBroker.acquire'));\n\n\t\tconst tryAcquire: LeaseBroker['tryAcquire'] = (key, owner) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst claimed = yield* Ref.modify<State, boolean>(state, (current) => {\n\t\t\t\t\tif (current.has(key)) return [false, current];\n\t\t\t\t\tconst next = new Map(current);\n\t\t\t\t\tnext.set(key, { holder: owner, waiters: [] });\n\t\t\t\t\treturn [true, next];\n\t\t\t\t});\n\t\t\t\tif (!claimed) {\n\t\t\t\t\tyield* Effect.annotateCurrentSpan({\n\t\t\t\t\t\t'leaseBroker.key': key,\n\t\t\t\t\t\t'leaseBroker.owner': owner,\n\t\t\t\t\t\t'leaseBroker.claimed': false,\n\t\t\t\t\t});\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tyield* installReleaseFinalizer(key);\n\t\t\t\tyield* Effect.annotateCurrentSpan({\n\t\t\t\t\t'leaseBroker.key': key,\n\t\t\t\t\t'leaseBroker.owner': owner,\n\t\t\t\t\t'leaseBroker.claimed': true,\n\t\t\t\t});\n\t\t\t\treturn { key, owner } satisfies Lease;\n\t\t\t}).pipe(\n\t\t\t\t// Make the claim-and-install-finalizer pair atomic w.r.t.\n\t\t\t\t// interruption: an interrupt arriving AFTER `Ref.modify`\n\t\t\t\t// claims the slot but BEFORE the finalizer is wired would\n\t\t\t\t// leak the lease. `Ref.modify` itself is a pure-data\n\t\t\t\t// transition, so wrapping the whole pipeline uninterruptibly\n\t\t\t\t// is safe.\n\t\t\t\tEffect.uninterruptible,\n\t\t\t\tEffect.withSpan('substrate.leaseBroker.tryAcquire'),\n\t\t\t);\n\n\t\tconst holders: LeaseBroker['holders'] = () =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst current = yield* Ref.get(state);\n\t\t\t\tconst out = new Map<LeaseKey, Owner>();\n\t\t\t\tfor (const [k, entry] of current) out.set(k, entry.holder);\n\t\t\t\treturn out;\n\t\t\t});\n\n\t\treturn LeaseBrokerService.of({ acquire, tryAcquire, holders });\n\t}),\n);\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { uniqueResourceRefs } from "../../plugin.mjs";
|
|
2
|
+
import { pluginKey } from "../../brand.mjs";
|
|
3
|
+
import { Data, Effect } from "effect";
|
|
4
|
+
//#region src/substrate/runtime/lifecycle/dep-graph.ts
|
|
5
|
+
/** Cycle detected in the dep graph. Carries the offending key path so
|
|
6
|
+
* the user sees the loop. Compile-time `defineDevstack` doesn't catch
|
|
7
|
+
* every cycle (capability-typed consumes resolve at runtime), so this
|
|
8
|
+
* surfaces a typed error at boot. */
|
|
9
|
+
var DepGraphCycleError = class extends Data.TaggedError("DepGraphCycleError") {};
|
|
10
|
+
/** A dependency resource matched no provider. This is normally caught by
|
|
11
|
+
* the compile-time `MissingProviders` check, but runtime-built stacks can
|
|
12
|
+
* hit it. */
|
|
13
|
+
var UnresolvedDependencyError = class extends Data.TaggedError("UnresolvedDependencyError") {};
|
|
14
|
+
/** Mint a stable PluginKey for a plugin. Plugins may declare a stable
|
|
15
|
+
* key; otherwise keys derive from resource id + ordinal so duplicates
|
|
16
|
+
* do not collide. */
|
|
17
|
+
const mintKey = (member, ordinal) => {
|
|
18
|
+
if (member.pluginKey !== void 0) return pluginKey(String(member.pluginKey));
|
|
19
|
+
return pluginKey(`${member.id}#${ordinal}`);
|
|
20
|
+
};
|
|
21
|
+
/** Walk the member tuple and emit one named-member entry per node. */
|
|
22
|
+
const expand = (members) => {
|
|
23
|
+
const out = [];
|
|
24
|
+
let ordinal = 0;
|
|
25
|
+
for (const member of members) {
|
|
26
|
+
const key = mintKey(member, ordinal++);
|
|
27
|
+
out.push({
|
|
28
|
+
key,
|
|
29
|
+
member
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Resolve a flat member tuple into a topo-sorted level batch.
|
|
36
|
+
*
|
|
37
|
+
* Steps:
|
|
38
|
+
* 1. Mint a plugin key for every member.
|
|
39
|
+
* 2. Build the resource-id -> key index (providers).
|
|
40
|
+
* 3. For each node, resolve its dependency refs to upstream keys.
|
|
41
|
+
* 4. Kahn's algorithm: peel zero-indegree nodes into level 0, decrement
|
|
42
|
+
* downstream indegrees, repeat.
|
|
43
|
+
* 5. If any node remains, return `DepGraphCycleError`.
|
|
44
|
+
*
|
|
45
|
+
* Span-instrumented so trace exports show the resolution alongside the
|
|
46
|
+
* supervisor's acquire spans.
|
|
47
|
+
*/
|
|
48
|
+
const resolveGraph = (members) => Effect.gen(function* () {
|
|
49
|
+
yield* Effect.annotateCurrentSpan({ "devstack.dep-graph.memberCount": members.length });
|
|
50
|
+
const named = expand(members);
|
|
51
|
+
const providerByResourceId = /* @__PURE__ */ new Map();
|
|
52
|
+
for (const { key, member } of named) providerByResourceId.set(member.id, key);
|
|
53
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
54
|
+
const indegree = /* @__PURE__ */ new Map();
|
|
55
|
+
const downstream = /* @__PURE__ */ new Map();
|
|
56
|
+
for (const { key } of named) {
|
|
57
|
+
indegree.set(key, 0);
|
|
58
|
+
downstream.set(key, /* @__PURE__ */ new Set());
|
|
59
|
+
}
|
|
60
|
+
for (const { key, member } of named) {
|
|
61
|
+
const upstreamKeys = [];
|
|
62
|
+
const upstreamResources = uniqueResourceRefs(member.dependsOn);
|
|
63
|
+
for (const resource of upstreamResources) {
|
|
64
|
+
const providerKey = providerByResourceId.get(resource.id);
|
|
65
|
+
if (providerKey === void 0) return yield* Effect.fail(new UnresolvedDependencyError({
|
|
66
|
+
pluginKey: key,
|
|
67
|
+
missingResourceId: resource.id
|
|
68
|
+
}));
|
|
69
|
+
upstreamKeys.push(providerKey);
|
|
70
|
+
downstream.get(providerKey)?.add(key);
|
|
71
|
+
indegree.set(key, (indegree.get(key) ?? 0) + 1);
|
|
72
|
+
}
|
|
73
|
+
nodes.set(key, {
|
|
74
|
+
key,
|
|
75
|
+
member,
|
|
76
|
+
upstreamResources,
|
|
77
|
+
upstreamKeys
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
const levels = [];
|
|
81
|
+
const settled = /* @__PURE__ */ new Set();
|
|
82
|
+
while (settled.size < nodes.size) {
|
|
83
|
+
const layer = [];
|
|
84
|
+
for (const [key, deg] of indegree) {
|
|
85
|
+
if (settled.has(key)) continue;
|
|
86
|
+
if (deg === 0) layer.push(key);
|
|
87
|
+
}
|
|
88
|
+
if (layer.length === 0) {
|
|
89
|
+
const trapped = [];
|
|
90
|
+
for (const key of nodes.keys()) if (!settled.has(key)) trapped.push(key);
|
|
91
|
+
return yield* Effect.fail(new DepGraphCycleError({ cycle: trapped }));
|
|
92
|
+
}
|
|
93
|
+
levels.push(layer);
|
|
94
|
+
for (const key of layer) {
|
|
95
|
+
settled.add(key);
|
|
96
|
+
for (const child of downstream.get(key) ?? []) indegree.set(child, (indegree.get(child) ?? 1) - 1);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const downstreamFrozen = /* @__PURE__ */ new Map();
|
|
100
|
+
for (const [k, v] of downstream) downstreamFrozen.set(k, v);
|
|
101
|
+
return {
|
|
102
|
+
nodes,
|
|
103
|
+
levels,
|
|
104
|
+
downstream: downstreamFrozen
|
|
105
|
+
};
|
|
106
|
+
}).pipe(Effect.withSpan("lifecycle.dep-graph.resolve"));
|
|
107
|
+
/**
|
|
108
|
+
* Compute the closure of nodes downstream of `root` (inclusive).
|
|
109
|
+
* Used by the supervisor to tear down a subgraph in reverse-dep order
|
|
110
|
+
* and re-acquire in forward order.
|
|
111
|
+
*
|
|
112
|
+
* Architecture § Watch-triggered invalidation:
|
|
113
|
+
* Invalidating a producer invalidates downstream consumers along
|
|
114
|
+
* dep-graph edges (cascade semantics).
|
|
115
|
+
*/
|
|
116
|
+
const downstreamClosure = (graph, root) => {
|
|
117
|
+
const closure = new Set([root]);
|
|
118
|
+
const queue = [root];
|
|
119
|
+
while (queue.length > 0) {
|
|
120
|
+
const next = queue.shift();
|
|
121
|
+
for (const child of graph.downstream.get(next) ?? []) if (!closure.has(child)) {
|
|
122
|
+
closure.add(child);
|
|
123
|
+
queue.push(child);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return closure;
|
|
127
|
+
};
|
|
128
|
+
/** Order a set of keys by their dep-graph level — forward (low-to-high)
|
|
129
|
+
* for acquire, reverse (high-to-low) for teardown. */
|
|
130
|
+
const orderByLevel = (graph, keys, direction) => {
|
|
131
|
+
const out = [];
|
|
132
|
+
for (const level of graph.levels) for (const key of level) if (keys.has(key)) out.push(key);
|
|
133
|
+
return direction === "reverse" ? out.slice().reverse() : out;
|
|
134
|
+
};
|
|
135
|
+
//#endregion
|
|
136
|
+
export { downstreamClosure, orderByLevel, resolveGraph };
|
|
137
|
+
|
|
138
|
+
//# sourceMappingURL=dep-graph.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dep-graph.mjs","names":["makePluginKey"],"sources":["../../../../src/substrate/runtime/lifecycle/dep-graph.ts"],"sourcesContent":["// Dep-graph resolution — turn a `Stack` member tuple into a topo-sorted\n// acquire schedule.\n//\n// Architecture § Plugin lifecycle within a stack:\n// \"Resolution. Upstream keys (concrete or capability-typed) resolve\n// once. Bootstrap asset dedup-by-key fires before the scheduler\n// starts node fibers. Scheduling. Plugin enters `pending`. When all\n// upstream keys are `ready`, the node begins `acquiring`. Per-key\n// serialization: only one acquire at a time per key.\"\n//\n// This module is the pure dep-graph math: members in, levels out.\n\nimport { Data, Effect } from 'effect';\n\nimport type { PluginKey } from '../../brand.ts';\nimport { pluginKey as makePluginKey } from '../../brand.ts';\nimport { uniqueResourceRefs, type AnyPlugin, type AnyResourceRef } from '../../plugin.ts';\n\n// -----------------------------------------------------------------------------\n// Errors\n// -----------------------------------------------------------------------------\n\n/** Cycle detected in the dep graph. Carries the offending key path so\n * the user sees the loop. Compile-time `defineDevstack` doesn't catch\n * every cycle (capability-typed consumes resolve at runtime), so this\n * surfaces a typed error at boot. */\nexport class DepGraphCycleError extends Data.TaggedError('DepGraphCycleError')<{\n\treadonly cycle: ReadonlyArray<PluginKey>;\n}> {}\n\n/** A dependency resource matched no provider. This is normally caught by\n * the compile-time `MissingProviders` check, but runtime-built stacks can\n * hit it. */\nexport class UnresolvedDependencyError extends Data.TaggedError('UnresolvedDependencyError')<{\n\treadonly pluginKey: PluginKey;\n\treadonly missingResourceId: string;\n}> {}\n\nexport type DepGraphError = DepGraphCycleError | UnresolvedDependencyError;\n\n// -----------------------------------------------------------------------------\n// Node shape\n// -----------------------------------------------------------------------------\n\n/** A resolved node in the dep graph. Wraps the original plugin with a\n * substrate-assigned `PluginKey`. */\nexport interface DepNode {\n\treadonly key: PluginKey;\n\treadonly member: AnyPlugin;\n\t/** Unique dependency refs and their resolved upstream keys. The two\n\t * arrays are positional peers. */\n\treadonly upstreamResources: ReadonlyArray<AnyResourceRef>;\n\treadonly upstreamKeys: ReadonlyArray<PluginKey>;\n}\n\n/** The result of resolving a member tuple. Levels are batches the\n * scheduler can acquire in parallel; each level's nodes only depend\n * on prior levels. */\nexport interface ResolvedGraph {\n\treadonly nodes: ReadonlyMap<PluginKey, DepNode>;\n\treadonly levels: ReadonlyArray<ReadonlyArray<PluginKey>>;\n\t/** Reverse-dep index: each key → keys that depend on it. The\n\t * supervisor uses this for selective-restart cascade. */\n\treadonly downstream: ReadonlyMap<PluginKey, ReadonlySet<PluginKey>>;\n}\n\n// -----------------------------------------------------------------------------\n// Plugin key minting\n// -----------------------------------------------------------------------------\n\ninterface NamedMember {\n\treadonly key: PluginKey;\n\treadonly member: AnyPlugin;\n}\n\n/** Mint a stable PluginKey for a plugin. Plugins may declare a stable\n * key; otherwise keys derive from resource id + ordinal so duplicates\n * do not collide. */\nconst mintKey = (member: AnyPlugin, ordinal: number): PluginKey => {\n\tif (member.pluginKey !== undefined) {\n\t\treturn makePluginKey(String(member.pluginKey));\n\t}\n\treturn makePluginKey(`${member.id}#${ordinal}`);\n};\n\n/** Walk the member tuple and emit one named-member entry per node. */\nconst expand = (members: ReadonlyArray<AnyPlugin>): ReadonlyArray<NamedMember> => {\n\tconst out: NamedMember[] = [];\n\tlet ordinal = 0;\n\tfor (const member of members) {\n\t\tconst key = mintKey(member, ordinal++);\n\t\tout.push({ key, member });\n\t}\n\treturn out;\n};\n\n// -----------------------------------------------------------------------------\n// Topological sort (Kahn's algorithm)\n// -----------------------------------------------------------------------------\n\n/**\n * Resolve a flat member tuple into a topo-sorted level batch.\n *\n * Steps:\n * 1. Mint a plugin key for every member.\n * 2. Build the resource-id -> key index (providers).\n * 3. For each node, resolve its dependency refs to upstream keys.\n * 4. Kahn's algorithm: peel zero-indegree nodes into level 0, decrement\n * downstream indegrees, repeat.\n * 5. If any node remains, return `DepGraphCycleError`.\n *\n * Span-instrumented so trace exports show the resolution alongside the\n * supervisor's acquire spans.\n */\nexport const resolveGraph = (\n\tmembers: ReadonlyArray<AnyPlugin>,\n): Effect.Effect<ResolvedGraph, DepGraphError> =>\n\tEffect.gen(function* () {\n\t\tyield* Effect.annotateCurrentSpan({ 'devstack.dep-graph.memberCount': members.length });\n\t\tconst named = expand(members);\n\n\t\t// Provider index: resource-id → key. Last writer wins; the\n\t\t// compile-time `MissingProviders` check ensures uniqueness on\n\t\t// the user-typed path, so a duplicate here would be a programmer\n\t\t// error in a runtime-typed stack — we don't enforce uniqueness at\n\t\t// runtime; the duplicate just resolves to the latest declaration.\n\t\tconst providerByResourceId = new Map<string, PluginKey>();\n\t\tfor (const { key, member } of named) {\n\t\t\tproviderByResourceId.set(member.id, key);\n\t\t}\n\n\t\tconst nodes = new Map<PluginKey, DepNode>();\n\t\tconst indegree = new Map<PluginKey, number>();\n\t\tconst downstream = new Map<PluginKey, Set<PluginKey>>();\n\t\tfor (const { key } of named) {\n\t\t\tindegree.set(key, 0);\n\t\t\tdownstream.set(key, new Set());\n\t\t}\n\n\t\tfor (const { key, member } of named) {\n\t\t\tconst upstreamKeys: PluginKey[] = [];\n\t\t\tconst upstreamResources = uniqueResourceRefs(member.dependsOn);\n\t\t\tfor (const resource of upstreamResources) {\n\t\t\t\tconst providerKey = providerByResourceId.get(resource.id);\n\t\t\t\tif (providerKey === undefined) {\n\t\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\t\tnew UnresolvedDependencyError({ pluginKey: key, missingResourceId: resource.id }),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tupstreamKeys.push(providerKey);\n\t\t\t\tdownstream.get(providerKey)?.add(key);\n\t\t\t\tindegree.set(key, (indegree.get(key) ?? 0) + 1);\n\t\t\t}\n\t\t\tnodes.set(key, {\n\t\t\t\tkey,\n\t\t\t\tmember,\n\t\t\t\tupstreamResources,\n\t\t\t\tupstreamKeys,\n\t\t\t});\n\t\t}\n\n\t\t// Kahn's algorithm — peel zero-indegree nodes level by level.\n\t\tconst levels: PluginKey[][] = [];\n\t\tconst settled = new Set<PluginKey>();\n\t\twhile (settled.size < nodes.size) {\n\t\t\tconst layer: PluginKey[] = [];\n\t\t\tfor (const [key, deg] of indegree) {\n\t\t\t\tif (settled.has(key)) continue;\n\t\t\t\tif (deg === 0) layer.push(key);\n\t\t\t}\n\t\t\tif (layer.length === 0) {\n\t\t\t\t// Cycle: collect every unsettled node as the cycle's witness.\n\t\t\t\t// More precise cycle extraction (Tarjan SCC) is overkill for\n\t\t\t\t// the user-facing message; we surface the trapped keys.\n\t\t\t\tconst trapped: PluginKey[] = [];\n\t\t\t\tfor (const key of nodes.keys()) {\n\t\t\t\t\tif (!settled.has(key)) trapped.push(key);\n\t\t\t\t}\n\t\t\t\treturn yield* Effect.fail(new DepGraphCycleError({ cycle: trapped }));\n\t\t\t}\n\t\t\tlevels.push(layer);\n\t\t\tfor (const key of layer) {\n\t\t\t\tsettled.add(key);\n\t\t\t\tfor (const child of downstream.get(key) ?? []) {\n\t\t\t\t\tindegree.set(child, (indegree.get(child) ?? 1) - 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Freeze downstream sets to ReadonlySet shape.\n\t\tconst downstreamFrozen = new Map<PluginKey, ReadonlySet<PluginKey>>();\n\t\tfor (const [k, v] of downstream) downstreamFrozen.set(k, v);\n\n\t\treturn {\n\t\t\tnodes,\n\t\t\tlevels,\n\t\t\tdownstream: downstreamFrozen,\n\t\t} satisfies ResolvedGraph;\n\t}).pipe(Effect.withSpan('lifecycle.dep-graph.resolve'));\n\n// -----------------------------------------------------------------------------\n// Selective-restart helpers\n// -----------------------------------------------------------------------------\n\n/**\n * Compute the closure of nodes downstream of `root` (inclusive).\n * Used by the supervisor to tear down a subgraph in reverse-dep order\n * and re-acquire in forward order.\n *\n * Architecture § Watch-triggered invalidation:\n * Invalidating a producer invalidates downstream consumers along\n * dep-graph edges (cascade semantics).\n */\nexport const downstreamClosure = (\n\tgraph: ResolvedGraph,\n\troot: PluginKey,\n): ReadonlySet<PluginKey> => {\n\tconst closure = new Set<PluginKey>([root]);\n\tconst queue: PluginKey[] = [root];\n\twhile (queue.length > 0) {\n\t\tconst next = queue.shift()!;\n\t\tfor (const child of graph.downstream.get(next) ?? []) {\n\t\t\tif (!closure.has(child)) {\n\t\t\t\tclosure.add(child);\n\t\t\t\tqueue.push(child);\n\t\t\t}\n\t\t}\n\t}\n\treturn closure;\n};\n\n/** Order a set of keys by their dep-graph level — forward (low-to-high)\n * for acquire, reverse (high-to-low) for teardown. */\nexport const orderByLevel = (\n\tgraph: ResolvedGraph,\n\tkeys: ReadonlySet<PluginKey>,\n\tdirection: 'forward' | 'reverse',\n): ReadonlyArray<PluginKey> => {\n\tconst out: PluginKey[] = [];\n\tfor (const level of graph.levels) {\n\t\tfor (const key of level) if (keys.has(key)) out.push(key);\n\t}\n\treturn direction === 'reverse' ? out.slice().reverse() : out;\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|