alchemy-effect 0.2.0 → 0.4.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/bin/alchemy-effect.js +55354 -8
- package/bin/alchemy-effect.js.map +1 -1
- package/bin/alchemy-effect.ts +266 -10
- package/lib/$.d.ts +5 -0
- package/lib/$.d.ts.map +1 -0
- package/lib/$.js +9 -0
- package/lib/$.js.map +1 -0
- package/lib/app.d.ts +4 -17
- package/lib/app.d.ts.map +1 -1
- package/lib/app.js +0 -20
- package/lib/app.js.map +1 -1
- package/lib/apply.d.ts +15 -75
- package/lib/apply.d.ts.map +1 -1
- package/lib/apply.js +439 -154
- package/lib/apply.js.map +1 -1
- package/lib/assert-never.d.ts +12 -0
- package/lib/assert-never.d.ts.map +1 -0
- package/lib/assert-never.js +11 -0
- package/lib/assert-never.js.map +1 -0
- package/lib/aws/account.d.ts +10 -1
- package/lib/aws/account.d.ts.map +1 -1
- package/lib/aws/account.js +18 -3
- package/lib/aws/account.js.map +1 -1
- package/lib/aws/client.d.ts.map +1 -1
- package/lib/aws/client.js +0 -1
- package/lib/aws/client.js.map +1 -1
- package/lib/aws/config.d.ts +15 -0
- package/lib/aws/config.d.ts.map +1 -0
- package/lib/aws/config.js +1 -0
- package/lib/aws/config.js.map +1 -0
- package/lib/aws/credentials.d.ts +10 -0
- package/lib/aws/credentials.d.ts.map +1 -1
- package/lib/aws/credentials.js +73 -47
- package/lib/aws/credentials.js.map +1 -1
- package/lib/aws/dynamodb/client.d.ts +1 -1
- package/lib/aws/dynamodb/client.d.ts.map +1 -1
- package/lib/aws/dynamodb/index.d.ts +2 -1
- package/lib/aws/dynamodb/index.d.ts.map +1 -1
- package/lib/aws/dynamodb/index.js +1 -2
- package/lib/aws/dynamodb/index.js.map +1 -1
- package/lib/aws/dynamodb/secondary-index.d.ts +5 -4
- package/lib/aws/dynamodb/secondary-index.d.ts.map +1 -1
- package/lib/aws/dynamodb/table.d.ts +23 -20
- package/lib/aws/dynamodb/table.d.ts.map +1 -1
- package/lib/aws/dynamodb/table.get-item.d.ts +8 -6
- package/lib/aws/dynamodb/table.get-item.d.ts.map +1 -1
- package/lib/aws/dynamodb/table.get-item.js +4 -2
- package/lib/aws/dynamodb/table.get-item.js.map +1 -1
- package/lib/aws/dynamodb/table.js.map +1 -1
- package/lib/aws/dynamodb/table.provider.d.ts +3 -4
- package/lib/aws/dynamodb/table.provider.d.ts.map +1 -1
- package/lib/aws/dynamodb/table.provider.js +18 -29
- package/lib/aws/dynamodb/table.provider.js.map +1 -1
- package/lib/aws/ec2/client.d.ts +1 -1
- package/lib/aws/ec2/client.d.ts.map +1 -1
- package/lib/aws/ec2/index.d.ts +11 -0
- package/lib/aws/ec2/index.d.ts.map +1 -1
- package/lib/aws/ec2/index.js +11 -0
- package/lib/aws/ec2/index.js.map +1 -1
- package/lib/aws/ec2/internet-gateway.d.ts +65 -0
- package/lib/aws/ec2/internet-gateway.d.ts.map +1 -0
- package/lib/aws/ec2/internet-gateway.js +4 -0
- package/lib/aws/ec2/internet-gateway.js.map +1 -0
- package/lib/aws/ec2/internet-gateway.provider.d.ts +6 -0
- package/lib/aws/ec2/internet-gateway.provider.d.ts.map +1 -0
- package/lib/aws/ec2/internet-gateway.provider.js +193 -0
- package/lib/aws/ec2/internet-gateway.provider.js.map +1 -0
- package/lib/aws/ec2/route-table-association.d.ts +63 -0
- package/lib/aws/ec2/route-table-association.d.ts.map +1 -0
- package/lib/aws/ec2/route-table-association.js +4 -0
- package/lib/aws/ec2/route-table-association.js.map +1 -0
- package/lib/aws/ec2/route-table-association.provider.d.ts +4 -0
- package/lib/aws/ec2/route-table-association.provider.d.ts.map +1 -0
- package/lib/aws/ec2/route-table-association.provider.js +121 -0
- package/lib/aws/ec2/route-table-association.provider.js.map +1 -0
- package/lib/aws/ec2/route-table.d.ts +159 -0
- package/lib/aws/ec2/route-table.d.ts.map +1 -0
- package/lib/aws/ec2/route-table.js +4 -0
- package/lib/aws/ec2/route-table.js.map +1 -0
- package/lib/aws/ec2/route-table.provider.d.ts +6 -0
- package/lib/aws/ec2/route-table.provider.d.ts.map +1 -0
- package/lib/aws/ec2/route-table.provider.js +213 -0
- package/lib/aws/ec2/route-table.provider.js.map +1 -0
- package/lib/aws/ec2/route.d.ts +155 -0
- package/lib/aws/ec2/route.d.ts.map +1 -0
- package/lib/aws/ec2/route.js +3 -0
- package/lib/aws/ec2/route.js.map +1 -0
- package/lib/aws/ec2/route.provider.d.ts +4 -0
- package/lib/aws/ec2/route.provider.d.ts.map +1 -0
- package/lib/aws/ec2/route.provider.js +166 -0
- package/lib/aws/ec2/route.provider.js.map +1 -0
- package/lib/aws/ec2/subnet.d.ts +175 -0
- package/lib/aws/ec2/subnet.d.ts.map +1 -0
- package/lib/aws/ec2/subnet.js +4 -0
- package/lib/aws/ec2/subnet.js.map +1 -0
- package/lib/aws/ec2/subnet.provider.d.ts +4 -0
- package/lib/aws/ec2/subnet.provider.d.ts.map +1 -0
- package/lib/aws/ec2/subnet.provider.js +250 -0
- package/lib/aws/ec2/subnet.provider.js.map +1 -0
- package/lib/aws/ec2/vpc.d.ts +13 -8
- package/lib/aws/ec2/vpc.d.ts.map +1 -1
- package/lib/aws/ec2/vpc.js +1 -0
- package/lib/aws/ec2/vpc.js.map +1 -1
- package/lib/aws/ec2/vpc.provider.d.ts +1 -2
- package/lib/aws/ec2/vpc.provider.d.ts.map +1 -1
- package/lib/aws/ec2/vpc.provider.js +45 -37
- package/lib/aws/ec2/vpc.provider.js.map +1 -1
- package/lib/aws/index.d.ts +15 -19
- package/lib/aws/index.d.ts.map +1 -1
- package/lib/aws/index.js +8 -10
- package/lib/aws/index.js.map +1 -1
- package/lib/aws/lambda/consume.d.ts +10 -11
- package/lib/aws/lambda/consume.d.ts.map +1 -1
- package/lib/aws/lambda/consume.js +3 -3
- package/lib/aws/lambda/consume.js.map +1 -1
- package/lib/aws/lambda/function.d.ts +7 -7
- package/lib/aws/lambda/function.d.ts.map +1 -1
- package/lib/aws/lambda/function.handler.d.ts +1 -1
- package/lib/aws/lambda/function.handler.d.ts.map +1 -1
- package/lib/aws/lambda/function.handler.js.map +1 -1
- package/lib/aws/lambda/function.invoke.d.ts +6 -4
- package/lib/aws/lambda/function.invoke.d.ts.map +1 -1
- package/lib/aws/lambda/function.invoke.js +3 -1
- package/lib/aws/lambda/function.invoke.js.map +1 -1
- package/lib/aws/lambda/function.js +1 -1
- package/lib/aws/lambda/function.js.map +1 -1
- package/lib/aws/lambda/function.provider.d.ts +3 -2
- package/lib/aws/lambda/function.provider.d.ts.map +1 -1
- package/lib/aws/lambda/function.provider.js +28 -25
- package/lib/aws/lambda/function.provider.js.map +1 -1
- package/lib/aws/lambda/index.d.ts +1 -0
- package/lib/aws/lambda/index.d.ts.map +1 -1
- package/lib/aws/lambda/index.js +1 -0
- package/lib/aws/lambda/index.js.map +1 -1
- package/lib/aws/lambda/serve.d.ts +2 -4
- package/lib/aws/lambda/serve.d.ts.map +1 -1
- package/lib/aws/profile.d.ts +2 -2
- package/lib/aws/profile.d.ts.map +1 -1
- package/lib/aws/profile.js +1 -1
- package/lib/aws/profile.js.map +1 -1
- package/lib/aws/region.d.ts +14 -2
- package/lib/aws/region.d.ts.map +1 -1
- package/lib/aws/region.js +26 -1
- package/lib/aws/region.js.map +1 -1
- package/lib/aws/sqs/client.d.ts +1 -1
- package/lib/aws/sqs/client.d.ts.map +1 -1
- package/lib/aws/sqs/index.d.ts +1 -0
- package/lib/aws/sqs/index.d.ts.map +1 -1
- package/lib/aws/sqs/index.js +1 -0
- package/lib/aws/sqs/index.js.map +1 -1
- package/lib/aws/sqs/queue.consume.d.ts +1 -1
- package/lib/aws/sqs/queue.consume.d.ts.map +1 -1
- package/lib/aws/sqs/queue.consume.js +0 -1
- package/lib/aws/sqs/queue.consume.js.map +1 -1
- package/lib/aws/sqs/queue.d.ts +6 -4
- package/lib/aws/sqs/queue.d.ts.map +1 -1
- package/lib/aws/sqs/queue.event-source.d.ts +8 -6
- package/lib/aws/sqs/queue.event-source.d.ts.map +1 -1
- package/lib/aws/sqs/queue.event-source.js +26 -44
- package/lib/aws/sqs/queue.event-source.js.map +1 -1
- package/lib/aws/sqs/queue.js +1 -1
- package/lib/aws/sqs/queue.js.map +1 -1
- package/lib/aws/sqs/queue.provider.d.ts +2 -2
- package/lib/aws/sqs/queue.provider.d.ts.map +1 -1
- package/lib/aws/sqs/queue.provider.js +2 -1
- package/lib/aws/sqs/queue.provider.js.map +1 -1
- package/lib/aws/sqs/queue.send-message.d.ts +7 -5
- package/lib/aws/sqs/queue.send-message.d.ts.map +1 -1
- package/lib/aws/sqs/queue.send-message.js +4 -2
- package/lib/aws/sqs/queue.send-message.js.map +1 -1
- package/lib/binding.d.ts +12 -12
- package/lib/binding.d.ts.map +1 -1
- package/lib/binding.js.map +1 -1
- package/lib/cli/components/ApprovePlan.d.ts +2 -2
- package/lib/cli/components/ApprovePlan.d.ts.map +1 -1
- package/lib/cli/components/ApprovePlan.js.map +1 -1
- package/lib/cli/components/Plan.d.ts +2 -2
- package/lib/cli/components/Plan.d.ts.map +1 -1
- package/lib/cli/components/Plan.js.map +1 -1
- package/lib/cli/components/PlanProgress.d.ts +8 -4
- package/lib/cli/components/PlanProgress.d.ts.map +1 -1
- package/lib/cli/components/PlanProgress.js +11 -1
- package/lib/cli/components/PlanProgress.js.map +1 -1
- package/lib/cli/index.d.ts +384 -264
- package/lib/cli/index.d.ts.map +1 -1
- package/lib/cli/index.js +57 -65
- package/lib/cli/index.js.map +1 -1
- package/lib/cli/ink-service.d.ts +4 -0
- package/lib/cli/ink-service.d.ts.map +1 -0
- package/lib/cli/ink-service.js +43 -0
- package/lib/cli/ink-service.js.map +1 -0
- package/lib/cli/service.d.ts +21 -0
- package/lib/cli/service.d.ts.map +1 -0
- package/lib/cli/service.js +5 -0
- package/lib/cli/service.js.map +1 -0
- package/lib/cloudflare/account.d.ts +10 -0
- package/lib/cloudflare/account.d.ts.map +1 -0
- package/lib/cloudflare/account.js +24 -0
- package/lib/cloudflare/account.js.map +1 -0
- package/lib/cloudflare/api.d.ts +7 -7
- package/lib/cloudflare/api.d.ts.map +1 -1
- package/lib/cloudflare/api.js +18 -17
- package/lib/cloudflare/api.js.map +1 -1
- package/lib/cloudflare/config.d.ts +9 -0
- package/lib/cloudflare/config.d.ts.map +1 -0
- package/lib/cloudflare/config.js +1 -0
- package/lib/cloudflare/config.js.map +1 -0
- package/lib/cloudflare/index.d.ts +3 -1
- package/lib/cloudflare/index.d.ts.map +1 -1
- package/lib/cloudflare/index.js +3 -0
- package/lib/cloudflare/index.js.map +1 -1
- package/lib/cloudflare/kv/namespace.binding.d.ts +5 -3
- package/lib/cloudflare/kv/namespace.binding.d.ts.map +1 -1
- package/lib/cloudflare/kv/namespace.binding.js +1 -1
- package/lib/cloudflare/kv/namespace.binding.js.map +1 -1
- package/lib/cloudflare/kv/namespace.client.d.ts +1 -1
- package/lib/cloudflare/kv/namespace.d.ts +3 -2
- package/lib/cloudflare/kv/namespace.d.ts.map +1 -1
- package/lib/cloudflare/kv/namespace.js.map +1 -1
- package/lib/cloudflare/kv/namespace.provider.d.ts +3 -2
- package/lib/cloudflare/kv/namespace.provider.d.ts.map +1 -1
- package/lib/cloudflare/kv/namespace.provider.js +9 -7
- package/lib/cloudflare/kv/namespace.provider.js.map +1 -1
- package/lib/cloudflare/live.d.ts +5 -5
- package/lib/cloudflare/live.d.ts.map +1 -1
- package/lib/cloudflare/live.js +5 -8
- package/lib/cloudflare/live.js.map +1 -1
- package/lib/cloudflare/r2/bucket.binding.d.ts +5 -3
- package/lib/cloudflare/r2/bucket.binding.d.ts.map +1 -1
- package/lib/cloudflare/r2/bucket.binding.js +1 -1
- package/lib/cloudflare/r2/bucket.binding.js.map +1 -1
- package/lib/cloudflare/r2/bucket.d.ts +3 -2
- package/lib/cloudflare/r2/bucket.d.ts.map +1 -1
- package/lib/cloudflare/r2/bucket.js.map +1 -1
- package/lib/cloudflare/r2/bucket.provider.d.ts +3 -2
- package/lib/cloudflare/r2/bucket.provider.d.ts.map +1 -1
- package/lib/cloudflare/r2/bucket.provider.js +14 -8
- package/lib/cloudflare/r2/bucket.provider.js.map +1 -1
- package/lib/cloudflare/worker/assets.fetch.d.ts +3 -2
- package/lib/cloudflare/worker/assets.fetch.d.ts.map +1 -1
- package/lib/cloudflare/worker/assets.fetch.js +2 -1
- package/lib/cloudflare/worker/assets.fetch.js.map +1 -1
- package/lib/cloudflare/worker/assets.provider.d.ts +1 -1
- package/lib/cloudflare/worker/assets.provider.d.ts.map +1 -1
- package/lib/cloudflare/worker/index.d.ts +0 -1
- package/lib/cloudflare/worker/index.d.ts.map +1 -1
- package/lib/cloudflare/worker/worker.d.ts +5 -6
- package/lib/cloudflare/worker/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker/worker.handler.d.ts +1 -1
- package/lib/cloudflare/worker/worker.handler.d.ts.map +1 -1
- package/lib/cloudflare/worker/worker.handler.js.map +1 -1
- package/lib/cloudflare/worker/worker.js.map +1 -1
- package/lib/cloudflare/worker/worker.provider.d.ts +3 -2
- package/lib/cloudflare/worker/worker.provider.d.ts.map +1 -1
- package/lib/cloudflare/worker/worker.provider.js +12 -7
- package/lib/cloudflare/worker/worker.provider.js.map +1 -1
- package/lib/cloudflare/worker/worker.serve.d.ts +7 -7
- package/lib/cloudflare/worker/worker.serve.d.ts.map +1 -1
- package/lib/cloudflare/worker/worker.serve.js.map +1 -1
- package/lib/data.d.ts +3 -0
- package/lib/data.d.ts.map +1 -0
- package/lib/data.js +8 -0
- package/lib/data.js.map +1 -0
- package/lib/destroy.d.ts +1 -1
- package/lib/destroy.d.ts.map +1 -1
- package/lib/destroy.js +1 -4
- package/lib/destroy.js.map +1 -1
- package/lib/diff.d.ts +18 -0
- package/lib/diff.d.ts.map +1 -0
- package/lib/diff.js +22 -0
- package/lib/diff.js.map +1 -0
- package/lib/env.d.ts +5 -0
- package/lib/env.d.ts.map +1 -1
- package/lib/env.js +15 -29
- package/lib/env.js.map +1 -1
- package/lib/event.d.ts +1 -1
- package/lib/event.d.ts.map +1 -1
- package/lib/exports.d.ts +9 -0
- package/lib/exports.d.ts.map +1 -0
- package/lib/exports.js +13 -0
- package/lib/exports.js.map +1 -0
- package/lib/index.d.ts +10 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +10 -5
- package/lib/index.js.map +1 -1
- package/lib/input.d.ts +32 -0
- package/lib/input.d.ts.map +1 -0
- package/lib/input.js +1 -0
- package/lib/input.js.map +1 -0
- package/lib/instance-id.d.ts +8 -0
- package/lib/instance-id.d.ts.map +1 -0
- package/lib/instance-id.js +12 -0
- package/lib/instance-id.js.map +1 -0
- package/lib/output.d.ts +145 -0
- package/lib/output.d.ts.map +1 -0
- package/lib/output.js +283 -0
- package/lib/output.js.map +1 -0
- package/lib/physical-name.d.ts +14 -1
- package/lib/physical-name.d.ts.map +1 -1
- package/lib/physical-name.js +41 -2
- package/lib/physical-name.js.map +1 -1
- package/lib/plan.d.ts +84 -58
- package/lib/plan.d.ts.map +1 -1
- package/lib/plan.js +504 -166
- package/lib/plan.js.map +1 -1
- package/lib/policy.d.ts +3 -4
- package/lib/policy.d.ts.map +1 -1
- package/lib/policy.js +0 -1
- package/lib/policy.js.map +1 -1
- package/lib/provider.d.ts +39 -24
- package/lib/provider.d.ts.map +1 -1
- package/lib/provider.js +9 -0
- package/lib/provider.js.map +1 -1
- package/lib/ref.d.ts +14 -0
- package/lib/ref.d.ts.map +1 -0
- package/lib/ref.js +21 -0
- package/lib/ref.js.map +1 -0
- package/lib/resource.d.ts +13 -8
- package/lib/resource.d.ts.map +1 -1
- package/lib/resource.js.map +1 -1
- package/lib/runtime.d.ts +7 -6
- package/lib/runtime.d.ts.map +1 -1
- package/lib/runtime.js.map +1 -1
- package/lib/service.d.ts +9 -6
- package/lib/service.d.ts.map +1 -1
- package/lib/service.js.map +1 -1
- package/lib/stack.d.ts +60 -0
- package/lib/stack.d.ts.map +1 -0
- package/lib/stack.js +11 -0
- package/lib/stack.js.map +1 -0
- package/lib/stage.d.ts +39 -0
- package/lib/stage.d.ts.map +1 -0
- package/lib/stage.js +32 -0
- package/lib/stage.js.map +1 -0
- package/lib/state.d.ts +135 -17
- package/lib/state.d.ts.map +1 -1
- package/lib/state.js +34 -30
- package/lib/state.js.map +1 -1
- package/lib/tags.d.ts +15 -0
- package/lib/tags.d.ts.map +1 -1
- package/lib/tags.js +27 -0
- package/lib/tags.js.map +1 -1
- package/lib/test.d.ts +25 -4
- package/lib/test.d.ts.map +1 -1
- package/lib/test.js +54 -14
- package/lib/test.js.map +1 -1
- package/lib/todo.d.ts +3 -0
- package/lib/todo.d.ts.map +1 -0
- package/lib/todo.js +3 -0
- package/lib/todo.js.map +1 -0
- package/lib/tsconfig.test.tsbuildinfo +1 -1
- package/lib/type.d.ts +3 -0
- package/lib/type.d.ts.map +1 -1
- package/lib/unknown.d.ts +4 -0
- package/lib/unknown.d.ts.map +1 -0
- package/lib/unknown.js +4 -0
- package/lib/unknown.js.map +1 -0
- package/lib/user.d.ts +3 -0
- package/lib/user.d.ts.map +1 -0
- package/lib/user.js +3 -0
- package/lib/user.js.map +1 -0
- package/lib/util.d.ts +6 -0
- package/lib/util.d.ts.map +1 -0
- package/lib/util.js +9 -0
- package/lib/util.js.map +1 -0
- package/package.json +18 -12
- package/src/$.ts +17 -0
- package/src/app.ts +3 -32
- package/src/apply.ts +824 -452
- package/src/assert-never.ts +18 -0
- package/src/aws/account.ts +23 -3
- package/src/aws/client.ts +0 -1
- package/src/aws/config.ts +16 -0
- package/src/aws/credentials.ts +212 -177
- package/src/aws/dynamodb/index.ts +3 -3
- package/src/aws/dynamodb/table.get-item.ts +5 -9
- package/src/aws/dynamodb/table.provider.ts +36 -39
- package/src/aws/dynamodb/table.ts +29 -84
- package/src/aws/ec2/index.ts +12 -0
- package/src/aws/ec2/internet-gateway.provider.ts +316 -0
- package/src/aws/ec2/internet-gateway.ts +79 -0
- package/src/aws/ec2/route-table-association.provider.ts +214 -0
- package/src/aws/ec2/route-table-association.ts +82 -0
- package/src/aws/ec2/route-table.provider.ts +306 -0
- package/src/aws/ec2/route-table.ts +175 -0
- package/src/aws/ec2/route.provider.ts +213 -0
- package/src/aws/ec2/route.ts +192 -0
- package/src/aws/ec2/subnet.provider.ts +358 -0
- package/src/aws/ec2/subnet.ts +213 -0
- package/src/aws/ec2/vpc.provider.ts +58 -50
- package/src/aws/ec2/vpc.ts +21 -8
- package/src/aws/index.ts +49 -40
- package/src/aws/lambda/consume.ts +8 -7
- package/src/aws/lambda/function.handler.ts +1 -1
- package/src/aws/lambda/function.invoke.ts +6 -2
- package/src/aws/lambda/function.provider.ts +41 -32
- package/src/aws/lambda/function.ts +7 -4
- package/src/aws/lambda/index.ts +2 -0
- package/src/aws/profile.ts +1 -4
- package/src/aws/region.ts +42 -3
- package/src/aws/sqs/index.ts +2 -0
- package/src/aws/sqs/queue.consume.ts +1 -1
- package/src/aws/sqs/queue.event-source.ts +29 -55
- package/src/aws/sqs/queue.provider.ts +10 -2
- package/src/aws/sqs/queue.send-message.ts +5 -8
- package/src/aws/sqs/queue.ts +9 -4
- package/src/binding.ts +19 -19
- package/src/cli/components/ApprovePlan.tsx +2 -2
- package/src/cli/components/Plan.tsx +3 -2
- package/src/cli/components/PlanProgress.tsx +32 -14
- package/src/cli/index.ts +2 -6
- package/src/cli/ink-service.tsx +61 -0
- package/src/cli/service.ts +23 -0
- package/src/cloudflare/account.ts +37 -0
- package/src/cloudflare/api.ts +33 -29
- package/src/cloudflare/config.ts +7 -0
- package/src/cloudflare/index.ts +3 -1
- package/src/cloudflare/kv/namespace.binding.ts +3 -1
- package/src/cloudflare/kv/namespace.provider.ts +10 -8
- package/src/cloudflare/kv/namespace.ts +3 -2
- package/src/cloudflare/live.ts +11 -17
- package/src/cloudflare/r2/bucket.binding.ts +3 -1
- package/src/cloudflare/r2/bucket.provider.ts +16 -9
- package/src/cloudflare/r2/bucket.ts +8 -2
- package/src/cloudflare/worker/assets.fetch.ts +3 -1
- package/src/cloudflare/worker/assets.provider.ts +1 -1
- package/src/cloudflare/worker/index.ts +0 -2
- package/src/cloudflare/worker/worker.handler.ts +1 -1
- package/src/cloudflare/worker/worker.provider.ts +21 -14
- package/src/cloudflare/worker/worker.serve.ts +5 -2
- package/src/cloudflare/worker/worker.ts +4 -3
- package/src/data.ts +18 -0
- package/src/destroy.ts +1 -5
- package/src/diff.ts +48 -0
- package/src/env.ts +20 -32
- package/src/event.ts +6 -0
- package/src/exports.ts +21 -0
- package/src/index.ts +10 -5
- package/src/input.ts +81 -0
- package/src/instance-id.ts +16 -0
- package/src/output.ts +542 -0
- package/src/physical-name.ts +57 -2
- package/src/plan.ts +757 -278
- package/src/policy.ts +3 -5
- package/src/provider.ts +70 -31
- package/src/ref.ts +48 -0
- package/src/resource.ts +70 -10
- package/src/runtime.ts +15 -8
- package/src/service.ts +11 -7
- package/src/stack.ts +116 -0
- package/src/stage.ts +85 -0
- package/src/state.ts +269 -76
- package/src/tags.ts +31 -0
- package/src/test.ts +118 -17
- package/src/todo.ts +4 -0
- package/src/type.ts +4 -0
- package/src/unknown.ts +6 -0
- package/src/user.ts +4 -0
- package/src/util.ts +21 -0
- package/lib/approve.d.ts +0 -15
- package/lib/approve.d.ts.map +0 -1
- package/lib/approve.js +0 -7
- package/lib/approve.js.map +0 -1
- package/lib/cli/approve.d.ts +0 -4
- package/lib/cli/approve.d.ts.map +0 -1
- package/lib/cli/approve.js +0 -18
- package/lib/cli/approve.js.map +0 -1
- package/lib/cli/clack.d.ts +0 -14
- package/lib/cli/clack.d.ts.map +0 -1
- package/lib/cli/clack.js +0 -12
- package/lib/cli/clack.js.map +0 -1
- package/lib/cli/main.d.ts +0 -2
- package/lib/cli/main.d.ts.map +0 -1
- package/lib/cli/main.js +0 -1
- package/lib/cli/main.js.map +0 -1
- package/lib/cli/plan.d.ts +0 -13
- package/lib/cli/plan.d.ts.map +0 -1
- package/lib/cli/plan.js +0 -1
- package/lib/cli/plan.js.map +0 -1
- package/lib/cli/progress.d.ts +0 -7
- package/lib/cli/progress.d.ts.map +0 -1
- package/lib/cli/progress.js +0 -30
- package/lib/cli/progress.js.map +0 -1
- package/lib/cli/spinner.d.ts +0 -2
- package/lib/cli/spinner.d.ts.map +0 -1
- package/lib/cli/spinner.js +0 -13
- package/lib/cli/spinner.js.map +0 -1
- package/src/approve.ts +0 -13
- package/src/cli/approve.tsx +0 -30
- package/src/cli/clack.ts +0 -22
- package/src/cli/main.ts +0 -0
- package/src/cli/plan.ts +0 -16
- package/src/cli/progress.tsx +0 -46
- package/src/cli/spinner.ts +0 -14
package/lib/plan.js
CHANGED
|
@@ -2,9 +2,12 @@ import * as Context from "effect/Context";
|
|
|
2
2
|
import * as Data from "effect/Data";
|
|
3
3
|
import * as Effect from "effect/Effect";
|
|
4
4
|
import { omit } from "effect/Struct";
|
|
5
|
-
import {} from "./
|
|
5
|
+
import { App } from "./app.js";
|
|
6
|
+
import * as Output from "./output.js";
|
|
7
|
+
import { getProviderByType } from "./provider.js";
|
|
6
8
|
import { isService } from "./service.js";
|
|
7
|
-
import { State, StateStoreError } from "./state.js";
|
|
9
|
+
import { State, StateStoreError, } from "./state.js";
|
|
10
|
+
import { asEffect } from "./util.js";
|
|
8
11
|
export const isBindNode = (node) => {
|
|
9
12
|
return (node &&
|
|
10
13
|
typeof node === "object" &&
|
|
@@ -20,187 +23,443 @@ export const isCRUD = (node) => {
|
|
|
20
23
|
node.action === "replace" ||
|
|
21
24
|
node.action === "noop"));
|
|
22
25
|
};
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
: []),
|
|
53
|
-
resource,
|
|
54
|
-
])
|
|
55
|
-
.filter((node, i, arr) => arr.findIndex((n) => n.id === node.id) === i)
|
|
56
|
-
.map(Effect.fn(function* (node) {
|
|
57
|
-
const id = node.id;
|
|
58
|
-
const resource = node;
|
|
59
|
-
const news = resource.props;
|
|
60
|
-
const oldState = yield* state.get(id);
|
|
26
|
+
export const plan = (..._resources) => Effect.gen(function* () {
|
|
27
|
+
const state = yield* State;
|
|
28
|
+
const findResources = (resource, visited) => {
|
|
29
|
+
if (visited.has(resource.id)) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
visited.add(resource.id);
|
|
33
|
+
const upstream = Object.values(Output.upstreamAny(resource.props));
|
|
34
|
+
return [
|
|
35
|
+
resource,
|
|
36
|
+
...upstream,
|
|
37
|
+
...upstream.flatMap((r) => findResources(r, visited)),
|
|
38
|
+
];
|
|
39
|
+
};
|
|
40
|
+
const resources = _resources
|
|
41
|
+
.flatMap((r) => findResources(r, new Set()))
|
|
42
|
+
.filter((r, i, arr) => arr.findIndex((r2) => r2.id === r.id) === i);
|
|
43
|
+
// TODO(sam): rename terminology to Stack
|
|
44
|
+
const app = yield* App;
|
|
45
|
+
const resourceIds = yield* state.list({
|
|
46
|
+
stack: app.name,
|
|
47
|
+
stage: app.stage,
|
|
48
|
+
});
|
|
49
|
+
const oldResources = yield* Effect.all(resourceIds.map((id) => state.get({ stack: app.name, stage: app.stage, resourceId: id })));
|
|
50
|
+
const resolvedResources = {};
|
|
51
|
+
const resolveResource = (resourceExpr) => Effect.gen(function* () {
|
|
52
|
+
return yield* (resolvedResources[resourceExpr.src.id] ??=
|
|
53
|
+
yield* Effect.cached(Effect.gen(function* () {
|
|
54
|
+
const resource = resourceExpr.src;
|
|
61
55
|
const provider = yield* resource.provider.tag;
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
oldProps: oldState?.props,
|
|
71
|
-
},
|
|
72
|
-
})
|
|
73
|
-
: []; // TODO(sam): return undefined instead of empty array
|
|
74
|
-
if (oldState === undefined ||
|
|
75
|
-
oldState.status === "creating") {
|
|
76
|
-
return Node({
|
|
77
|
-
action: "create",
|
|
78
|
-
news,
|
|
79
|
-
provider,
|
|
80
|
-
resource,
|
|
81
|
-
bindings,
|
|
82
|
-
// phantom
|
|
83
|
-
attributes: undefined,
|
|
84
|
-
});
|
|
56
|
+
const props = yield* resolveInput(resource.props);
|
|
57
|
+
const oldState = yield* state.get({
|
|
58
|
+
stack: app.name,
|
|
59
|
+
stage: app.stage,
|
|
60
|
+
resourceId: resource.id,
|
|
61
|
+
});
|
|
62
|
+
if (!oldState || oldState.status === "creating") {
|
|
63
|
+
return resourceExpr;
|
|
85
64
|
}
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
65
|
+
const oldProps = oldState.status === "created" ||
|
|
66
|
+
oldState.status === "updated" ||
|
|
67
|
+
oldState.status === "replaced"
|
|
68
|
+
? // if we're in a stable state, then just use the props
|
|
69
|
+
oldState.props
|
|
70
|
+
: // if we failed to update or replace, compare with the last known stable props
|
|
71
|
+
oldState.status === "updating" ||
|
|
72
|
+
oldState.status === "replacing"
|
|
73
|
+
? oldState.old.props
|
|
74
|
+
: // TODO(sam): it kinda doesn't make sense to diff with a "deleting" state
|
|
75
|
+
oldState.props;
|
|
76
|
+
const diff = yield* provider.diff
|
|
77
|
+
? provider.diff({
|
|
78
|
+
id: resource.id,
|
|
79
|
+
olds: oldProps,
|
|
80
|
+
instanceId: oldState.instanceId,
|
|
81
|
+
news: props,
|
|
82
|
+
output: oldState.attr,
|
|
92
83
|
})
|
|
93
|
-
: undefined;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
84
|
+
: Effect.succeed(undefined);
|
|
85
|
+
const stables = [
|
|
86
|
+
...(provider.stables ?? []),
|
|
87
|
+
...(diff?.stables ?? []),
|
|
88
|
+
];
|
|
89
|
+
const withStables = (output) => stables.length > 0
|
|
90
|
+
? new Output.ResourceExpr(resourceExpr.src, Object.fromEntries(stables.map((stable) => [stable, output?.[stable]])))
|
|
91
|
+
: // if there are no stable properties, treat every property as changed
|
|
92
|
+
resourceExpr;
|
|
93
|
+
if (diff == null) {
|
|
94
|
+
if (arePropsChanged(oldProps, props)) {
|
|
95
|
+
// the props have changed but the provider did not provide any hints as to what is stable
|
|
96
|
+
// so we must assume everything has changed
|
|
97
|
+
return withStables(oldState?.attr);
|
|
98
|
+
}
|
|
106
99
|
}
|
|
107
|
-
else if (diff
|
|
108
|
-
return
|
|
109
|
-
action: "replace",
|
|
110
|
-
olds: oldState.props,
|
|
111
|
-
news,
|
|
112
|
-
output: oldState.output,
|
|
113
|
-
provider,
|
|
114
|
-
resource,
|
|
115
|
-
bindings,
|
|
116
|
-
// phantom
|
|
117
|
-
attributes: undefined,
|
|
118
|
-
});
|
|
100
|
+
else if (diff.action === "update") {
|
|
101
|
+
return withStables(oldState?.attr);
|
|
119
102
|
}
|
|
120
|
-
else if (diff
|
|
121
|
-
return
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
bindings,
|
|
129
|
-
// phantom
|
|
130
|
-
attributes: undefined,
|
|
131
|
-
});
|
|
103
|
+
else if (diff.action === "replace") {
|
|
104
|
+
return resourceExpr;
|
|
105
|
+
}
|
|
106
|
+
if (oldState.status === "created" ||
|
|
107
|
+
oldState.status === "updated" ||
|
|
108
|
+
oldState.status === "replaced") {
|
|
109
|
+
// we can safely return the attributes if we know they have stabilized
|
|
110
|
+
return oldState?.attr;
|
|
132
111
|
}
|
|
133
112
|
else {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
resource,
|
|
137
|
-
bindings,
|
|
138
|
-
// phantom
|
|
139
|
-
attributes: undefined,
|
|
140
|
-
});
|
|
113
|
+
// we must assume the resource doesn't exist if it hasn't stabilized
|
|
114
|
+
return resourceExpr;
|
|
141
115
|
}
|
|
142
|
-
})))
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
116
|
+
})));
|
|
117
|
+
});
|
|
118
|
+
const resolveInput = (input) => Effect.gen(function* () {
|
|
119
|
+
if (!input) {
|
|
120
|
+
return input;
|
|
121
|
+
}
|
|
122
|
+
else if (Output.isExpr(input)) {
|
|
123
|
+
return yield* resolveOutput(input);
|
|
124
|
+
}
|
|
125
|
+
else if (Array.isArray(input)) {
|
|
126
|
+
return yield* Effect.all(input.map(resolveInput));
|
|
127
|
+
}
|
|
128
|
+
else if (typeof input === "object") {
|
|
129
|
+
return Object.fromEntries(yield* Effect.all(Object.entries(input).map(([key, value]) => resolveInput(value).pipe(Effect.map((value) => [key, value])))));
|
|
130
|
+
}
|
|
131
|
+
return input;
|
|
132
|
+
});
|
|
133
|
+
const resolveOutput = (expr) => Effect.gen(function* () {
|
|
134
|
+
if (Output.isResourceExpr(expr)) {
|
|
135
|
+
return yield* resolveResource(expr);
|
|
136
|
+
}
|
|
137
|
+
else if (Output.isPropExpr(expr)) {
|
|
138
|
+
const upstream = yield* resolveOutput(expr.expr);
|
|
139
|
+
return upstream?.[expr.identifier];
|
|
140
|
+
}
|
|
141
|
+
else if (Output.isApplyExpr(expr)) {
|
|
142
|
+
const upstream = yield* resolveOutput(expr.expr);
|
|
143
|
+
return Output.hasOutputs(upstream) ? expr : expr.f(upstream);
|
|
144
|
+
}
|
|
145
|
+
else if (Output.isEffectExpr(expr)) {
|
|
146
|
+
const upstream = yield* resolveOutput(expr.expr);
|
|
147
|
+
return Output.hasOutputs(upstream) ? expr : yield* expr.f(upstream);
|
|
148
|
+
}
|
|
149
|
+
else if (Output.isAllExpr(expr)) {
|
|
150
|
+
return yield* Effect.all(expr.outs.map(resolveOutput));
|
|
151
|
+
}
|
|
152
|
+
return yield* Effect.die(new Error("Not implemented yet"));
|
|
153
|
+
});
|
|
154
|
+
// map of resource ID -> its downstream dependencies (resources that depend on it)
|
|
155
|
+
const oldDownstreamDependencies = Object.fromEntries(oldResources
|
|
156
|
+
.filter((resource) => !!resource)
|
|
157
|
+
.map((resource) => [resource.logicalId, resource.downstream]));
|
|
158
|
+
const newUpstreamDependencies = Object.fromEntries(resources.map((resource) => [
|
|
159
|
+
resource.id,
|
|
160
|
+
[
|
|
161
|
+
...Object.values(Output.upstreamAny(resource.props)).map((r) => r.id),
|
|
162
|
+
...(isService(resource)
|
|
163
|
+
? resource.props.bindings.capabilities.map((cap) => cap.resource.id)
|
|
164
|
+
: []),
|
|
165
|
+
],
|
|
166
|
+
]));
|
|
167
|
+
const newDownstreamDependencies = Object.fromEntries(resources.map((resource) => [
|
|
168
|
+
resource.id,
|
|
169
|
+
Object.entries(newUpstreamDependencies)
|
|
170
|
+
.filter(([_, downstream]) => downstream.includes(resource.id))
|
|
171
|
+
.map(([id]) => id),
|
|
172
|
+
]));
|
|
173
|
+
const resourceGraph = Object.fromEntries((yield* Effect.all(resources
|
|
174
|
+
.flatMap((resource) => [
|
|
175
|
+
...(isService(resource)
|
|
176
|
+
? resource.props.bindings.capabilities.map((cap) => cap.resource)
|
|
177
|
+
: []),
|
|
178
|
+
...Object.values(Output.upstreamAny(resource.props)),
|
|
179
|
+
resource,
|
|
180
|
+
])
|
|
181
|
+
.filter((node, i, arr) => arr.findIndex((n) => n.id === node.id) === i)
|
|
182
|
+
.map(Effect.fn(function* (node) {
|
|
183
|
+
const id = node.id;
|
|
184
|
+
const resource = node;
|
|
185
|
+
const news = yield* resolveInput(resource.props);
|
|
186
|
+
const oldState = yield* state.get({
|
|
187
|
+
stack: app.name,
|
|
188
|
+
stage: app.stage,
|
|
189
|
+
resourceId: id,
|
|
190
|
+
});
|
|
191
|
+
const provider = yield* resource.provider.tag;
|
|
192
|
+
const downstream = newDownstreamDependencies[id] ?? [];
|
|
193
|
+
const bindings = isService(node)
|
|
194
|
+
? yield* diffBindings({
|
|
195
|
+
oldState,
|
|
196
|
+
bindings: node.props.bindings.bindings,
|
|
197
|
+
target: {
|
|
198
|
+
id: node.id,
|
|
199
|
+
props: node.props,
|
|
200
|
+
// TODO(sam): pick the right ones based on old status
|
|
201
|
+
oldAttr: oldState?.attr,
|
|
202
|
+
oldProps: oldState?.props,
|
|
203
|
+
},
|
|
204
|
+
})
|
|
205
|
+
: []; // TODO(sam): return undefined instead of empty array
|
|
206
|
+
const Node = (node) => ({
|
|
207
|
+
...node,
|
|
208
|
+
provider,
|
|
209
|
+
resource,
|
|
210
|
+
bindings,
|
|
211
|
+
downstream,
|
|
212
|
+
});
|
|
213
|
+
// handle empty and intermediate (non-final) states:
|
|
214
|
+
if (oldState === undefined) {
|
|
215
|
+
return Node({
|
|
216
|
+
action: "create",
|
|
217
|
+
props: news,
|
|
218
|
+
state: oldState,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
// TODO(sam): is this correct for all possible states a resource can be in?
|
|
222
|
+
const oldProps = oldState.props;
|
|
223
|
+
const diff = yield* asEffect(provider.diff
|
|
224
|
+
? provider.diff({
|
|
225
|
+
id,
|
|
226
|
+
olds: oldProps,
|
|
227
|
+
instanceId: oldState.instanceId,
|
|
228
|
+
output: oldState.attr,
|
|
229
|
+
news,
|
|
230
|
+
})
|
|
231
|
+
: undefined).pipe(Effect.map((diff) => diff ??
|
|
232
|
+
{
|
|
233
|
+
action: arePropsChanged(oldProps, news)
|
|
234
|
+
? "update"
|
|
235
|
+
: "noop",
|
|
236
|
+
}));
|
|
237
|
+
if (oldState.status === "creating") {
|
|
238
|
+
if (diff.action === "noop") {
|
|
239
|
+
// we're in the creating state and props are un-changed
|
|
240
|
+
// let's just continue where we left off
|
|
241
|
+
return Node({
|
|
242
|
+
action: "create",
|
|
243
|
+
props: news,
|
|
244
|
+
state: oldState,
|
|
245
|
+
});
|
|
147
246
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
247
|
+
else if (diff.action === "update") {
|
|
248
|
+
// props have changed in a way that is updatable
|
|
249
|
+
// again, just continue with the create
|
|
250
|
+
// TODO(sam): should we maybe try an update instead?
|
|
251
|
+
return Node({
|
|
252
|
+
action: "create",
|
|
253
|
+
props: news,
|
|
254
|
+
state: oldState,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
// props have changed in an incompatible way
|
|
259
|
+
// because it's possible that an un-updatable resource has already been created
|
|
260
|
+
// we must use a replace step to create a new one and delete the potential old one
|
|
261
|
+
return Node({
|
|
262
|
+
action: "replace",
|
|
263
|
+
props: news,
|
|
264
|
+
deleteFirst: diff.deleteFirst ?? false,
|
|
265
|
+
state: oldState,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else if (oldState.status === "updating") {
|
|
270
|
+
// we started to update a resource but did not complete
|
|
271
|
+
if (diff.action === "update" || diff.action === "noop") {
|
|
272
|
+
return Node({
|
|
273
|
+
action: "update",
|
|
274
|
+
props: news,
|
|
275
|
+
state: oldState,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
// we started to update a resource but now believe we should replace it
|
|
280
|
+
return Node({
|
|
281
|
+
action: "replace",
|
|
282
|
+
deleteFirst: diff.deleteFirst ?? false,
|
|
283
|
+
props: news,
|
|
284
|
+
// TODO(sam): can Apply handle replacements when the oldState is UpdatingResourceState?
|
|
285
|
+
// -> or is there we do a provider.read to try and reconcile back to UpdatedResourceState?
|
|
286
|
+
state: oldState,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
else if (oldState.status === "replacing") {
|
|
291
|
+
// resource replacement started, but the replacement may or may not have been created
|
|
292
|
+
if (diff.action === "noop") {
|
|
293
|
+
// this is the stable case - noop means just continue with the replacement
|
|
294
|
+
return Node({
|
|
295
|
+
action: "replace",
|
|
296
|
+
deleteFirst: oldState.deleteFirst,
|
|
297
|
+
props: news,
|
|
298
|
+
state: oldState,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
else if (diff.action === "update") {
|
|
302
|
+
// potential problem here - the props have changed since we tried to replace,
|
|
303
|
+
// but not enough to trigger another replacement. the resource provider should
|
|
304
|
+
// be designed as idempotent to converge to the right state when creating the new resource
|
|
305
|
+
// the newly generated instanceId is intended to assist with this
|
|
306
|
+
return Node({
|
|
307
|
+
action: "replace",
|
|
308
|
+
deleteFirst: oldState.deleteFirst,
|
|
309
|
+
props: news,
|
|
310
|
+
state: oldState,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
// ah shit, so we tried to replace the resource and then crashed
|
|
315
|
+
// now the props have changed again in such a way that the (maybe, maybe not)
|
|
316
|
+
// created resource should also be replaced
|
|
317
|
+
// TODO(sam): what should we do?
|
|
318
|
+
// 1. trigger a deletion of the potentially created resource
|
|
319
|
+
// 2. expect the resource provider to handle it idempotently?
|
|
320
|
+
// -> i don't think this case is fair to put on the resource provider
|
|
321
|
+
// because if the resource was created, it's in a state that can't be updated
|
|
322
|
+
return yield* Effect.fail(new CannotReplacePartiallyReplacedResource(id));
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
else if (oldState.status === "replaced") {
|
|
326
|
+
// replacement has been created but we're not done cleaning up the old state
|
|
327
|
+
if (diff.action === "noop") {
|
|
328
|
+
// this is the stable case - noop means just continue cleaning up the replacement
|
|
329
|
+
return Node({
|
|
330
|
+
action: "replace",
|
|
331
|
+
deleteFirst: oldState.deleteFirst,
|
|
332
|
+
props: news,
|
|
333
|
+
state: oldState,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
else if (diff.action === "update") {
|
|
337
|
+
// the replacement has been created but now also needs to be updated
|
|
338
|
+
// the resource provider should:
|
|
339
|
+
// 1. Update the newly created replacement resource
|
|
340
|
+
// 2. Then proceed as normal to delete the replaced resources (after all downstream references are updated)
|
|
341
|
+
return Node({
|
|
342
|
+
action: "update",
|
|
343
|
+
props: news,
|
|
344
|
+
state: oldState,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
// the replacement has been created but now it needs to be replaced
|
|
349
|
+
// this is the worst-case scenario because downstream resources
|
|
350
|
+
// could have been been updated to point to the replaced resources
|
|
351
|
+
return yield* Effect.fail(new CannotReplacePartiallyReplacedResource(id));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
else if (oldState.status === "deleting") {
|
|
355
|
+
if (diff.action === "noop" || diff.action === "update") {
|
|
356
|
+
// we're in a partially deleted state, it is unclear whether it was or was not deleted
|
|
357
|
+
// it should be safe to re-create it with the same instanceId?
|
|
358
|
+
return Node({
|
|
359
|
+
action: "create",
|
|
360
|
+
props: news,
|
|
361
|
+
state: {
|
|
362
|
+
...oldState,
|
|
363
|
+
status: "creating",
|
|
364
|
+
props: news,
|
|
173
365
|
},
|
|
174
|
-
|
|
366
|
+
});
|
|
175
367
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
const dependencies = deletion.downstream.filter((d) => d in resourceGraph);
|
|
179
|
-
if (dependencies.length > 0) {
|
|
180
|
-
return yield* Effect.fail(new DeleteResourceHasDownstreamDependencies({
|
|
181
|
-
message: `Resource ${resourceId} has downstream dependencies`,
|
|
182
|
-
resourceId,
|
|
183
|
-
dependencies,
|
|
184
|
-
}));
|
|
368
|
+
else {
|
|
369
|
+
return yield* Effect.fail(new CannotReplacePartiallyReplacedResource(id));
|
|
185
370
|
}
|
|
186
371
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
|
|
372
|
+
else if (diff.action === "update") {
|
|
373
|
+
return Node({
|
|
374
|
+
action: "update",
|
|
375
|
+
props: news,
|
|
376
|
+
state: oldState,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
else if (diff.action === "replace") {
|
|
380
|
+
return Node({
|
|
381
|
+
action: "replace",
|
|
382
|
+
props: news,
|
|
383
|
+
state: oldState,
|
|
384
|
+
deleteFirst: diff?.deleteFirst ?? false,
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
return Node({
|
|
389
|
+
action: "noop",
|
|
390
|
+
state: oldState,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
})))).map((update) => [update.resource.id, update]));
|
|
394
|
+
const deletions = Object.fromEntries((yield* Effect.all((yield* state.list({ stack: app.name, stage: app.stage })).map(Effect.fn(function* (id) {
|
|
395
|
+
if (id in resourceGraph) {
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
const oldState = yield* state.get({
|
|
399
|
+
stack: app.name,
|
|
400
|
+
stage: app.stage,
|
|
401
|
+
resourceId: id,
|
|
402
|
+
});
|
|
403
|
+
if (oldState) {
|
|
404
|
+
const provider = yield* getProviderByType(oldState.resourceType);
|
|
405
|
+
return [
|
|
406
|
+
id,
|
|
407
|
+
{
|
|
408
|
+
action: "delete",
|
|
409
|
+
state: oldState,
|
|
410
|
+
// // TODO(sam): Support Detach Bindings
|
|
411
|
+
bindings: [],
|
|
412
|
+
provider,
|
|
413
|
+
resource: {
|
|
414
|
+
id: id,
|
|
415
|
+
type: oldState.resourceType,
|
|
416
|
+
attr: oldState.attr,
|
|
417
|
+
props: oldState.props,
|
|
418
|
+
},
|
|
419
|
+
// TODO(sam): is it enough to just pass through oldState?
|
|
420
|
+
downstream: oldDownstreamDependencies[id] ?? [],
|
|
421
|
+
},
|
|
422
|
+
];
|
|
423
|
+
}
|
|
424
|
+
})))).filter((v) => !!v));
|
|
425
|
+
for (const [resourceId, deletion] of Object.entries(deletions)) {
|
|
426
|
+
const dependencies = deletion.state.downstream.filter((d) => d in resourceGraph);
|
|
427
|
+
if (dependencies.length > 0) {
|
|
428
|
+
return yield* Effect.fail(new DeleteResourceHasDownstreamDependencies({
|
|
429
|
+
message: `Resource ${resourceId} has downstream dependencies`,
|
|
430
|
+
resourceId,
|
|
431
|
+
dependencies,
|
|
432
|
+
}));
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
return {
|
|
436
|
+
resources: resourceGraph,
|
|
437
|
+
deletions,
|
|
438
|
+
};
|
|
439
|
+
});
|
|
440
|
+
export class CannotReplacePartiallyReplacedResource extends Data.TaggedError("CannotReplacePartiallyReplacedResource") {
|
|
441
|
+
constructor(logicalId) {
|
|
442
|
+
super({
|
|
443
|
+
message: `Resource '${logicalId}' did not finish being replaced in a previous deployment ` +
|
|
444
|
+
`and is expected to be replaced again in this deployment. ` +
|
|
445
|
+
`You should revert its properties and try again after a successful deployment.`,
|
|
446
|
+
logicalId,
|
|
447
|
+
});
|
|
448
|
+
}
|
|
195
449
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
450
|
+
export class DeleteResourceHasDownstreamDependencies extends Data.TaggedError("DeleteResourceHasDownstreamDependencies") {
|
|
451
|
+
}
|
|
452
|
+
const arePropsChanged = (oldProps, newProps) => {
|
|
453
|
+
return (Output.hasOutputs(newProps) ||
|
|
454
|
+
JSON.stringify(omit((oldProps ?? {}), "bindings")) !==
|
|
455
|
+
JSON.stringify(omit((newProps ?? {}), "bindings")));
|
|
199
456
|
};
|
|
200
457
|
const diffBindings = Effect.fn(function* ({ oldState, bindings, target, }) {
|
|
201
458
|
// const actions: BindNode[] = [];
|
|
202
459
|
const oldBindings = oldState?.bindings;
|
|
203
|
-
const oldSids = new Set(
|
|
460
|
+
// const oldSids = new Set(
|
|
461
|
+
// oldBindings?.map(({ binding }) => binding.capability.sid),
|
|
462
|
+
// );
|
|
204
463
|
const diffBinding = Effect.fn(function* (binding) {
|
|
205
464
|
const cap = binding.capability;
|
|
206
465
|
const sid = cap.sid ?? `${cap.action}:${cap.resource.ID}`;
|
|
@@ -277,7 +536,7 @@ const isBindingDiff = Effect.fn(function* ({ target, oldBinding: { binding: oldB
|
|
|
277
536
|
id: oldCap.resource.id,
|
|
278
537
|
props: newCap.resource.props,
|
|
279
538
|
oldProps: oldState?.props,
|
|
280
|
-
oldAttr: oldState?.
|
|
539
|
+
oldAttr: oldState?.attr,
|
|
281
540
|
},
|
|
282
541
|
props: newBinding.props,
|
|
283
542
|
attr: oldBinding.attr,
|
|
@@ -297,4 +556,83 @@ const isBindingDiff = Effect.fn(function* ({ target, oldBinding: { binding: oldB
|
|
|
297
556
|
});
|
|
298
557
|
// TODO(sam): compare props
|
|
299
558
|
// oldBinding.props !== newBinding.props;
|
|
559
|
+
/**
|
|
560
|
+
* Print a plan in a human-readable format that shows the graph topology.
|
|
561
|
+
*/
|
|
562
|
+
export const printPlan = (plan) => {
|
|
563
|
+
const lines = [];
|
|
564
|
+
const allNodes = { ...plan.resources, ...plan.deletions };
|
|
565
|
+
// Build reverse mapping: upstream -> downstream
|
|
566
|
+
const upstreamMap = {};
|
|
567
|
+
for (const [id] of Object.entries(allNodes)) {
|
|
568
|
+
upstreamMap[id] = [];
|
|
569
|
+
}
|
|
570
|
+
for (const [id, node] of Object.entries(allNodes)) {
|
|
571
|
+
if (!node)
|
|
572
|
+
continue;
|
|
573
|
+
for (const downstreamId of node.state?.downstream ?? []) {
|
|
574
|
+
if (upstreamMap[downstreamId]) {
|
|
575
|
+
upstreamMap[downstreamId].push(id);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
// Action symbols
|
|
580
|
+
const actionSymbol = (action) => {
|
|
581
|
+
switch (action) {
|
|
582
|
+
case "create":
|
|
583
|
+
return "+";
|
|
584
|
+
case "update":
|
|
585
|
+
return "~";
|
|
586
|
+
case "delete":
|
|
587
|
+
return "-";
|
|
588
|
+
case "replace":
|
|
589
|
+
return "±";
|
|
590
|
+
case "noop":
|
|
591
|
+
return "=";
|
|
592
|
+
default:
|
|
593
|
+
return "?";
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
// Print header
|
|
597
|
+
lines.push("╔════════════════════════════════════════════════════════════════╗");
|
|
598
|
+
lines.push("║ PLAN ║");
|
|
599
|
+
lines.push("╠════════════════════════════════════════════════════════════════╣");
|
|
600
|
+
lines.push("║ Legend: + create, ~ update, - delete, ± replace, = noop ║");
|
|
601
|
+
lines.push("╚════════════════════════════════════════════════════════════════╝");
|
|
602
|
+
lines.push("");
|
|
603
|
+
// Print resources section
|
|
604
|
+
lines.push("┌─ Resources ────────────────────────────────────────────────────┐");
|
|
605
|
+
const resourceIds = Object.keys(plan.resources).sort();
|
|
606
|
+
for (const id of resourceIds) {
|
|
607
|
+
const node = plan.resources[id];
|
|
608
|
+
const symbol = actionSymbol(node.action);
|
|
609
|
+
const type = node.resource?.type ?? "unknown";
|
|
610
|
+
const downstream = node.state?.downstream?.length
|
|
611
|
+
? ` → [${node.state?.downstream.join(", ")}]`
|
|
612
|
+
: "";
|
|
613
|
+
lines.push(`│ [${symbol}] ${id} (${type})${downstream}`);
|
|
614
|
+
}
|
|
615
|
+
if (resourceIds.length === 0) {
|
|
616
|
+
lines.push("│ (none)");
|
|
617
|
+
}
|
|
618
|
+
lines.push("└────────────────────────────────────────────────────────────────┘");
|
|
619
|
+
lines.push("");
|
|
620
|
+
// Print deletions section
|
|
621
|
+
lines.push("┌─ Deletions ────────────────────────────────────────────────────┐");
|
|
622
|
+
const deletionIds = Object.keys(plan.deletions).sort();
|
|
623
|
+
for (const id of deletionIds) {
|
|
624
|
+
const node = plan.deletions[id];
|
|
625
|
+
const type = node.resource?.type ?? "unknown";
|
|
626
|
+
const downstream = node.state.downstream?.length
|
|
627
|
+
? ` → [${node.state.downstream.join(", ")}]`
|
|
628
|
+
: "";
|
|
629
|
+
lines.push(`│ [-] ${id} (${type})${downstream}`);
|
|
630
|
+
}
|
|
631
|
+
if (deletionIds.length === 0) {
|
|
632
|
+
lines.push("│ (none)");
|
|
633
|
+
}
|
|
634
|
+
lines.push("└────────────────────────────────────────────────────────────────┘");
|
|
635
|
+
lines.push("");
|
|
636
|
+
return lines.join("\n");
|
|
637
|
+
};
|
|
300
638
|
//# sourceMappingURL=plan.js.map
|