alchemy 2.0.0-beta.84 → 2.0.0-beta.85
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/THIRD_PARTY_LICENSES.md +2 -2
- package/bin/cli.js +14 -6
- package/bin/register-oxc.js +16 -12
- package/lib/AdoptPolicy.d.ts +73 -0
- package/lib/AdoptPolicy.d.ts.map +1 -1
- package/lib/AdoptPolicy.js +54 -0
- package/lib/AdoptPolicy.js.map +1 -1
- package/lib/Alchemist/AuthRegistry.d.ts +31 -0
- package/lib/Alchemist/AuthRegistry.d.ts.map +1 -0
- package/lib/Alchemist/AuthRegistry.js +95 -0
- package/lib/Alchemist/AuthRegistry.js.map +1 -0
- package/lib/Alchemist/Drift.d.ts +70 -0
- package/lib/Alchemist/Drift.d.ts.map +1 -0
- package/lib/Alchemist/Drift.js +54 -0
- package/lib/Alchemist/Drift.js.map +1 -0
- package/lib/Alchemist/Entrypoint.d.ts +27 -3
- package/lib/Alchemist/Entrypoint.d.ts.map +1 -1
- package/lib/Alchemist/Entrypoint.js +34 -3
- package/lib/Alchemist/Entrypoint.js.map +1 -1
- package/lib/Alchemist/Errors.d.ts +1 -1
- package/lib/Alchemist/Errors.d.ts.map +1 -1
- package/lib/Alchemist/Errors.js +1 -1
- package/lib/Alchemist/Errors.js.map +1 -1
- package/lib/Alchemist/Logs.d.ts +46 -0
- package/lib/Alchemist/Logs.d.ts.map +1 -0
- package/lib/Alchemist/{routes/logs.js → Logs.js} +21 -26
- package/lib/Alchemist/Logs.js.map +1 -0
- package/lib/Alchemist/Nuke.d.ts +69 -0
- package/lib/Alchemist/Nuke.d.ts.map +1 -0
- package/lib/Alchemist/Nuke.js +35 -0
- package/lib/Alchemist/Nuke.js.map +1 -0
- package/lib/Alchemist/Operations.d.ts +168 -0
- package/lib/Alchemist/Operations.d.ts.map +1 -0
- package/lib/Alchemist/Operations.js +165 -0
- package/lib/Alchemist/Operations.js.map +1 -0
- package/lib/Alchemist/Profile.d.ts +132 -0
- package/lib/Alchemist/Profile.d.ts.map +1 -0
- package/lib/Alchemist/{routes/profile.js → Profile.js} +20 -21
- package/lib/Alchemist/Profile.js.map +1 -0
- package/lib/Alchemist/{routes/provider.d.ts → Provider.d.ts} +4 -4
- package/lib/Alchemist/Provider.d.ts.map +1 -0
- package/lib/Alchemist/{routes/provider.js → Provider.js} +7 -6
- package/lib/Alchemist/Provider.js.map +1 -0
- package/lib/Alchemist/Runtime.d.ts +10 -6
- package/lib/Alchemist/Runtime.d.ts.map +1 -1
- package/lib/Alchemist/Runtime.js +38 -2
- package/lib/Alchemist/Runtime.js.map +1 -1
- package/lib/Alchemist/{routes/state.d.ts → State.d.ts} +36 -16
- package/lib/Alchemist/State.d.ts.map +1 -0
- package/lib/Alchemist/{routes/state.js → State.js} +50 -15
- package/lib/Alchemist/State.js.map +1 -0
- package/lib/Alchemist/index.d.ts +11 -10
- package/lib/Alchemist/index.d.ts.map +1 -1
- package/lib/Alchemist/index.js +10 -9
- package/lib/Alchemist/index.js.map +1 -1
- package/lib/Apply.d.ts +2 -8
- package/lib/Apply.d.ts.map +1 -1
- package/lib/Apply.js +364 -184
- package/lib/Apply.js.map +1 -1
- package/lib/Auth/AuthProvider.d.ts +24 -11
- package/lib/Auth/AuthProvider.d.ts.map +1 -1
- package/lib/Auth/AuthProvider.js +28 -12
- package/lib/Auth/AuthProvider.js.map +1 -1
- package/lib/Auth/BrowserOAuth.d.ts +6 -8
- package/lib/Auth/BrowserOAuth.d.ts.map +1 -1
- package/lib/Auth/BrowserOAuth.js +25 -41
- package/lib/Auth/BrowserOAuth.js.map +1 -1
- package/lib/Auth/Credentials.d.ts.map +1 -1
- package/lib/Auth/Credentials.js +2 -2
- package/lib/Auth/Credentials.js.map +1 -1
- package/lib/Auth/Demand.d.ts +4 -4
- package/lib/Auth/Demand.d.ts.map +1 -1
- package/lib/Auth/Demand.js +16 -10
- package/lib/Auth/Demand.js.map +1 -1
- package/lib/Auth/Env.d.ts +2 -1
- package/lib/Auth/Env.d.ts.map +1 -1
- package/lib/Auth/Env.js +4 -2
- package/lib/Auth/Env.js.map +1 -1
- package/lib/Auth/Inspect.d.ts +2 -2
- package/lib/Auth/Inspect.d.ts.map +1 -1
- package/lib/Auth/Inspect.js +3 -1
- package/lib/Auth/Inspect.js.map +1 -1
- package/lib/Auth/Lock.d.ts.map +1 -1
- package/lib/Auth/Lock.js +4 -8
- package/lib/Auth/Lock.js.map +1 -1
- package/lib/Auth/OAuthFlow.d.ts +3 -12
- package/lib/Auth/OAuthFlow.d.ts.map +1 -1
- package/lib/Auth/OAuthFlow.js +7 -17
- package/lib/Auth/OAuthFlow.js.map +1 -1
- package/lib/Auth/Paths.d.ts +2 -1
- package/lib/Auth/Paths.d.ts.map +1 -1
- package/lib/Auth/Paths.js +3 -2
- package/lib/Auth/Paths.js.map +1 -1
- package/lib/Auth/Profile.d.ts +10 -0
- package/lib/Auth/Profile.d.ts.map +1 -1
- package/lib/Auth/Profile.js +19 -2
- package/lib/Auth/Profile.js.map +1 -1
- package/lib/Auth/Registry.d.ts +20 -0
- package/lib/Auth/Registry.d.ts.map +1 -0
- package/lib/Auth/Registry.js +17 -0
- package/lib/Auth/Registry.js.map +1 -0
- package/lib/Auth/Resolve.d.ts +34 -2
- package/lib/Auth/Resolve.d.ts.map +1 -1
- package/lib/Auth/Resolve.js +51 -3
- package/lib/Auth/Resolve.js.map +1 -1
- package/lib/Auth/StoredAuthProvider.d.ts +1 -1
- package/lib/Auth/StoredAuthProvider.d.ts.map +1 -1
- package/lib/Auth/StoredAuthProvider.js +1 -2
- package/lib/Auth/StoredAuthProvider.js.map +1 -1
- package/lib/Binding.d.ts.map +1 -1
- package/lib/Binding.js +3 -1
- package/lib/Binding.js.map +1 -1
- package/lib/Bundle/Bundle.d.ts +5 -0
- package/lib/Bundle/Bundle.d.ts.map +1 -1
- package/lib/Bundle/Bundle.js +36 -6
- package/lib/Bundle/Bundle.js.map +1 -1
- package/lib/Bundle/NamespaceImportPlugin.d.ts +55 -0
- package/lib/Bundle/NamespaceImportPlugin.d.ts.map +1 -0
- package/lib/Bundle/NamespaceImportPlugin.js +226 -0
- package/lib/Bundle/NamespaceImportPlugin.js.map +1 -0
- package/lib/Bundle/index.d.ts +1 -0
- package/lib/Bundle/index.d.ts.map +1 -1
- package/lib/Bundle/index.js +1 -0
- package/lib/Bundle/index.js.map +1 -1
- package/lib/Cli/Format.d.ts.map +1 -1
- package/lib/Cli/Format.js +2 -1
- package/lib/Cli/Format.js.map +1 -1
- package/lib/Cli/GlobalLog.d.ts +72 -26
- package/lib/Cli/GlobalLog.d.ts.map +1 -1
- package/lib/Cli/GlobalLog.js +151 -59
- package/lib/Cli/GlobalLog.js.map +1 -1
- package/lib/Cli/LoggingCli.d.ts.map +1 -1
- package/lib/Cli/LoggingCli.js +24 -18
- package/lib/Cli/LoggingCli.js.map +1 -1
- package/lib/Cli/PlainCliFormatter.d.ts.map +1 -1
- package/lib/Cli/PlainCliFormatter.js +4 -1
- package/lib/Cli/PlainCliFormatter.js.map +1 -1
- package/lib/Cli/Present.d.ts +14 -0
- package/lib/Cli/Present.d.ts.map +1 -0
- package/lib/Cli/Present.js +22 -0
- package/lib/Cli/Present.js.map +1 -0
- package/lib/Cli/SigilRenderer.d.ts +58 -0
- package/lib/Cli/SigilRenderer.d.ts.map +1 -0
- package/lib/Cli/SigilRenderer.js +39 -0
- package/lib/Cli/SigilRenderer.js.map +1 -0
- package/lib/Cli/checkVersion.d.ts +11 -14
- package/lib/Cli/checkVersion.d.ts.map +1 -1
- package/lib/Cli/checkVersion.js +19 -77
- package/lib/Cli/checkVersion.js.map +1 -1
- package/lib/Cli/commands/confirm.d.ts +2 -2
- package/lib/Cli/commands/confirm.d.ts.map +1 -1
- package/lib/Cli/commands/confirm.js +3 -3
- package/lib/Cli/commands/confirm.js.map +1 -1
- package/lib/Cli/commands/deploy.d.ts +4 -4
- package/lib/Cli/commands/deploy.d.ts.map +1 -1
- package/lib/Cli/commands/deploy.js +40 -39
- package/lib/Cli/commands/deploy.js.map +1 -1
- package/lib/Cli/commands/dev.d.ts.map +1 -1
- package/lib/Cli/commands/dev.js +41 -3
- package/lib/Cli/commands/dev.js.map +1 -1
- package/lib/Cli/commands/drift.d.ts +2 -2
- package/lib/Cli/commands/drift.d.ts.map +1 -1
- package/lib/Cli/commands/drift.js +14 -13
- package/lib/Cli/commands/drift.js.map +1 -1
- package/lib/Cli/commands/errors.d.ts.map +1 -1
- package/lib/Cli/commands/errors.js +2 -1
- package/lib/Cli/commands/errors.js.map +1 -1
- package/lib/Cli/commands/instrument.d.ts +15 -5
- package/lib/Cli/commands/instrument.d.ts.map +1 -1
- package/lib/Cli/commands/instrument.js +33 -8
- package/lib/Cli/commands/instrument.js.map +1 -1
- package/lib/Cli/commands/logs.d.ts +1 -1
- package/lib/Cli/commands/logs.d.ts.map +1 -1
- package/lib/Cli/commands/logs.js +22 -22
- package/lib/Cli/commands/logs.js.map +1 -1
- package/lib/Cli/commands/nuke.d.ts +3 -2
- package/lib/Cli/commands/nuke.d.ts.map +1 -1
- package/lib/Cli/commands/nuke.js +19 -17
- package/lib/Cli/commands/nuke.js.map +1 -1
- package/lib/Cli/commands/profile/commands.d.ts +3 -2
- package/lib/Cli/commands/profile/commands.d.ts.map +1 -1
- package/lib/Cli/commands/profile/commands.js +26 -27
- package/lib/Cli/commands/profile/commands.js.map +1 -1
- package/lib/Cli/commands/profile/flows.d.ts +6 -5
- package/lib/Cli/commands/profile/flows.d.ts.map +1 -1
- package/lib/Cli/commands/profile/flows.js +19 -17
- package/lib/Cli/commands/profile/flows.js.map +1 -1
- package/lib/Cli/commands/profile/hub.d.ts +1 -2
- package/lib/Cli/commands/profile/hub.d.ts.map +1 -1
- package/lib/Cli/commands/profile/hub.js +15 -17
- package/lib/Cli/commands/profile/hub.js.map +1 -1
- package/lib/Cli/commands/provider.d.ts +3 -1
- package/lib/Cli/commands/provider.d.ts.map +1 -1
- package/lib/Cli/commands/provider.js +4 -4
- package/lib/Cli/commands/provider.js.map +1 -1
- package/lib/Cli/commands/render.d.ts +2 -4
- package/lib/Cli/commands/render.d.ts.map +1 -1
- package/lib/Cli/commands/render.js +33 -56
- package/lib/Cli/commands/render.js.map +1 -1
- package/lib/Cli/commands/state.d.ts +1 -2
- package/lib/Cli/commands/state.d.ts.map +1 -1
- package/lib/Cli/commands/state.js +74 -27
- package/lib/Cli/commands/state.js.map +1 -1
- package/lib/Cli/components/capabilities.d.ts +4 -0
- package/lib/Cli/components/capabilities.d.ts.map +1 -0
- package/lib/Cli/components/capabilities.js +18 -0
- package/lib/Cli/components/capabilities.js.map +1 -0
- package/lib/Cli/components/types.d.ts +2 -81
- package/lib/Cli/components/types.d.ts.map +1 -1
- package/lib/Cli/components/types.js +1 -3
- package/lib/Cli/components/types.js.map +1 -1
- package/lib/Cli/components/ui/Environment.d.ts +3 -3
- package/lib/Cli/components/ui/Environment.d.ts.map +1 -1
- package/lib/Cli/components/ui/Environment.js.map +1 -1
- package/lib/Cli/components/ui/Interactive.d.ts +17 -4
- package/lib/Cli/components/ui/Interactive.d.ts.map +1 -1
- package/lib/Cli/components/ui/Interactive.js +7 -11
- package/lib/Cli/components/ui/Interactive.js.map +1 -1
- package/lib/Cli/components/ui/Layout.d.ts +1 -1
- package/lib/Cli/components/ui/Layout.d.ts.map +1 -1
- package/lib/Cli/components/ui/Layout.js +1 -1
- package/lib/Cli/components/ui/Layout.js.map +1 -1
- package/lib/Cli/components/ui/Typography.d.ts +1 -1
- package/lib/Cli/components/ui/Typography.d.ts.map +1 -1
- package/lib/Cli/components/ui/Typography.js +1 -1
- package/lib/Cli/components/ui/Typography.js.map +1 -1
- package/lib/Cli/components/ui/index.d.ts +2 -2
- package/lib/Cli/components/ui/index.js +2 -2
- package/lib/Cli/components/view/ApprovePlan.d.ts +1 -1
- package/lib/Cli/components/view/ApprovePlan.d.ts.map +1 -1
- package/lib/Cli/components/view/ApprovePlan.js +2 -1
- package/lib/Cli/components/view/ApprovePlan.js.map +1 -1
- package/lib/Cli/components/view/Format.d.ts +5 -0
- package/lib/Cli/components/view/Format.d.ts.map +1 -0
- package/lib/Cli/components/view/Format.js +39 -0
- package/lib/Cli/components/view/Format.js.map +1 -0
- package/lib/Cli/components/view/Help.d.ts +2 -2
- package/lib/Cli/components/view/Help.d.ts.map +1 -1
- package/lib/Cli/components/view/Help.js +7 -5
- package/lib/Cli/components/view/Help.js.map +1 -1
- package/lib/Cli/components/view/Logo.js +1 -1
- package/lib/Cli/components/view/Logo.js.map +1 -1
- package/lib/Cli/components/view/Nuke.d.ts +8 -9
- package/lib/Cli/components/view/Nuke.d.ts.map +1 -1
- package/lib/Cli/components/view/Nuke.js +49 -52
- package/lib/Cli/components/view/Nuke.js.map +1 -1
- package/lib/Cli/components/view/PlanDecision.d.ts +1 -1
- package/lib/Cli/components/view/PlanDecision.d.ts.map +1 -1
- package/lib/Cli/components/view/PlanDecision.js +1 -1
- package/lib/Cli/components/view/PlanDecision.js.map +1 -1
- package/lib/Cli/components/view/PlanRow.js +1 -1
- package/lib/Cli/components/view/PlanRow.js.map +1 -1
- package/lib/Cli/components/view/PlanTree.d.ts +1 -1
- package/lib/Cli/components/view/PlanTree.d.ts.map +1 -1
- package/lib/Cli/components/view/PlanTree.js +1 -1
- package/lib/Cli/components/view/PlanView.js +1 -1
- package/lib/Cli/components/view/PlanView.js.map +1 -1
- package/lib/Cli/components/view/Profile.d.ts +1 -1
- package/lib/Cli/components/view/Profile.js +2 -2
- package/lib/Cli/components/view/Profile.js.map +1 -1
- package/lib/Cli/components/view/ProfileDashboard.d.ts +4 -4
- package/lib/Cli/components/view/ProfileDashboard.d.ts.map +1 -1
- package/lib/Cli/components/view/ProfileDashboard.js +9 -8
- package/lib/Cli/components/view/ProfileDashboard.js.map +1 -1
- package/lib/Cli/components/view/Prompts.d.ts +3 -3
- package/lib/Cli/components/view/Prompts.d.ts.map +1 -1
- package/lib/Cli/components/view/Prompts.js +11 -18
- package/lib/Cli/components/view/Prompts.js.map +1 -1
- package/lib/Cli/components/view/Runtime.d.ts +5 -5
- package/lib/Cli/components/view/Runtime.d.ts.map +1 -1
- package/lib/Cli/components/view/Runtime.js +136 -219
- package/lib/Cli/components/view/Runtime.js.map +1 -1
- package/lib/Cli/components/view/SigilCli.d.ts +2 -2
- package/lib/Cli/components/view/SigilCli.d.ts.map +1 -1
- package/lib/Cli/components/view/SigilCli.js +7 -7
- package/lib/Cli/components/view/SigilCli.js.map +1 -1
- package/lib/Cli/components/view/StateExplorer.d.ts +1 -1
- package/lib/Cli/components/view/StateExplorer.d.ts.map +1 -1
- package/lib/Cli/components/view/StateExplorer.js +2 -1
- package/lib/Cli/components/view/StateExplorer.js.map +1 -1
- package/lib/Cli/components/view/statusStyle.d.ts +2 -2
- package/lib/Cli/components/view/statusStyle.d.ts.map +1 -1
- package/lib/Cli/components/view/statusStyle.js +1 -1
- package/lib/Cli/components/view/statusStyle.js.map +1 -1
- package/lib/Cli/exec.d.ts +6 -1
- package/lib/Cli/exec.d.ts.map +1 -1
- package/lib/Cli/exec.js +29 -34
- package/lib/Cli/exec.js.map +1 -1
- package/lib/Cli/main.d.ts.map +1 -1
- package/lib/Cli/main.js +35 -26
- package/lib/Cli/main.js.map +1 -1
- package/lib/Cli/selectCli.d.ts +2 -2
- package/lib/Cli/selectCli.d.ts.map +1 -1
- package/lib/Cli/selectCli.js +2 -2
- package/lib/Cli/selectCli.js.map +1 -1
- package/lib/Command/Command.js +1 -1
- package/lib/Command/Command.js.map +1 -1
- package/lib/Command/Dev.d.ts +58 -4
- package/lib/Command/Dev.d.ts.map +1 -1
- package/lib/Command/Dev.js +87 -30
- package/lib/Command/Dev.js.map +1 -1
- package/lib/Command/Local.d.ts +1 -1
- package/lib/Command/Memo.js +1 -1
- package/lib/Command/Memo.js.map +1 -1
- package/lib/Command/Providers.d.ts +1 -1
- package/lib/Command/Providers.d.ts.map +1 -1
- package/lib/Contributions.d.ts +2 -3
- package/lib/Contributions.d.ts.map +1 -1
- package/lib/Contributions.js +38 -6
- package/lib/Contributions.js.map +1 -1
- package/lib/DNS/Adapter.d.ts +204 -0
- package/lib/DNS/Adapter.d.ts.map +1 -0
- package/lib/DNS/Adapter.js +112 -0
- package/lib/DNS/Adapter.js.map +1 -0
- package/lib/DNS/index.d.ts +2 -0
- package/lib/DNS/index.d.ts.map +1 -0
- package/lib/DNS/index.js +2 -0
- package/lib/DNS/index.js.map +1 -0
- package/lib/Deploy.d.ts +7 -2
- package/lib/Deploy.d.ts.map +1 -1
- package/lib/Deploy.js +8 -3
- package/lib/Deploy.js.map +1 -1
- package/lib/Destroy.d.ts +5 -8
- package/lib/Destroy.d.ts.map +1 -1
- package/lib/Destroy.js +10 -7
- package/lib/Destroy.js.map +1 -1
- package/lib/Diff.d.ts.map +1 -1
- package/lib/Diff.js +14 -4
- package/lib/Diff.js.map +1 -1
- package/lib/Drift.d.ts +7 -7
- package/lib/Drift.d.ts.map +1 -1
- package/lib/Drift.js +184 -101
- package/lib/Drift.js.map +1 -1
- package/lib/EvalStack.d.ts +23 -0
- package/lib/EvalStack.d.ts.map +1 -0
- package/lib/EvalStack.js +47 -0
- package/lib/EvalStack.js.map +1 -0
- package/lib/Events.d.ts +210 -0
- package/lib/Events.d.ts.map +1 -0
- package/lib/Events.js +244 -0
- package/lib/Events.js.map +1 -0
- package/lib/Interaction.d.ts +159 -48
- package/lib/Interaction.d.ts.map +1 -1
- package/lib/Interaction.js +139 -58
- package/lib/Interaction.js.map +1 -1
- package/lib/Local/LocalProvider.d.ts.map +1 -1
- package/lib/Local/LocalProvider.js +31 -9
- package/lib/Local/LocalProvider.js.map +1 -1
- package/lib/Local/RpcProvider.d.ts.map +1 -1
- package/lib/Local/RpcProvider.js +10 -1
- package/lib/Local/RpcProvider.js.map +1 -1
- package/lib/Local/RpcProviderProxy.d.ts +16 -0
- package/lib/Local/RpcProviderProxy.d.ts.map +1 -1
- package/lib/Local/RpcProviderProxy.js +19 -10
- package/lib/Local/RpcProviderProxy.js.map +1 -1
- package/lib/Local/RpcSerialization.d.ts +3 -2
- package/lib/Local/RpcSerialization.d.ts.map +1 -1
- package/lib/Local/RpcSerialization.js +13 -10
- package/lib/Local/RpcSerialization.js.map +1 -1
- package/lib/Local/RpcServer.d.ts +2 -1
- package/lib/Local/RpcServer.d.ts.map +1 -1
- package/lib/Local/RpcServer.js +19 -14
- package/lib/Local/RpcServer.js.map +1 -1
- package/lib/Local/RpcServerBun.d.ts.map +1 -1
- package/lib/Local/RpcServerBun.js +8 -4
- package/lib/Local/RpcServerBun.js.map +1 -1
- package/lib/Local/RpcServerEnvironment.d.ts +2 -3
- package/lib/Local/RpcServerEnvironment.d.ts.map +1 -1
- package/lib/Local/RpcServerEnvironment.js +2 -2
- package/lib/Local/RpcServerEnvironment.js.map +1 -1
- package/lib/Local/RpcServerNode.d.ts.map +1 -1
- package/lib/Local/RpcServerNode.js +5 -1
- package/lib/Local/RpcServerNode.js.map +1 -1
- package/lib/Local/RpcServerSession.d.ts +1 -1
- package/lib/Local/RpcServerSession.d.ts.map +1 -1
- package/lib/Local/RpcServerSession.js.map +1 -1
- package/lib/Local/RpcSpawner.d.ts +6 -8
- package/lib/Local/RpcSpawner.d.ts.map +1 -1
- package/lib/Local/RpcSpawner.js +45 -36
- package/lib/Local/RpcSpawner.js.map +1 -1
- package/lib/Local/Sidecar.d.ts +23 -0
- package/lib/Local/Sidecar.d.ts.map +1 -1
- package/lib/Local/Sidecar.js +14 -9
- package/lib/Local/Sidecar.js.map +1 -1
- package/lib/Nuke.d.ts +5 -23
- package/lib/Nuke.d.ts.map +1 -1
- package/lib/Nuke.js +48 -13
- package/lib/Nuke.js.map +1 -1
- package/lib/Output.d.ts +19 -1
- package/lib/Output.d.ts.map +1 -1
- package/lib/Output.js +96 -3
- package/lib/Output.js.map +1 -1
- package/lib/Plan.d.ts +5 -1
- package/lib/Plan.d.ts.map +1 -1
- package/lib/Plan.js +111 -33
- package/lib/Plan.js.map +1 -1
- package/lib/Platform.d.ts.map +1 -1
- package/lib/Platform.js +31 -7
- package/lib/Platform.js.map +1 -1
- package/lib/Provider.d.ts +45 -0
- package/lib/Provider.d.ts.map +1 -1
- package/lib/Provider.js +2 -2
- package/lib/Provider.js.map +1 -1
- package/lib/Report.d.ts +17 -195
- package/lib/Report.d.ts.map +1 -1
- package/lib/Report.js +39 -12
- package/lib/Report.js.map +1 -1
- package/lib/Runtime/ManagedHttpShutdown.d.ts +17 -0
- package/lib/Runtime/ManagedHttpShutdown.d.ts.map +1 -1
- package/lib/Runtime/ManagedHttpShutdown.js +11 -2
- package/lib/Runtime/ManagedHttpShutdown.js.map +1 -1
- package/lib/RuntimeContext.js +1 -1
- package/lib/RuntimeContext.js.map +1 -1
- package/lib/Stack.d.ts +49 -29
- package/lib/Stack.d.ts.map +1 -1
- package/lib/Stack.js +25 -31
- package/lib/Stack.js.map +1 -1
- package/lib/State/BucketState.d.ts.map +1 -1
- package/lib/State/BucketState.js +43 -14
- package/lib/State/BucketState.js.map +1 -1
- package/lib/State/LocalState.d.ts.map +1 -1
- package/lib/State/LocalState.js +3 -3
- package/lib/State/LocalState.js.map +1 -1
- package/lib/State/Provisioning.d.ts +5 -0
- package/lib/State/Provisioning.d.ts.map +1 -1
- package/lib/State/Provisioning.js +3 -1
- package/lib/State/Provisioning.js.map +1 -1
- package/lib/State/ResourceState.d.ts +2 -0
- package/lib/State/ResourceState.d.ts.map +1 -1
- package/lib/State/State.d.ts +26 -0
- package/lib/State/State.d.ts.map +1 -1
- package/lib/State/StateEncoding.d.ts +7 -0
- package/lib/State/StateEncoding.d.ts.map +1 -1
- package/lib/State/StateEncoding.js +19 -0
- package/lib/State/StateEncoding.js.map +1 -1
- package/lib/State/index.js +2 -2
- package/lib/State/index.js.map +1 -1
- package/lib/Telemetry/Layer.d.ts +2 -5
- package/lib/Telemetry/Layer.d.ts.map +1 -1
- package/lib/Telemetry/Layer.js +3 -23
- package/lib/Telemetry/Layer.js.map +1 -1
- package/lib/Telemetry/Metrics.d.ts +1 -1
- package/lib/Telemetry/Metrics.d.ts.map +1 -1
- package/lib/TelemetryRelay.js +1 -1
- package/lib/TelemetryRelay.js.map +1 -1
- package/lib/TelemetryRuntime.d.ts +1 -1
- package/lib/TelemetryRuntime.d.ts.map +1 -1
- package/lib/TelemetryRuntime.js +4 -3
- package/lib/TelemetryRuntime.js.map +1 -1
- package/lib/Util/ConsoleSink.d.ts +23 -2
- package/lib/Util/ConsoleSink.d.ts.map +1 -1
- package/lib/Util/ConsoleSink.js +54 -14
- package/lib/Util/ConsoleSink.js.map +1 -1
- package/lib/Util/LogAnnotation.d.ts +19 -0
- package/lib/Util/LogAnnotation.d.ts.map +1 -0
- package/lib/Util/LogAnnotation.js +19 -0
- package/lib/Util/LogAnnotation.js.map +1 -0
- package/lib/Util/LogRecord.d.ts +281 -0
- package/lib/Util/LogRecord.d.ts.map +1 -0
- package/lib/Util/LogRecord.js +267 -0
- package/lib/Util/LogRecord.js.map +1 -0
- package/lib/Util/Node.d.ts +9 -0
- package/lib/Util/Node.d.ts.map +1 -1
- package/lib/Util/Node.js +10 -6
- package/lib/Util/Node.js.map +1 -1
- package/lib/Util/PlatformServices.d.ts +3 -2
- package/lib/Util/PlatformServices.d.ts.map +1 -1
- package/lib/Util/PlatformServices.js +6 -2
- package/lib/Util/PlatformServices.js.map +1 -1
- package/lib/Util/ResourceOutput.d.ts +18 -10
- package/lib/Util/ResourceOutput.d.ts.map +1 -1
- package/lib/Util/ResourceOutput.js +22 -23
- package/lib/Util/ResourceOutput.js.map +1 -1
- package/lib/Util/Shutdown.d.ts +10 -0
- package/lib/Util/Shutdown.d.ts.map +1 -0
- package/lib/Util/Shutdown.js +32 -0
- package/lib/Util/Shutdown.js.map +1 -0
- package/lib/Util/Terminal.d.ts +2 -4
- package/lib/Util/Terminal.d.ts.map +1 -1
- package/lib/Util/Terminal.js +3 -11
- package/lib/Util/Terminal.js.map +1 -1
- package/lib/Util/TraceParent.d.ts +32 -0
- package/lib/Util/TraceParent.d.ts.map +1 -0
- package/lib/Util/TraceParent.js +42 -0
- package/lib/Util/TraceParent.js.map +1 -0
- package/lib/Util/base64.d.ts +7 -0
- package/lib/Util/base64.d.ts.map +1 -0
- package/lib/Util/base64.js +24 -0
- package/lib/Util/base64.js.map +1 -0
- package/lib/Util/cached-function.d.ts +5 -0
- package/lib/Util/cached-function.d.ts.map +1 -1
- package/lib/Util/cached-function.js +13 -8
- package/lib/Util/cached-function.js.map +1 -1
- package/lib/Util/data.d.ts +1 -1
- package/lib/Util/data.d.ts.map +1 -1
- package/lib/Util/data.js +1 -1
- package/lib/Util/data.js.map +1 -1
- package/lib/Util/equal.d.ts.map +1 -1
- package/lib/Util/equal.js +3 -2
- package/lib/Util/equal.js.map +1 -1
- package/lib/Util/extraFiles.d.ts.map +1 -1
- package/lib/Util/extraFiles.js +5 -5
- package/lib/Util/extraFiles.js.map +1 -1
- package/lib/Util/interactive.js +1 -1
- package/lib/Website/AstroOutput.d.ts +42 -0
- package/lib/Website/AstroOutput.d.ts.map +1 -0
- package/lib/Website/AstroOutput.js +34 -0
- package/lib/Website/AstroOutput.js.map +1 -0
- package/lib/Website/FrontendCore.d.ts +1 -1
- package/lib/Workflows.d.ts +9 -0
- package/lib/Workflows.d.ts.map +1 -1
- package/lib/Workflows.js +8 -0
- package/lib/Workflows.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/package.json +21 -28
- package/src/AdoptPolicy.ts +76 -0
- package/src/Alchemist/AuthRegistry.ts +164 -0
- package/src/Alchemist/Drift.ts +103 -0
- package/src/Alchemist/Entrypoint.ts +51 -3
- package/src/Alchemist/Errors.ts +1 -1
- package/src/Alchemist/{routes/logs.ts → Logs.ts} +28 -30
- package/src/Alchemist/Nuke.ts +90 -0
- package/src/Alchemist/Operations.ts +309 -0
- package/src/Alchemist/{routes/profile.ts → Profile.ts} +22 -22
- package/src/Alchemist/{routes/provider.ts → Provider.ts} +7 -6
- package/src/Alchemist/Runtime.ts +46 -12
- package/src/Alchemist/{routes/state.ts → State.ts} +78 -21
- package/src/Alchemist/index.ts +32 -15
- package/src/Apply.ts +513 -274
- package/src/Auth/AuthProvider.ts +76 -23
- package/src/Auth/BrowserOAuth.ts +37 -60
- package/src/Auth/Credentials.ts +2 -4
- package/src/Auth/Demand.ts +27 -18
- package/src/Auth/Env.ts +13 -8
- package/src/Auth/Inspect.ts +5 -2
- package/src/Auth/Lock.ts +4 -8
- package/src/Auth/OAuthFlow.ts +12 -26
- package/src/Auth/Paths.ts +3 -2
- package/src/Auth/Profile.ts +30 -2
- package/src/Auth/Registry.ts +27 -0
- package/src/Auth/Resolve.ts +75 -3
- package/src/Auth/StoredAuthProvider.ts +1 -2
- package/src/Binding.ts +3 -4
- package/src/Bundle/Bundle.ts +58 -7
- package/src/Bundle/NamespaceImportPlugin.ts +259 -0
- package/src/Bundle/index.ts +1 -0
- package/src/Cli/Format.ts +2 -1
- package/src/Cli/GlobalLog.ts +206 -68
- package/src/Cli/LoggingCli.ts +33 -20
- package/src/Cli/PlainCliFormatter.ts +4 -1
- package/src/Cli/Present.ts +34 -0
- package/src/Cli/SigilRenderer.ts +75 -0
- package/src/Cli/checkVersion.ts +25 -78
- package/src/Cli/commands/confirm.ts +3 -3
- package/src/Cli/commands/deploy.ts +53 -44
- package/src/Cli/commands/dev.ts +65 -7
- package/src/Cli/commands/drift.ts +20 -16
- package/src/Cli/commands/errors.ts +2 -3
- package/src/Cli/commands/instrument.ts +39 -8
- package/src/Cli/commands/logs.ts +22 -30
- package/src/Cli/commands/nuke.ts +25 -26
- package/src/Cli/commands/profile/commands.ts +34 -34
- package/src/Cli/commands/profile/flows.ts +26 -20
- package/src/Cli/commands/profile/hub.ts +16 -18
- package/src/Cli/commands/provider.ts +4 -4
- package/src/Cli/commands/render.ts +43 -71
- package/src/Cli/commands/state.ts +113 -33
- package/src/Cli/components/capabilities.ts +20 -0
- package/src/Cli/components/types.ts +13 -99
- package/src/Cli/components/ui/Environment.tsx +5 -5
- package/src/Cli/components/ui/Interactive.tsx +24 -15
- package/src/Cli/components/ui/Layout.tsx +1 -1
- package/src/Cli/components/ui/Typography.tsx +1 -1
- package/src/Cli/components/ui/index.ts +2 -2
- package/src/Cli/components/view/ApprovePlan.tsx +2 -1
- package/src/Cli/components/view/Format.tsx +58 -0
- package/src/Cli/components/view/Help.tsx +14 -17
- package/src/Cli/components/view/Logo.tsx +1 -1
- package/src/Cli/components/view/Nuke.tsx +74 -49
- package/src/Cli/components/view/PlanDecision.tsx +1 -1
- package/src/Cli/components/view/PlanRow.tsx +1 -1
- package/src/Cli/components/view/PlanTree.ts +2 -2
- package/src/Cli/components/view/PlanView.tsx +2 -2
- package/src/Cli/components/view/Profile.tsx +2 -2
- package/src/Cli/components/view/ProfileDashboard.tsx +12 -11
- package/src/Cli/components/view/Prompts.tsx +37 -75
- package/src/Cli/components/view/Runtime.tsx +132 -238
- package/src/Cli/components/view/SigilCli.tsx +12 -12
- package/src/Cli/components/view/StateExplorer.tsx +2 -1
- package/src/Cli/components/view/statusStyle.ts +2 -2
- package/src/Cli/exec.ts +48 -41
- package/src/Cli/main.ts +52 -33
- package/src/Cli/selectCli.ts +3 -3
- package/src/Command/Command.ts +1 -1
- package/src/Command/Dev.ts +129 -36
- package/src/Command/Memo.ts +1 -1
- package/src/Contributions.ts +42 -8
- package/src/DNS/Adapter.ts +289 -0
- package/src/DNS/index.ts +1 -0
- package/src/Deploy.ts +11 -3
- package/src/Destroy.ts +19 -13
- package/src/Diff.ts +17 -4
- package/src/Drift.ts +256 -127
- package/src/EvalStack.ts +97 -0
- package/src/Events.ts +296 -0
- package/src/Interaction.ts +332 -97
- package/src/Local/LocalProvider.ts +40 -9
- package/src/Local/RpcProvider.ts +11 -1
- package/src/Local/RpcProviderProxy.ts +29 -21
- package/src/Local/RpcSerialization.ts +32 -17
- package/src/Local/RpcServer.ts +25 -17
- package/src/Local/RpcServerBun.ts +10 -6
- package/src/Local/RpcServerEnvironment.ts +2 -2
- package/src/Local/RpcServerNode.ts +8 -1
- package/src/Local/RpcServerSession.ts +2 -2
- package/src/Local/RpcSpawner.ts +61 -37
- package/src/Local/Sidecar.ts +10 -1
- package/src/Nuke.ts +66 -43
- package/src/Output.ts +120 -7
- package/src/Plan.ts +140 -52
- package/src/Platform.ts +47 -18
- package/src/Provider.ts +48 -3
- package/src/Report.ts +77 -275
- package/src/Runtime/ManagedHttpShutdown.ts +21 -4
- package/src/RuntimeContext.ts +1 -1
- package/src/Stack.ts +113 -135
- package/src/State/BucketState.ts +53 -21
- package/src/State/LocalState.ts +7 -9
- package/src/State/Provisioning.ts +8 -1
- package/src/State/ResourceState.ts +2 -0
- package/src/State/State.ts +30 -0
- package/src/State/StateEncoding.ts +22 -0
- package/src/State/index.ts +2 -2
- package/src/Telemetry/Layer.ts +3 -24
- package/src/Telemetry/Metrics.ts +1 -1
- package/src/TelemetryRelay.ts +1 -1
- package/src/TelemetryRuntime.ts +8 -8
- package/src/Util/ConsoleSink.ts +76 -13
- package/src/Util/LogAnnotation.ts +18 -0
- package/src/Util/LogRecord.ts +386 -0
- package/src/Util/Node.ts +20 -6
- package/src/Util/PlatformServices.ts +17 -4
- package/src/Util/ResourceOutput.ts +26 -25
- package/src/Util/Shutdown.ts +52 -0
- package/src/Util/Terminal.ts +3 -20
- package/src/Util/TraceParent.ts +70 -0
- package/src/Util/base64.ts +22 -0
- package/src/Util/cached-function.ts +30 -19
- package/src/Util/data.ts +2 -2
- package/src/Util/equal.ts +3 -2
- package/src/Util/extraFiles.ts +9 -8
- package/src/Util/interactive.ts +1 -1
- package/src/Website/AstroOutput.ts +83 -0
- package/src/Workflows.ts +11 -0
- package/src/index.ts +1 -0
- package/lib/Alchemist/Progress.d.ts +0 -16
- package/lib/Alchemist/Progress.d.ts.map +0 -1
- package/lib/Alchemist/Progress.js +0 -123
- package/lib/Alchemist/Progress.js.map +0 -1
- package/lib/Alchemist/Session.d.ts +0 -116
- package/lib/Alchemist/Session.d.ts.map +0 -1
- package/lib/Alchemist/Session.js +0 -212
- package/lib/Alchemist/Session.js.map +0 -1
- package/lib/Alchemist/routes/drift.d.ts +0 -55
- package/lib/Alchemist/routes/drift.d.ts.map +0 -1
- package/lib/Alchemist/routes/drift.js +0 -52
- package/lib/Alchemist/routes/drift.js.map +0 -1
- package/lib/Alchemist/routes/logs.d.ts +0 -41
- package/lib/Alchemist/routes/logs.d.ts.map +0 -1
- package/lib/Alchemist/routes/logs.js.map +0 -1
- package/lib/Alchemist/routes/nuke.d.ts +0 -46
- package/lib/Alchemist/routes/nuke.d.ts.map +0 -1
- package/lib/Alchemist/routes/nuke.js +0 -80
- package/lib/Alchemist/routes/nuke.js.map +0 -1
- package/lib/Alchemist/routes/profile.d.ts +0 -133
- package/lib/Alchemist/routes/profile.d.ts.map +0 -1
- package/lib/Alchemist/routes/profile.js.map +0 -1
- package/lib/Alchemist/routes/provider.d.ts.map +0 -1
- package/lib/Alchemist/routes/provider.js.map +0 -1
- package/lib/Alchemist/routes/stack.d.ts +0 -95
- package/lib/Alchemist/routes/stack.d.ts.map +0 -1
- package/lib/Alchemist/routes/stack.js +0 -73
- package/lib/Alchemist/routes/stack.js.map +0 -1
- package/lib/Alchemist/routes/state.d.ts.map +0 -1
- package/lib/Alchemist/routes/state.js.map +0 -1
- package/lib/Cli/CliKit/CliKit.d.ts +0 -92
- package/lib/Cli/CliKit/CliKit.d.ts.map +0 -1
- package/lib/Cli/CliKit/CliKit.js +0 -27
- package/lib/Cli/CliKit/CliKit.js.map +0 -1
- package/lib/Cli/CliKit/index.d.ts +0 -9
- package/lib/Cli/CliKit/index.d.ts.map +0 -1
- package/lib/Cli/CliKit/index.js +0 -9
- package/lib/Cli/CliKit/index.js.map +0 -1
- package/lib/Cli/CliKit/interaction.d.ts +0 -13
- package/lib/Cli/CliKit/interaction.d.ts.map +0 -1
- package/lib/Cli/CliKit/interaction.js +0 -17
- package/lib/Cli/CliKit/interaction.js.map +0 -1
- package/lib/Cli/CliKit/layer.d.ts +0 -7
- package/lib/Cli/CliKit/layer.d.ts.map +0 -1
- package/lib/Cli/CliKit/layer.js +0 -33
- package/lib/Cli/CliKit/layer.js.map +0 -1
- package/lib/Local/DevLog.d.ts +0 -32
- package/lib/Local/DevLog.d.ts.map +0 -1
- package/lib/Local/DevLog.js +0 -112
- package/lib/Local/DevLog.js.map +0 -1
- package/lib/Test/Alchemy.d.ts +0 -79
- package/lib/Test/Alchemy.d.ts.map +0 -1
- package/lib/Test/Alchemy.js +0 -193
- package/lib/Test/Alchemy.js.map +0 -1
- package/lib/Test/Bun.d.ts +0 -69
- package/lib/Test/Bun.d.ts.map +0 -1
- package/lib/Test/Bun.js +0 -126
- package/lib/Test/Bun.js.map +0 -1
- package/lib/Test/Core.d.ts +0 -277
- package/lib/Test/Core.d.ts.map +0 -1
- package/lib/Test/Core.js +0 -362
- package/lib/Test/Core.js.map +0 -1
- package/lib/Test/Http.d.ts +0 -109
- package/lib/Test/Http.d.ts.map +0 -1
- package/lib/Test/Http.js +0 -123
- package/lib/Test/Http.js.map +0 -1
- package/lib/Test/TestState.d.ts +0 -12
- package/lib/Test/TestState.d.ts.map +0 -1
- package/lib/Test/TestState.js +0 -15
- package/lib/Test/TestState.js.map +0 -1
- package/lib/Test/Vitest.d.ts +0 -60
- package/lib/Test/Vitest.d.ts.map +0 -1
- package/lib/Test/Vitest.js +0 -132
- package/lib/Test/Vitest.js.map +0 -1
- package/lib/Test/index.d.ts +0 -3
- package/lib/Test/index.d.ts.map +0 -1
- package/lib/Test/index.js +0 -3
- package/lib/Test/index.js.map +0 -1
- package/lib/Util/FileLogger.d.ts +0 -7
- package/lib/Util/FileLogger.d.ts.map +0 -1
- package/lib/Util/FileLogger.js +0 -16
- package/lib/Util/FileLogger.js.map +0 -1
- package/src/Alchemist/Progress.ts +0 -167
- package/src/Alchemist/Session.ts +0 -415
- package/src/Alchemist/routes/drift.ts +0 -87
- package/src/Alchemist/routes/nuke.ts +0 -131
- package/src/Alchemist/routes/stack.ts +0 -173
- package/src/Cli/CliKit/CliKit.ts +0 -159
- package/src/Cli/CliKit/index.ts +0 -41
- package/src/Cli/CliKit/interaction.ts +0 -19
- package/src/Cli/CliKit/layer.ts +0 -44
- package/src/Local/DevLog.ts +0 -122
- package/src/Test/Alchemy.ts +0 -334
- package/src/Test/Bun.ts +0 -230
- package/src/Test/Core.ts +0 -785
- package/src/Test/Http.ts +0 -201
- package/src/Test/TestState.ts +0 -35
- package/src/Test/Vitest.ts +0 -239
- package/src/Test/index.ts +0 -2
- package/src/Util/FileLogger.ts +0 -20
package/lib/Apply.js
CHANGED
|
@@ -2,28 +2,30 @@ import * as Cause from "effect/Cause";
|
|
|
2
2
|
import * as Data from "effect/Data";
|
|
3
3
|
import * as Deferred from "effect/Deferred";
|
|
4
4
|
import * as Effect from "effect/Effect";
|
|
5
|
-
import * as
|
|
5
|
+
import * as Formatter from "effect/Formatter";
|
|
6
6
|
import * as Layer from "effect/Layer";
|
|
7
7
|
import * as Option from "effect/Option";
|
|
8
8
|
import * as Predicate from "effect/Predicate";
|
|
9
9
|
import { makeResolveContext } from "./ActionRuntimeContext.js";
|
|
10
|
-
import { OwnedBySomeoneElse, stripUnowned, Unowned } from "./AdoptPolicy.js";
|
|
10
|
+
import { OwnedBySomeoneElse, stripUnowned, Unowned, Unresolved, UnverifiableReplacement, } from "./AdoptPolicy.js";
|
|
11
11
|
import { AlchemyContext } from "./AlchemyContext.js";
|
|
12
12
|
import { Artifacts, ArtifactStore, createArtifactStore, ensureArtifactStore, makeScopedArtifacts, } from "./Artifacts.js";
|
|
13
13
|
import { failCredentialsRequired, demandPlanCredentials, } from "./Auth/Demand.js";
|
|
14
|
-
import { havePropsChanged, stripUnresolved } from "./Diff.js";
|
|
14
|
+
import { havePropsChanged, isResolved, stripEffects, stripUnresolved } from "./Diff.js";
|
|
15
|
+
import { captureEmit } from "./Events.js";
|
|
15
16
|
import { generateInstanceId } from "./InstanceId.js";
|
|
16
17
|
import * as Output from "./Output.js";
|
|
17
18
|
import {} from "./Plan.js";
|
|
18
19
|
import { findProviderByType, missingProviderError, tryFindProviderByType, } from "./Provider.js";
|
|
19
20
|
import { stampedMode } from "./ProviderMode.js";
|
|
20
|
-
import {
|
|
21
|
+
import { resourceSession } from "./Report.js";
|
|
21
22
|
import { ResourceContext } from "./ResourceContext.js";
|
|
22
23
|
import { RuntimeContext } from "./RuntimeContext.js";
|
|
23
24
|
import { Stack } from "./Stack.js";
|
|
24
25
|
import { Stage } from "./Stage.js";
|
|
25
26
|
import { State, StateStoreError, } from "./State/index.js";
|
|
26
27
|
import { recordResourceOp } from "./Telemetry/Metrics.js";
|
|
28
|
+
import { LogAnnotation } from "./Util/LogAnnotation.js";
|
|
27
29
|
import { hashInput } from "./Util/sha256.js";
|
|
28
30
|
/**
|
|
29
31
|
* Record a resource's result in `tracker` and its output in `outputs`, the
|
|
@@ -35,6 +37,20 @@ const track = (tracker, outputs, fqn, entry) => {
|
|
|
35
37
|
tracker[fqn] = entry;
|
|
36
38
|
outputs[fqn] = entry.output;
|
|
37
39
|
};
|
|
40
|
+
/**
|
|
41
|
+
* Whether an attr-less checkpoint lost props to `stripUnresolved`. Its stored
|
|
42
|
+
* props no longer identify the physical resource it was creating (e.g. a
|
|
43
|
+
* stripped namespace makes a name match a different resource), so recovery
|
|
44
|
+
* must not look the resource up from them.
|
|
45
|
+
*
|
|
46
|
+
* Effect-valued props don't count: `Output.evaluate` passes them through
|
|
47
|
+
* untouched, so even fully resolved props carry them (a Function's runtime
|
|
48
|
+
* wiring). They never name a physical resource, and treating them as holes
|
|
49
|
+
* would mark every create of such a resource and orphan it on interruption.
|
|
50
|
+
*/
|
|
51
|
+
const propsIncomplete = (value) => value.attr === undefined && (value.propsIncomplete || !isResolved(stripEffects(value.props)))
|
|
52
|
+
? true
|
|
53
|
+
: undefined;
|
|
38
54
|
const provideLifecycleScope = (resource) => (effect) => Effect.serviceOption(ArtifactStore).pipe(Effect.map(Option.getOrElse(createArtifactStore)), Effect.flatMap((store) => effect.pipe(failCredentialsRequired(resource.fqn), Effect.provide([
|
|
39
55
|
Layer.succeed(Artifacts, makeScopedArtifacts(store, resource.fqn)),
|
|
40
56
|
Layer.succeed(ResourceContext, resource),
|
|
@@ -49,7 +65,9 @@ const provideLifecycleScope = (resource) => (effect) => Effect.serviceOption(Art
|
|
|
49
65
|
* are dispatched, so wrapping it here gives us a fully-instrumented
|
|
50
66
|
* toolchain without touching any individual provider implementation.
|
|
51
67
|
*/
|
|
52
|
-
const instrumentLifecycle = (op, fqn, resourceType, logicalId, instanceId) => (effect) => effect.pipe(provideLifecycleScope({ logicalId, fqn, instanceId, type: resourceType }),
|
|
68
|
+
const instrumentLifecycle = (op, fqn, resourceType, logicalId, instanceId) => (effect) => effect.pipe(provideLifecycleScope({ logicalId, fqn, instanceId, type: resourceType }),
|
|
69
|
+
// Every log a provider writes during the op carries its resource.
|
|
70
|
+
Effect.annotateLogs(LogAnnotation.fqn, fqn), recordResourceOp(resourceType, op), Effect.withSpan(`provider.${op}`, {
|
|
53
71
|
attributes: {
|
|
54
72
|
"alchemy.resource.fqn": fqn,
|
|
55
73
|
"alchemy.resource.type": resourceType,
|
|
@@ -58,7 +76,64 @@ const instrumentLifecycle = (op, fqn, resourceType, logicalId, instanceId) => (e
|
|
|
58
76
|
"alchemy.resource.op": op,
|
|
59
77
|
},
|
|
60
78
|
}));
|
|
61
|
-
|
|
79
|
+
/**
|
|
80
|
+
* A dependency cycle precreates on raw props, before `read` can check
|
|
81
|
+
* ownership. Ask the provider's `observe` what exists at the identity
|
|
82
|
+
* precreate would claim, and refuse a foreign resource unless adoption is
|
|
83
|
+
* allowed. A provider without `observe` precreates `unchecked`; one whose
|
|
84
|
+
* identity has not resolved yet reports it `unresolved`, so the engine must
|
|
85
|
+
* check the resolved identity before reconcile claims it.
|
|
86
|
+
*/
|
|
87
|
+
const observeBeforePrecreate = Effect.fn(function* (node, news, fqn, logicalId, instanceId, previous) {
|
|
88
|
+
if (node.provider.observe === undefined || node.deferredAdoption === undefined) {
|
|
89
|
+
return "unchecked";
|
|
90
|
+
}
|
|
91
|
+
const observed = yield* node.provider
|
|
92
|
+
.observe({ id: logicalId, fqn, instanceId, news, previous })
|
|
93
|
+
.pipe(instrumentLifecycle("observe", fqn, node.resource.Type, logicalId, instanceId));
|
|
94
|
+
if (observed === Unresolved)
|
|
95
|
+
return "unresolved";
|
|
96
|
+
if (observed !== undefined && Unowned.is(observed) && !node.deferredAdoption.adopt) {
|
|
97
|
+
return yield* new OwnedBySomeoneElse({
|
|
98
|
+
message: `Cannot pre-create resource '${fqn}' (${node.resource.Type}): ` +
|
|
99
|
+
"it exists in the cloud but is not owned by this " +
|
|
100
|
+
"stack/stage/logical-id. Re-run with `--adopt` (or " +
|
|
101
|
+
"wrap the effect in `adopt(true)`) to take it over.",
|
|
102
|
+
resourceType: node.resource.Type,
|
|
103
|
+
logicalId,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return "admitted";
|
|
107
|
+
});
|
|
108
|
+
/** A provider's `observe` reported `Unresolved` for fully resolved props. */
|
|
109
|
+
class UnresolvedObservation extends Data.TaggedError("UnresolvedObservation") {
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Reports what exists at the resolved identity reconcile will claim: `read`
|
|
113
|
+
* when the provider implements it, `observe` otherwise. A replacement passes
|
|
114
|
+
* its `previous` generation's attributes, so the provider can recognize it.
|
|
115
|
+
*/
|
|
116
|
+
const observeResolved = Effect.fn(function* (node, news, fqn, logicalId, instanceId, previous) {
|
|
117
|
+
if (node.provider.read) {
|
|
118
|
+
return yield* node.provider
|
|
119
|
+
.read({ id: logicalId, fqn, instanceId, olds: news, output: undefined, previous })
|
|
120
|
+
.pipe(instrumentLifecycle("read", fqn, node.resource.Type, logicalId, instanceId));
|
|
121
|
+
}
|
|
122
|
+
const observed = yield* node.provider.observe({
|
|
123
|
+
id: logicalId,
|
|
124
|
+
fqn,
|
|
125
|
+
instanceId,
|
|
126
|
+
news,
|
|
127
|
+
previous,
|
|
128
|
+
}).pipe(instrumentLifecycle("observe", fqn, node.resource.Type, logicalId, instanceId));
|
|
129
|
+
if (observed === Unresolved) {
|
|
130
|
+
return yield* Effect.die(new UnresolvedObservation({
|
|
131
|
+
message: `The provider for '${fqn}' (${node.resource.Type}) reported its identity as Unresolved, but its props are resolved.`,
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
return observed;
|
|
135
|
+
});
|
|
136
|
+
export const apply = (plan) => Effect.gen(function* () {
|
|
62
137
|
// Credential-free dev: a dev-mode plan that needs the real cloud
|
|
63
138
|
// (`Alchemy.remote()` rows, remote-proxied bindings, deletions of rows
|
|
64
139
|
// stamped `providerMode: "live"`) demands cloud credentials exactly
|
|
@@ -72,93 +147,99 @@ export const apply = (plan, options = {}) => Effect.gen(function* () {
|
|
|
72
147
|
if (Option.isSome(alchemy) && alchemy.value.dev) {
|
|
73
148
|
yield* demandPlanCredentials(plan);
|
|
74
149
|
}
|
|
75
|
-
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
const emitEvent = yield* captureEmit;
|
|
151
|
+
// The last status each resource announced, so the post-convergence
|
|
152
|
+
// flush below re-emits only what is still unannounced (cycle members).
|
|
153
|
+
const announced = new Map();
|
|
154
|
+
const reportEvent = (event) => {
|
|
155
|
+
if (event.type === "apply.resource.status")
|
|
156
|
+
announced.set(event.fqn, event.status);
|
|
157
|
+
return emitEvent(event);
|
|
158
|
+
};
|
|
159
|
+
// No Effect.scoped around apply: local dev providers start long-running
|
|
160
|
+
// processes in the AMBIENT scope during reconcile, which a scope here
|
|
161
|
+
// would kill when apply returns.
|
|
162
|
+
const state = yield* yield* State;
|
|
163
|
+
const stack = yield* Stack;
|
|
164
|
+
const stage = yield* Stage;
|
|
165
|
+
const stackName = stack.name;
|
|
166
|
+
const tracker = {};
|
|
167
|
+
const outputs = {};
|
|
168
|
+
const terminalStatuses = new Map();
|
|
169
|
+
// ── FQN migrations (renamedFrom) ──
|
|
170
|
+
// Persist renames before any lifecycle operation runs: a node whose row
|
|
171
|
+
// was found under a former FQN carries that row pre-remapped in
|
|
172
|
+
// `node.state` (see Plan's rename resolution). Commit it at the current
|
|
173
|
+
// FQN FIRST, then drop the former row — in that order, so an
|
|
174
|
+
// interruption leaves rows at both FQNs with the same instanceId, which
|
|
175
|
+
// the next plan recognizes as an in-flight migration (and never as an
|
|
176
|
+
// orphan to delete).
|
|
177
|
+
//
|
|
178
|
+
// In a same-deploy shift (A→B while B→C), C's former FQN `B` is
|
|
179
|
+
// simultaneously B's migration TARGET. C must NOT delete it: B's own
|
|
180
|
+
// `state.set` supersedes the stale copy, and the migrations run
|
|
181
|
+
// concurrently — the delete could land after B's write and destroy the
|
|
182
|
+
// freshly migrated row.
|
|
183
|
+
const migrationTargets = new Set(Object.values(plan.resources)
|
|
184
|
+
.filter((node) => node.renamedFrom?.length && node.state !== undefined)
|
|
185
|
+
.map((node) => node.resource.FQN));
|
|
186
|
+
yield* Effect.forEach(Object.values(plan.resources), (node) => {
|
|
187
|
+
const { renamedFrom, state: row } = node;
|
|
188
|
+
return renamedFrom === undefined || renamedFrom.length === 0 || row === undefined
|
|
189
|
+
? Effect.void
|
|
190
|
+
: Effect.gen(function* () {
|
|
191
|
+
yield* state.set({ stack: stackName, stage, fqn: node.resource.FQN, value: row });
|
|
192
|
+
yield* Effect.forEach(renamedFrom.filter((formerFqn) => !migrationTargets.has(formerFqn)), (formerFqn) => state.delete({ stack: stackName, stage, fqn: formerFqn }), { concurrency: "unbounded" });
|
|
193
|
+
});
|
|
194
|
+
}, { concurrency: "unbounded" });
|
|
195
|
+
yield* executePlan(plan, tracker, outputs, terminalStatuses, reportEvent, state, stackName, stage);
|
|
196
|
+
// TODO(sam): support roll back to previous state if errors occur during expansion
|
|
197
|
+
// -> RISK: some UPDATEs may not be reversible (i.e. trigger replacements)
|
|
198
|
+
// TODO(sam): should pivot be done separately? E.g shift traffic?
|
|
199
|
+
yield* collectGarbage(plan, reportEvent);
|
|
200
|
+
yield* converge(plan, tracker, outputs, terminalStatuses, reportEvent, state, stackName, stage);
|
|
201
|
+
// Cycle members hold their terminal status until `converge` settles
|
|
202
|
+
// it; everything else announced it as it finished.
|
|
203
|
+
yield* Effect.forEach(Array.from(terminalStatuses.values()).filter(({ fqn, status }) => announced.get(fqn) !== status), ({ fqn, id, type, status, providerMode }) => reportEvent({
|
|
204
|
+
type: "apply.resource.status",
|
|
205
|
+
fqn,
|
|
206
|
+
id,
|
|
207
|
+
resourceType: type,
|
|
208
|
+
status,
|
|
209
|
+
providerMode,
|
|
210
|
+
}), { concurrency: "unbounded" });
|
|
211
|
+
if (plan.destroy) {
|
|
212
|
+
// The destroy converged: every resource row was deleted above. Drop
|
|
213
|
+
// the rest of the stage's persisted state — notably the stack output
|
|
214
|
+
// record written by the last deploy — so `getOutput` returns
|
|
215
|
+
// undefined and `listStages` no longer reports the stage.
|
|
216
|
+
// https://github.com/alchemy-run/alchemy/issues/961
|
|
217
|
+
yield* state.deleteStack({ stack: stackName, stage });
|
|
218
|
+
// Invariant: a successful destroy leaves the stage EMPTY. If rows
|
|
219
|
+
// survive, this destroy session could not actually see (or delete)
|
|
220
|
+
// the stack's state — e.g. its plan listed an empty store while
|
|
221
|
+
// committed rows existed — and reporting success here would silently
|
|
222
|
+
// leak every cloud resource those rows track. Fail loudly instead so
|
|
223
|
+
// the leak surfaces in the run that caused it.
|
|
224
|
+
const remaining = yield* state.list({ stack: stackName, stage });
|
|
225
|
+
if (remaining.length > 0) {
|
|
226
|
+
return yield* new StateStoreError({
|
|
227
|
+
message: `destroy of ${stackName}/${stage} reported success but ${remaining.length} ` +
|
|
228
|
+
`state row(s) remain (${remaining.join(", ")}) — the destroy session could ` +
|
|
229
|
+
`not see the stack's persisted state, so its cloud resources were NOT deleted`,
|
|
230
|
+
});
|
|
154
231
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
if (plan.selectedFqns !== undefined || !plan.output) {
|
|
235
|
+
return undefined;
|
|
236
|
+
}
|
|
237
|
+
const resolved = yield* Output.evaluate(plan.output, outputs);
|
|
238
|
+
// Persist the stack's evaluated outputs so cross-stack references
|
|
239
|
+
// (`yield* OtherStack` / `OtherStack.stage.<name>` / `Output.stackRef`)
|
|
240
|
+
// can read them back out of the state store.
|
|
241
|
+
yield* state.setOutput({ stack: stackName, stage, value: resolved });
|
|
242
|
+
return resolved;
|
|
162
243
|
}).pipe(ensureArtifactStore, Effect.withSpan("apply", {
|
|
163
244
|
attributes: {
|
|
164
245
|
"alchemy.resources.count": Object.keys(plan.resources).length,
|
|
@@ -171,20 +252,18 @@ export const apply = (plan, options = {}) => Effect.gen(function* () {
|
|
|
171
252
|
// available in `tracker`." Resources with `precreate` signal early so that
|
|
172
253
|
// downstream resources can resolve stable identifiers without deadlocking.
|
|
173
254
|
// The actual output lives in the mutable `tracker` map, not in the Deferred.
|
|
174
|
-
const executePlan = Effect.fn(function* (plan, tracker, outputs, terminalStatuses,
|
|
255
|
+
const executePlan = Effect.fn(function* (plan, tracker, outputs, terminalStatuses, reportEvent, state, stackName, stage) {
|
|
175
256
|
// Resources and tasks share the same FQN namespace and DAG, so the
|
|
176
257
|
// scheduler tracks them together. Each entry gets a single Deferred that
|
|
177
258
|
// signals "my output is available in `tracker`."
|
|
178
259
|
const allNodes = { ...plan.resources, ...plan.actions };
|
|
179
|
-
const ready = Object.fromEntries(yield* Effect.
|
|
260
|
+
const ready = Object.fromEntries(yield* Effect.forEach(Object.keys(allNodes), (fqn) => Effect.map(Deferred.make(), (d) => [fqn, d])));
|
|
180
261
|
// `readyStable` fires only when a node has reached its TERMINAL output —
|
|
181
262
|
// resources after `reconcile`, tasks after the body completes. Resource
|
|
182
263
|
// precreate stubs do NOT signal `readyStable`, so any consumer that
|
|
183
264
|
// requires stable inputs (e.g. Tasks) waits past the precreate phase.
|
|
184
|
-
const readyStable = Object.fromEntries(yield* Effect.
|
|
185
|
-
const waitForDeps = (downstreamFqn, fqns) => Effect.
|
|
186
|
-
.filter((fqn) => fqn in ready)
|
|
187
|
-
.map((fqn) =>
|
|
265
|
+
const readyStable = Object.fromEntries(yield* Effect.forEach(Object.keys(allNodes), (fqn) => Effect.map(Deferred.make(), (d) => [fqn, d])));
|
|
266
|
+
const waitForDeps = (downstreamFqn, fqns) => Effect.forEach(fqns.filter((fqn) => fqn in ready), (fqn) =>
|
|
188
267
|
// Non-cycle upstreams must be observed at their TERMINAL output
|
|
189
268
|
// (`readyStable`), not their early precreate signal (`ready`). This
|
|
190
269
|
// is what makes a failed upstream actually interrupt its downstream:
|
|
@@ -202,12 +281,12 @@ const executePlan = Effect.fn(function* (plan, tracker, outputs, terminalStatuse
|
|
|
202
281
|
// consumer cannot attach to a Worker's fetch-only precreate stub.
|
|
203
282
|
plan.cycleMembers.has(downstreamFqn) && plan.cycleMembers.has(fqn)
|
|
204
283
|
? Deferred.await(ready[fqn])
|
|
205
|
-
: Deferred.await(readyStable[fqn])
|
|
206
|
-
const waitForStableDeps = (fqns) => Effect.
|
|
284
|
+
: Deferred.await(readyStable[fqn]), { concurrency: "unbounded" });
|
|
285
|
+
const waitForStableDeps = (fqns) => Effect.forEach(fqns.filter((fqn) => fqn in readyStable), (fqn) => Deferred.await(readyStable[fqn]), { concurrency: "unbounded" });
|
|
207
286
|
const failures = [];
|
|
208
|
-
yield* Effect.
|
|
209
|
-
? executeActionNode(fqn, node, tracker, outputs, ready, readyStable, terminalStatuses,
|
|
210
|
-
: executeNode(fqn, node, tracker, outputs, ready, readyStable, terminalStatuses,
|
|
287
|
+
yield* Effect.forEach(Object.entries(allNodes), ([fqn, node]) => node.kind === "action"
|
|
288
|
+
? executeActionNode(fqn, node, tracker, outputs, ready, readyStable, terminalStatuses, reportEvent, state, stackName, stage, waitForStableDeps, failures)
|
|
289
|
+
: executeNode(fqn, node, tracker, outputs, ready, readyStable, terminalStatuses, reportEvent, state, stackName, stage, (fqns) => waitForDeps(fqn, fqns), failures, plan.cycleMembers), { concurrency: "unbounded" });
|
|
211
290
|
if (failures.length > 0) {
|
|
212
291
|
// Aggregate every collected lifecycle failure into a single parallel Cause
|
|
213
292
|
// so the apply ends with one combined error containing every distinct
|
|
@@ -237,13 +316,16 @@ const failureMessage = (cause) => {
|
|
|
237
316
|
: undefined;
|
|
238
317
|
const message = Predicate.hasProperty(error, "message") && typeof error.message === "string"
|
|
239
318
|
? error.message
|
|
240
|
-
:
|
|
319
|
+
: typeof error === "string"
|
|
320
|
+
? error
|
|
321
|
+
: Formatter.format(error);
|
|
241
322
|
const line = message.split("\n", 1)[0];
|
|
242
323
|
return tag !== undefined && !line.includes(tag) ? `${tag}: ${line}` : line;
|
|
243
324
|
}
|
|
244
325
|
return undefined;
|
|
245
326
|
};
|
|
246
|
-
const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalStatuses,
|
|
327
|
+
const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalStatuses, reportEvent, state, stackName, stage, waitForDeps, failures, cycleMembers) => Effect.gen(function* () {
|
|
328
|
+
const inCycle = cycleMembers.has(fqn);
|
|
247
329
|
const logicalId = node.resource.LogicalId;
|
|
248
330
|
const namespace = node.resource.Namespace;
|
|
249
331
|
const commit = (value) => state.set({
|
|
@@ -266,21 +348,13 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
266
348
|
value: {
|
|
267
349
|
...value,
|
|
268
350
|
adoptionBlocked: value.adoptionBlocked ?? node.adoptionBlocked,
|
|
351
|
+
propsIncomplete: propsIncomplete(value),
|
|
269
352
|
props: stripUnresolved(value.props),
|
|
270
353
|
bindings: stripUnresolved(value.bindings),
|
|
271
354
|
namespace,
|
|
272
355
|
},
|
|
273
356
|
});
|
|
274
|
-
const scopedSession =
|
|
275
|
-
...session,
|
|
276
|
-
note: (note, options) => session.emit({
|
|
277
|
-
fqn,
|
|
278
|
-
id: logicalId,
|
|
279
|
-
_tag: "apply.resource.note",
|
|
280
|
-
message: note,
|
|
281
|
-
kind: options?.kind,
|
|
282
|
-
}),
|
|
283
|
-
};
|
|
357
|
+
const scopedSession = resourceSession(reportEvent, fqn, logicalId);
|
|
284
358
|
// On a mode-switch replacement (local ⇄ live) surface the transition:
|
|
285
359
|
// the old generation's stamped mode → the mode resolved for this run.
|
|
286
360
|
const fromProviderMode = node.action === "replace" &&
|
|
@@ -289,11 +363,11 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
289
363
|
node.state.providerMode !== node.mode
|
|
290
364
|
? node.state.providerMode
|
|
291
365
|
: undefined;
|
|
292
|
-
const report = (status) =>
|
|
293
|
-
|
|
366
|
+
const report = (status) => reportEvent({
|
|
367
|
+
type: "apply.resource.status",
|
|
294
368
|
fqn,
|
|
295
369
|
id: logicalId,
|
|
296
|
-
|
|
370
|
+
resourceType: node.resource.Type,
|
|
297
371
|
status,
|
|
298
372
|
providerMode: node.mode,
|
|
299
373
|
fromProviderMode,
|
|
@@ -330,11 +404,11 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
330
404
|
// `terminalStatuses` after `converge` completes.
|
|
331
405
|
if (inCycle)
|
|
332
406
|
return;
|
|
333
|
-
yield*
|
|
334
|
-
|
|
407
|
+
yield* reportEvent({
|
|
408
|
+
type: "apply.resource.status",
|
|
335
409
|
fqn,
|
|
336
410
|
id: logicalId,
|
|
337
|
-
|
|
411
|
+
resourceType: node.resource.Type,
|
|
338
412
|
status,
|
|
339
413
|
providerMode: node.mode,
|
|
340
414
|
});
|
|
@@ -400,6 +474,17 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
400
474
|
const bindingDeps = Object.keys(Output.resolveUpstream(node.bindings));
|
|
401
475
|
return [...new Set([...propDeps, ...bindingDeps])];
|
|
402
476
|
};
|
|
477
|
+
// A cycle precreates before its peers reconcile. An upstream outside the
|
|
478
|
+
// cycle cannot depend on it, so wait for those upstreams and resolve the
|
|
479
|
+
// props they determine: only values derived from cycle peers stay
|
|
480
|
+
// unresolved when precreate and `observe` run.
|
|
481
|
+
const resolvePrecreateProps = Effect.gen(function* () {
|
|
482
|
+
const outside = allUpstreamFqns().filter((upstream) => !cycleMembers.has(upstream));
|
|
483
|
+
yield* waitForDeps(outside);
|
|
484
|
+
return yield* Output.evaluateAvailable(node.props, Object.fromEntries(outside
|
|
485
|
+
.filter((upstream) => Object.hasOwn(outputs, upstream))
|
|
486
|
+
.map((upstream) => [upstream, outputs[upstream]])));
|
|
487
|
+
});
|
|
403
488
|
// ── instance ID ──
|
|
404
489
|
const resolveInstanceId = Effect.gen(function* () {
|
|
405
490
|
if (node.action === "create" && !node.state?.instanceId) {
|
|
@@ -475,6 +560,8 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
475
560
|
});
|
|
476
561
|
}
|
|
477
562
|
let attr = node.state?.attr;
|
|
563
|
+
// Whether the identity reconcile claims has passed the ownership check.
|
|
564
|
+
let admitted = node.deferredAdoption === undefined;
|
|
478
565
|
if (attr !== undefined) {
|
|
479
566
|
// Precreate/read may already have produced a usable output snapshot. Publish
|
|
480
567
|
// it early so downstream resources can start resolving against it.
|
|
@@ -486,6 +573,10 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
486
573
|
// Durable Object classes are empty) can serve traffic while the real
|
|
487
574
|
// version propagates.
|
|
488
575
|
if (inCycle && node.provider.precreate && attr === undefined) {
|
|
576
|
+
const props = yield* resolvePrecreateProps;
|
|
577
|
+
// Without `observe`, precreate and reconcile claim the identity unchecked.
|
|
578
|
+
admitted =
|
|
579
|
+
(yield* observeBeforePrecreate(node, props, fqn, logicalId, instanceId)) !== "unresolved";
|
|
489
580
|
// Some resources need a placeholder physical resource before their real
|
|
490
581
|
// create can finish. Persist that stub so downstream evaluation can proceed.
|
|
491
582
|
yield* report("pre-creating");
|
|
@@ -493,7 +584,7 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
493
584
|
.precreate({
|
|
494
585
|
id: logicalId,
|
|
495
586
|
fqn,
|
|
496
|
-
news:
|
|
587
|
+
news: props,
|
|
497
588
|
session: scopedSession,
|
|
498
589
|
instanceId,
|
|
499
590
|
bindings: excludeDeletedBindings(node.bindings),
|
|
@@ -506,7 +597,9 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
506
597
|
instanceId,
|
|
507
598
|
resourceType: node.resource.Type,
|
|
508
599
|
props: node.props,
|
|
509
|
-
|
|
600
|
+
// A stub for an unresolved identity claims nothing. Leave the
|
|
601
|
+
// checkpoint without it, so a retry checks the identity again.
|
|
602
|
+
attr: admitted ? attr : undefined,
|
|
510
603
|
providerVersion: node.provider.version ?? 0,
|
|
511
604
|
bindings: excludeDeletedBindings(node.bindings),
|
|
512
605
|
downstream: node.downstream,
|
|
@@ -526,8 +619,8 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
526
619
|
yield* report("creating");
|
|
527
620
|
const news = (yield* Output.evaluate(node.props, outputs));
|
|
528
621
|
const bindingOutputs = excludeDeletedBindings(yield* Output.evaluate(node.bindings, outputs));
|
|
529
|
-
if (
|
|
530
|
-
const checkpoint = () => commit({
|
|
622
|
+
if (!admitted) {
|
|
623
|
+
const checkpoint = (attr) => commit({
|
|
531
624
|
status: "creating",
|
|
532
625
|
fqn,
|
|
533
626
|
logicalId,
|
|
@@ -542,13 +635,12 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
542
635
|
providerMode: node.mode,
|
|
543
636
|
adoptionBlocked: node.adoptionBlocked,
|
|
544
637
|
});
|
|
545
|
-
// Refusal or interruption must retain identity, never foreign
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
.pipe(instrumentLifecycle("read", fqn, node.resource.Type, logicalId, instanceId));
|
|
638
|
+
// Refusal or interruption must retain identity, never foreign
|
|
639
|
+
// attributes, nor a stub for an identity not yet checked.
|
|
640
|
+
yield* checkpoint(undefined);
|
|
641
|
+
const observed = yield* observeResolved(node, news, fqn, logicalId, instanceId);
|
|
550
642
|
if (observed !== undefined) {
|
|
551
|
-
if (Unowned.is(observed) && !node.deferredAdoption
|
|
643
|
+
if (Unowned.is(observed) && !node.deferredAdoption?.adopt) {
|
|
552
644
|
return yield* new OwnedBySomeoneElse({
|
|
553
645
|
message: `Cannot adopt resource '${fqn}' (${node.resource.Type}): ` +
|
|
554
646
|
"it exists in the cloud but is not owned by this " +
|
|
@@ -558,9 +650,10 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
558
650
|
logicalId,
|
|
559
651
|
});
|
|
560
652
|
}
|
|
561
|
-
|
|
653
|
+
// Reconcile keeps a precreated stub as its output.
|
|
654
|
+
attr ??= stripUnowned(observed);
|
|
562
655
|
// A creating checkpoint retains olds: undefined on retry.
|
|
563
|
-
yield* checkpoint();
|
|
656
|
+
yield* checkpoint(attr);
|
|
564
657
|
}
|
|
565
658
|
}
|
|
566
659
|
attr = yield* node.provider
|
|
@@ -824,11 +917,76 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
824
917
|
yield* deleteOldGenerations(old.old);
|
|
825
918
|
}
|
|
826
919
|
});
|
|
827
|
-
|
|
920
|
+
const deleteFirst = Effect.fn(function* () {
|
|
828
921
|
yield* scopedSession.note("Deleting previous resource before creating its replacement (deleteFirst)...");
|
|
829
922
|
yield* deleteOldGenerations(replState.old);
|
|
830
|
-
}
|
|
923
|
+
});
|
|
831
924
|
let attr = replState.attr;
|
|
925
|
+
// ── replacement admission ──
|
|
926
|
+
//
|
|
927
|
+
// The replacement may resolve to a physical identity that already
|
|
928
|
+
// exists and belongs to someone else (e.g. a renamed Worker pointing at
|
|
929
|
+
// a foreign script). Read it before anything is mutated — before
|
|
930
|
+
// precreate, reconcile, and delete-first cleanup of the previous
|
|
931
|
+
// generation — and refuse an unowned target unless adoption is allowed,
|
|
932
|
+
// exactly like a fresh create.
|
|
933
|
+
let admitted = attr !== undefined || node.deferredAdoption === undefined;
|
|
934
|
+
const admit = Effect.fn(function* (props) {
|
|
935
|
+
admitted = true;
|
|
936
|
+
const observed = yield* observeResolved(node, props, fqn, logicalId, instanceId, replState.old?.attr);
|
|
937
|
+
if (observed === undefined)
|
|
938
|
+
return;
|
|
939
|
+
if (Unowned.is(observed) && !node.deferredAdoption?.adopt) {
|
|
940
|
+
return yield* new OwnedBySomeoneElse({
|
|
941
|
+
message: `Cannot replace resource '${fqn}' (${node.resource.Type}): ` +
|
|
942
|
+
"its replacement exists in the cloud but is not owned by this " +
|
|
943
|
+
"stack/stage/logical-id. Re-run with `--adopt` (or " +
|
|
944
|
+
"wrap the effect in `adopt(true)`) to take it over.",
|
|
945
|
+
resourceType: node.resource.Type,
|
|
946
|
+
logicalId,
|
|
947
|
+
});
|
|
948
|
+
}
|
|
949
|
+
// A delete-first target may be the previous generation itself, which
|
|
950
|
+
// is about to be deleted — never hand its attributes to reconcile.
|
|
951
|
+
// Reconcile keeps a precreated stub as its output.
|
|
952
|
+
if (!node.deleteFirst)
|
|
953
|
+
attr ??= stripUnowned(observed);
|
|
954
|
+
});
|
|
955
|
+
// A cycle precreates on the props its upstreams outside the cycle
|
|
956
|
+
// determine; anything else waits for every upstream.
|
|
957
|
+
const precreateProps = inCycle ? yield* resolvePrecreateProps : node.props;
|
|
958
|
+
if (!admitted && isResolved(precreateProps)) {
|
|
959
|
+
yield* admit(precreateProps);
|
|
960
|
+
}
|
|
961
|
+
// A cycle precreates before its props resolve, so `observe` admits the
|
|
962
|
+
// identity precreate will claim — before delete-first, too. Without
|
|
963
|
+
// `observe`, precreate and reconcile claim it unchecked. An unresolved
|
|
964
|
+
// identity is admitted once it resolves, before reconcile.
|
|
965
|
+
if (!admitted && inCycle) {
|
|
966
|
+
const observation = yield* observeBeforePrecreate(node, precreateProps, fqn, logicalId, instanceId, replState.old?.attr);
|
|
967
|
+
admitted = observation !== "unresolved";
|
|
968
|
+
if (!admitted && node.deleteFirst && !node.deferredAdoption?.adopt) {
|
|
969
|
+
return yield* new UnverifiableReplacement({
|
|
970
|
+
message: `Cannot replace resource '${fqn}' (${node.resource.Type}): ` +
|
|
971
|
+
"it must be deleted before its replacement is pre-created, but " +
|
|
972
|
+
"the replacement's identity depends on outputs that are not " +
|
|
973
|
+
"resolved yet, so its ownership cannot be checked first. Re-run " +
|
|
974
|
+
"with `--adopt` (or wrap the effect in `adopt(true)`) to replace it anyway.",
|
|
975
|
+
resourceType: node.resource.Type,
|
|
976
|
+
logicalId,
|
|
977
|
+
});
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
// A cycle must delete before precreate claims the identity. Plan has
|
|
981
|
+
// already refused one whose identity could not be admitted first
|
|
982
|
+
// without `observe`; the check above refuses an unresolved one.
|
|
983
|
+
// Otherwise the previous generation survives until reconcile is
|
|
984
|
+
// about to run, so a failed upstream never leaves the resource missing.
|
|
985
|
+
let deletedFirst = false;
|
|
986
|
+
if (node.deleteFirst && inCycle) {
|
|
987
|
+
yield* deleteFirst();
|
|
988
|
+
deletedFirst = true;
|
|
989
|
+
}
|
|
832
990
|
if (attr !== undefined) {
|
|
833
991
|
// If precreate already ran, expose that intermediate output immediately so
|
|
834
992
|
// downstream resources can resolve against the same in-flight replacement.
|
|
@@ -840,7 +998,7 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
840
998
|
.precreate({
|
|
841
999
|
id: logicalId,
|
|
842
1000
|
fqn,
|
|
843
|
-
news:
|
|
1001
|
+
news: precreateProps,
|
|
844
1002
|
session: scopedSession,
|
|
845
1003
|
instanceId,
|
|
846
1004
|
bindings: excludeDeletedBindings(node.bindings),
|
|
@@ -853,7 +1011,9 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
853
1011
|
instanceId,
|
|
854
1012
|
resourceType: node.resource.Type,
|
|
855
1013
|
props: node.props,
|
|
856
|
-
|
|
1014
|
+
// A stub for an unresolved identity claims nothing. Leave the
|
|
1015
|
+
// checkpoint without it, so a retry checks the identity again.
|
|
1016
|
+
attr: admitted ? attr : undefined,
|
|
857
1017
|
providerVersion: node.provider.version ?? 0,
|
|
858
1018
|
bindings: excludeDeletedBindings(node.bindings),
|
|
859
1019
|
downstream: node.downstream,
|
|
@@ -873,6 +1033,12 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
873
1033
|
yield* report("creating replacement");
|
|
874
1034
|
const news = (yield* Output.evaluate(node.props, outputs));
|
|
875
1035
|
const bindingOutputs = excludeDeletedBindings(yield* Output.evaluate(node.bindings, outputs));
|
|
1036
|
+
if (!admitted) {
|
|
1037
|
+
yield* admit(news);
|
|
1038
|
+
}
|
|
1039
|
+
if (node.deleteFirst && !deletedFirst) {
|
|
1040
|
+
yield* deleteFirst();
|
|
1041
|
+
}
|
|
876
1042
|
attr = yield* node.provider
|
|
877
1043
|
.reconcile({
|
|
878
1044
|
id: logicalId,
|
|
@@ -945,18 +1111,18 @@ const executeNode = (fqn, node, tracker, outputs, ready, readyStable, terminalSt
|
|
|
945
1111
|
}).pipe(Effect.catchCause((cause) =>
|
|
946
1112
|
// Record the failure, propagate it to any downstream resources waiting on
|
|
947
1113
|
// our Deferred (so their waitForDeps short-circuits instead of deadlocking),
|
|
948
|
-
// emit a "fail" status
|
|
1114
|
+
// emit a "fail" status, and resolve to void so Effect.all
|
|
949
1115
|
// does not interrupt sibling fibers. The aggregated cause is raised at
|
|
950
1116
|
// the end of executePlan.
|
|
951
1117
|
Effect.gen(function* () {
|
|
952
1118
|
failures.push({ fqn, logicalId: node.resource.LogicalId, type: node.resource.Type, cause });
|
|
953
1119
|
yield* Deferred.failCause(ready[fqn], cause);
|
|
954
1120
|
yield* Deferred.failCause(readyStable[fqn], cause);
|
|
955
|
-
yield*
|
|
956
|
-
|
|
1121
|
+
yield* reportEvent({
|
|
1122
|
+
type: "apply.resource.status",
|
|
957
1123
|
fqn,
|
|
958
1124
|
id: node.resource.LogicalId,
|
|
959
|
-
|
|
1125
|
+
resourceType: node.resource.Type,
|
|
960
1126
|
status: "fail",
|
|
961
1127
|
message: failureMessage(cause),
|
|
962
1128
|
providerMode: node.mode,
|
|
@@ -989,12 +1155,18 @@ const runAction = Effect.fn("apply.runAction")(function* (task, input, outputs)
|
|
|
989
1155
|
.Run(input)
|
|
990
1156
|
.pipe(Effect.provideService(RuntimeContext, makeResolveContext(resolved)));
|
|
991
1157
|
});
|
|
992
|
-
const executeActionNode = (fqn, node, tracker, outputs, ready, readyStable, terminalStatuses,
|
|
1158
|
+
const executeActionNode = (fqn, node, tracker, outputs, ready, readyStable, terminalStatuses, reportEvent, state, stackName, stage, waitForDeps, failures) => Effect.gen(function* () {
|
|
993
1159
|
const task = node.def;
|
|
994
1160
|
const logicalId = task.LogicalId;
|
|
995
1161
|
const namespace = task.Namespace;
|
|
996
1162
|
const commit = (value) => state.set({ stack: stackName, stage, fqn, value: { ...value, namespace } });
|
|
997
|
-
const report = (status) =>
|
|
1163
|
+
const report = (status) => reportEvent({
|
|
1164
|
+
type: "apply.resource.status",
|
|
1165
|
+
fqn,
|
|
1166
|
+
id: logicalId,
|
|
1167
|
+
resourceType: task.Type,
|
|
1168
|
+
status,
|
|
1169
|
+
});
|
|
998
1170
|
const signalReady = Deferred.succeed(ready[fqn], void 0);
|
|
999
1171
|
const signalReadyStable = Deferred.succeed(readyStable[fqn], void 0);
|
|
1000
1172
|
const skip = (state) => Effect.gen(function* () {
|
|
@@ -1070,11 +1242,11 @@ const executeActionNode = (fqn, node, tracker, outputs, ready, readyStable, term
|
|
|
1070
1242
|
failures.push({ fqn, logicalId: node.def.LogicalId, type: node.def.Type, cause });
|
|
1071
1243
|
yield* Deferred.failCause(ready[fqn], cause);
|
|
1072
1244
|
yield* Deferred.failCause(readyStable[fqn], cause);
|
|
1073
|
-
yield*
|
|
1074
|
-
|
|
1245
|
+
yield* reportEvent({
|
|
1246
|
+
type: "apply.resource.status",
|
|
1075
1247
|
fqn,
|
|
1076
1248
|
id: node.def.LogicalId,
|
|
1077
|
-
|
|
1249
|
+
resourceType: node.def.Type,
|
|
1078
1250
|
status: "fail",
|
|
1079
1251
|
message: failureMessage(cause),
|
|
1080
1252
|
});
|
|
@@ -1094,7 +1266,7 @@ const executeActionNode = (fqn, node, tracker, outputs, ready, readyStable, term
|
|
|
1094
1266
|
// against the current tracker outputs. Call provider.reconcile for any
|
|
1095
1267
|
// resource whose resolved inputs differ from what it was last applied with.
|
|
1096
1268
|
// Repeat until no resource needs updating.
|
|
1097
|
-
const converge = Effect.fn(function* (plan, tracker, outputs, terminalStatuses,
|
|
1269
|
+
const converge = Effect.fn(function* (plan, tracker, outputs, terminalStatuses, reportEvent, state, stackName, stage) {
|
|
1098
1270
|
for (;;) {
|
|
1099
1271
|
let anyUpdated = false;
|
|
1100
1272
|
for (const [fqn, node] of Object.entries(plan.resources)) {
|
|
@@ -1114,16 +1286,24 @@ const converge = Effect.fn(function* (plan, tracker, outputs, terminalStatuses,
|
|
|
1114
1286
|
const logicalId = node.resource.LogicalId;
|
|
1115
1287
|
const namespace = node.resource.Namespace;
|
|
1116
1288
|
const instanceId = tracker[fqn].instanceId;
|
|
1117
|
-
const scopedSession =
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1289
|
+
const scopedSession = resourceSession(reportEvent, fqn, logicalId);
|
|
1290
|
+
// A cycle peer resolves against its peers' first outputs, so an
|
|
1291
|
+
// identity checked then may resolve differently now. Check the identity
|
|
1292
|
+
// these props resolve to before reconcile claims it.
|
|
1293
|
+
const deferredAdoption = "deferredAdoption" in node ? node.deferredAdoption : undefined;
|
|
1294
|
+
if (propsChanged && deferredAdoption !== undefined) {
|
|
1295
|
+
const observed = yield* observeResolved(node, newProps, fqn, logicalId, instanceId, tracker[fqn].output);
|
|
1296
|
+
if (observed !== undefined && Unowned.is(observed) && !deferredAdoption.adopt) {
|
|
1297
|
+
return yield* new OwnedBySomeoneElse({
|
|
1298
|
+
message: `Cannot converge resource '${fqn}' (${node.resource.Type}): ` +
|
|
1299
|
+
"its final identity exists in the cloud but is not owned by this " +
|
|
1300
|
+
"stack/stage/logical-id. Re-run with `--adopt` (or " +
|
|
1301
|
+
"wrap the effect in `adopt(true)`) to take it over.",
|
|
1302
|
+
resourceType: node.resource.Type,
|
|
1303
|
+
logicalId,
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1127
1307
|
const attr = yield* node.provider
|
|
1128
1308
|
.reconcile({
|
|
1129
1309
|
id: logicalId,
|
|
@@ -1264,7 +1444,7 @@ export class DestroyError extends Data.TaggedError("DestroyError") {
|
|
|
1264
1444
|
].join("\n");
|
|
1265
1445
|
}
|
|
1266
1446
|
}
|
|
1267
|
-
const collectGarbage = Effect.fn(function* (plan,
|
|
1447
|
+
const collectGarbage = Effect.fn(function* (plan, reportEvent) {
|
|
1268
1448
|
const state = yield* yield* State;
|
|
1269
1449
|
const stack = yield* Stack;
|
|
1270
1450
|
const stackName = stack.name;
|
|
@@ -1272,25 +1452,25 @@ const collectGarbage = Effect.fn(function* (plan, session) {
|
|
|
1272
1452
|
// Task deletions are pure state drops — no body is invoked. Run them in
|
|
1273
1453
|
// parallel before resource GC; tasks never have provider-side dependencies
|
|
1274
1454
|
// to wait on.
|
|
1275
|
-
yield* Effect.
|
|
1455
|
+
yield* Effect.forEach(Object.entries(plan.actionDeletions ?? {}), ([fqn, node]) => node === undefined
|
|
1276
1456
|
? Effect.void
|
|
1277
1457
|
: Effect.gen(function* () {
|
|
1278
|
-
yield*
|
|
1279
|
-
|
|
1458
|
+
yield* reportEvent({
|
|
1459
|
+
type: "apply.resource.status",
|
|
1280
1460
|
fqn,
|
|
1281
1461
|
id: node.def.LogicalId,
|
|
1282
|
-
|
|
1462
|
+
resourceType: node.def.Type,
|
|
1283
1463
|
status: "deleting",
|
|
1284
1464
|
});
|
|
1285
1465
|
yield* state.delete({ stack: stackName, stage, fqn });
|
|
1286
|
-
yield*
|
|
1287
|
-
|
|
1466
|
+
yield* reportEvent({
|
|
1467
|
+
type: "apply.resource.status",
|
|
1288
1468
|
fqn,
|
|
1289
1469
|
id: node.def.LogicalId,
|
|
1290
|
-
|
|
1470
|
+
resourceType: node.def.Type,
|
|
1291
1471
|
status: "deleted",
|
|
1292
1472
|
});
|
|
1293
|
-
})
|
|
1473
|
+
}), { concurrency: "unbounded" });
|
|
1294
1474
|
// Failures are collected — not propagated — so one bad delete never
|
|
1295
1475
|
// strands unrelated siblings. `unresolved` tracks every FQN whose delete
|
|
1296
1476
|
// failed or was blocked this run: later passes must not retry them (a
|
|
@@ -1356,6 +1536,9 @@ const collectGarbage = Effect.fn(function* (plan, session) {
|
|
|
1356
1536
|
const adoptionBlocked = isDeleteNode(node)
|
|
1357
1537
|
? node.state.adoptionBlocked
|
|
1358
1538
|
: generation.adoptionBlocked;
|
|
1539
|
+
const incompleteProps = isDeleteNode(node)
|
|
1540
|
+
? node.state.propsIncomplete
|
|
1541
|
+
: generation.propsIncomplete;
|
|
1359
1542
|
// Mutable: an attr-less row (interrupted create) may recover its
|
|
1360
1543
|
// attributes from `provider.read` below, right before deletion.
|
|
1361
1544
|
let attr = persistedAttr;
|
|
@@ -1375,31 +1558,22 @@ const collectGarbage = Effect.fn(function* (plan, session) {
|
|
|
1375
1558
|
namespace,
|
|
1376
1559
|
},
|
|
1377
1560
|
});
|
|
1378
|
-
const report = (status) =>
|
|
1379
|
-
|
|
1561
|
+
const report = (status) => reportEvent({
|
|
1562
|
+
type: "apply.resource.status",
|
|
1380
1563
|
fqn,
|
|
1381
1564
|
id: logicalId,
|
|
1382
|
-
|
|
1565
|
+
resourceType,
|
|
1383
1566
|
status,
|
|
1384
1567
|
providerMode,
|
|
1385
1568
|
});
|
|
1386
|
-
const scopedSession =
|
|
1387
|
-
...session,
|
|
1388
|
-
note: (note, options) => session.emit({
|
|
1389
|
-
fqn,
|
|
1390
|
-
id: logicalId,
|
|
1391
|
-
_tag: "apply.resource.note",
|
|
1392
|
-
message: note,
|
|
1393
|
-
kind: options?.kind,
|
|
1394
|
-
}),
|
|
1395
|
-
};
|
|
1569
|
+
const scopedSession = resourceSession(reportEvent, fqn, logicalId);
|
|
1396
1570
|
return yield* (deletions[fqn] ??= yield* Effect.cached(Effect.gen(function* () {
|
|
1397
1571
|
// Dependents (`downstream`) are deleted before this resource. A
|
|
1398
1572
|
// dependent whose delete failed (or was itself blocked) may make
|
|
1399
1573
|
// this resource legitimately undeletable (dependency violation),
|
|
1400
1574
|
// so it is skipped with a "blocked by" note instead of surfacing
|
|
1401
1575
|
// a spurious second error.
|
|
1402
|
-
const dependents = yield* Effect.
|
|
1576
|
+
const dependents = yield* Effect.forEach(downstream, (dep) => dep !== fqn && !ancestors.has(dep)
|
|
1403
1577
|
? dep in deletionGraph
|
|
1404
1578
|
? deleteResource(deletionGraph[dep], nextAncestors).pipe(Effect.map((outcome) => ({ dep, outcome })))
|
|
1405
1579
|
: // Not in this pass's graph — but it may have failed in
|
|
@@ -1408,7 +1582,7 @@ const collectGarbage = Effect.fn(function* (plan, session) {
|
|
|
1408
1582
|
dep,
|
|
1409
1583
|
outcome: unresolved.has(dep) ? "failed" : "deleted",
|
|
1410
1584
|
}))
|
|
1411
|
-
: Effect.succeed({ dep, outcome: "deleted" })
|
|
1585
|
+
: Effect.succeed({ dep, outcome: "deleted" }), { concurrency: "unbounded" });
|
|
1412
1586
|
const blockedBy = dependents
|
|
1413
1587
|
.filter(({ outcome }) => outcome === "failed" || outcome === "blocked")
|
|
1414
1588
|
.map(({ dep }) => dep);
|
|
@@ -1470,6 +1644,12 @@ const collectGarbage = Effect.fn(function* (plan, session) {
|
|
|
1470
1644
|
"migrated predecessor. Any interrupted new physical " +
|
|
1471
1645
|
"resource must be identified and cleaned up manually.");
|
|
1472
1646
|
}
|
|
1647
|
+
else if (incompleteProps) {
|
|
1648
|
+
yield* scopedSession.note("Skipping recovery: unresolved properties were omitted from " +
|
|
1649
|
+
"this interrupted create's state, so they cannot identify it. " +
|
|
1650
|
+
"Any interrupted physical resource must be identified and " +
|
|
1651
|
+
"cleaned up manually.");
|
|
1652
|
+
}
|
|
1473
1653
|
else if (provider.read) {
|
|
1474
1654
|
const recovered = yield* provider
|
|
1475
1655
|
.read({ id: logicalId, fqn, instanceId, olds: props, output: undefined })
|
|
@@ -1522,6 +1702,7 @@ const collectGarbage = Effect.fn(function* (plan, session) {
|
|
|
1522
1702
|
removalPolicy: node.resource.RemovalPolicy,
|
|
1523
1703
|
providerMode,
|
|
1524
1704
|
adoptionBlocked,
|
|
1705
|
+
propsIncomplete: incompleteProps,
|
|
1525
1706
|
});
|
|
1526
1707
|
}
|
|
1527
1708
|
if (attr !== undefined && !retainOldGeneration) {
|
|
@@ -1583,6 +1764,7 @@ const collectGarbage = Effect.fn(function* (plan, session) {
|
|
|
1583
1764
|
bindings: excludeDeletedBindings(node.bindings),
|
|
1584
1765
|
removalPolicy: node.removalPolicy,
|
|
1585
1766
|
providerMode: node.providerMode,
|
|
1767
|
+
propsIncomplete: node.propsIncomplete,
|
|
1586
1768
|
});
|
|
1587
1769
|
}
|
|
1588
1770
|
yield* scopedSession.note(retainOldGeneration
|
|
@@ -1605,9 +1787,7 @@ const collectGarbage = Effect.fn(function* (plan, session) {
|
|
|
1605
1787
|
// retained) inside each node's delete effect — the effects resolve to
|
|
1606
1788
|
// outcomes and never fail, so one bad resource never interrupts sibling
|
|
1607
1789
|
// deletions mid-flight.
|
|
1608
|
-
yield* Effect.
|
|
1609
|
-
.filter((node) => node !== undefined)
|
|
1610
|
-
.map((node) => deleteResource(node)), { concurrency: "unbounded" });
|
|
1790
|
+
yield* Effect.forEach(Object.values(deletionGraph).filter((node) => node !== undefined), (node) => deleteResource(node), { concurrency: "unbounded" });
|
|
1611
1791
|
});
|
|
1612
1792
|
// Drain one old generation per FQN per pass, preserving that generation's
|
|
1613
1793
|
// dependency edges. Planned deletions remain queued until their chains drain.
|