alchemy 2.0.0-beta.44 → 2.0.0-beta.46
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/exec.js +67 -8
- package/bin/exec.js.map +1 -1
- package/lib/AWS/Lambda/Function.d.ts +17 -0
- package/lib/AWS/Lambda/Function.d.ts.map +1 -1
- package/lib/AWS/Lambda/Function.js +61 -16
- package/lib/AWS/Lambda/Function.js.map +1 -1
- package/lib/AWS/Providers.d.ts +2 -1
- package/lib/AWS/Providers.d.ts.map +1 -1
- package/lib/AWS/Providers.js +3 -1
- package/lib/AWS/Providers.js.map +1 -1
- package/lib/AlchemyContext.d.ts +0 -1
- package/lib/AlchemyContext.d.ts.map +1 -1
- package/lib/AlchemyContext.js.map +1 -1
- package/lib/Apply.js +17 -1
- package/lib/Apply.js.map +1 -1
- package/lib/Auth/AuthProvider.d.ts.map +1 -1
- package/lib/Auth/AuthProvider.js +24 -6
- package/lib/Auth/AuthProvider.js.map +1 -1
- package/lib/Auth/Credentials.d.ts.map +1 -1
- package/lib/Auth/Credentials.js +3 -3
- package/lib/Auth/Credentials.js.map +1 -1
- package/lib/Cli/commands/_shared.d.ts +13 -1
- package/lib/Cli/commands/_shared.d.ts.map +1 -1
- package/lib/Cli/commands/_shared.js +33 -2
- package/lib/Cli/commands/_shared.js.map +1 -1
- package/lib/Cli/commands/cloudflare.d.ts.map +1 -1
- package/lib/Cli/commands/cloudflare.js +5 -1
- package/lib/Cli/commands/cloudflare.js.map +1 -1
- package/lib/Cli/commands/dev.d.ts.map +1 -1
- package/lib/Cli/commands/dev.js +10 -1
- package/lib/Cli/commands/dev.js.map +1 -1
- package/lib/Cli/commands/login.d.ts.map +1 -1
- package/lib/Cli/commands/login.js +19 -5
- package/lib/Cli/commands/login.js.map +1 -1
- package/lib/Cli/commands/profile.d.ts.map +1 -1
- package/lib/Cli/commands/profile.js +7 -27
- package/lib/Cli/commands/profile.js.map +1 -1
- package/lib/Cli/main.d.ts.map +1 -1
- package/lib/Cli/main.js +0 -2
- package/lib/Cli/main.js.map +1 -1
- package/lib/Cloudflare/AiGateway/AiGateway.d.ts +0 -2
- package/lib/Cloudflare/AiGateway/AiGateway.d.ts.map +1 -1
- package/lib/Cloudflare/AiGateway/AiGateway.js +2 -4
- package/lib/Cloudflare/AiGateway/AiGateway.js.map +1 -1
- package/lib/Cloudflare/BrowserRendering/BrowserRendering.d.ts +116 -0
- package/lib/Cloudflare/BrowserRendering/BrowserRendering.d.ts.map +1 -0
- package/lib/Cloudflare/BrowserRendering/BrowserRendering.js +92 -0
- package/lib/Cloudflare/BrowserRendering/BrowserRendering.js.map +1 -0
- package/lib/Cloudflare/BrowserRendering/BrowserRenderingBinding.d.ts +55 -0
- package/lib/Cloudflare/BrowserRendering/BrowserRenderingBinding.d.ts.map +1 -0
- package/lib/Cloudflare/BrowserRendering/BrowserRenderingBinding.js +55 -0
- package/lib/Cloudflare/BrowserRendering/BrowserRenderingBinding.js.map +1 -0
- package/lib/Cloudflare/BrowserRendering/index.d.ts +3 -0
- package/lib/Cloudflare/BrowserRendering/index.d.ts.map +1 -0
- package/lib/Cloudflare/BrowserRendering/index.js +3 -0
- package/lib/Cloudflare/BrowserRendering/index.js.map +1 -0
- package/lib/Cloudflare/Container/Container.d.ts +3 -3
- package/lib/Cloudflare/Container/Container.js +3 -3
- package/lib/Cloudflare/Container/StartContainer.d.ts.map +1 -1
- package/lib/Cloudflare/Container/StartContainer.js.map +1 -1
- package/lib/Cloudflare/D1/D1Database.d.ts +1 -0
- package/lib/Cloudflare/D1/D1Database.d.ts.map +1 -1
- package/lib/Cloudflare/D1/D1Database.js +2 -1
- package/lib/Cloudflare/D1/D1Database.js.map +1 -1
- package/lib/Cloudflare/D1/D1DatabaseBinding.js +1 -1
- package/lib/Cloudflare/D1/D1DatabaseBinding.js.map +1 -1
- package/lib/Cloudflare/Fetcher.d.ts.map +1 -1
- package/lib/Cloudflare/Fetcher.js +0 -2
- package/lib/Cloudflare/Fetcher.js.map +1 -1
- package/lib/Cloudflare/Hyperdrive/Hyperdrive.d.ts +1 -0
- package/lib/Cloudflare/Hyperdrive/Hyperdrive.d.ts.map +1 -1
- package/lib/Cloudflare/Hyperdrive/Hyperdrive.js +3 -0
- package/lib/Cloudflare/Hyperdrive/Hyperdrive.js.map +1 -1
- package/lib/Cloudflare/Hyperdrive/HyperdriveBinding.d.ts +3 -2
- package/lib/Cloudflare/Hyperdrive/HyperdriveBinding.d.ts.map +1 -1
- package/lib/Cloudflare/Hyperdrive/HyperdriveBinding.js +32 -33
- package/lib/Cloudflare/Hyperdrive/HyperdriveBinding.js.map +1 -1
- package/lib/Cloudflare/KV/KVNamespace.d.ts +1 -0
- package/lib/Cloudflare/KV/KVNamespace.d.ts.map +1 -1
- package/lib/Cloudflare/KV/KVNamespace.js +2 -0
- package/lib/Cloudflare/KV/KVNamespace.js.map +1 -1
- package/lib/Cloudflare/Local.js +1 -1
- package/lib/Cloudflare/Local.js.map +1 -1
- package/lib/Cloudflare/Providers.d.ts +2 -1
- package/lib/Cloudflare/Providers.d.ts.map +1 -1
- package/lib/Cloudflare/Providers.js +25 -17
- package/lib/Cloudflare/Providers.js.map +1 -1
- package/lib/Cloudflare/Queue/Queue.d.ts +1 -0
- package/lib/Cloudflare/Queue/Queue.d.ts.map +1 -1
- package/lib/Cloudflare/Queue/Queue.js +1 -0
- package/lib/Cloudflare/Queue/Queue.js.map +1 -1
- package/lib/Cloudflare/Queue/QueueConsumer.d.ts +2 -1
- package/lib/Cloudflare/Queue/QueueConsumer.d.ts.map +1 -1
- package/lib/Cloudflare/Queue/QueueConsumer.js +10 -3
- package/lib/Cloudflare/Queue/QueueConsumer.js.map +1 -1
- package/lib/Cloudflare/Queue/QueueEventSource.d.ts +30 -4
- package/lib/Cloudflare/Queue/QueueEventSource.d.ts.map +1 -1
- package/lib/Cloudflare/Queue/QueueEventSource.js +22 -1
- package/lib/Cloudflare/Queue/QueueEventSource.js.map +1 -1
- package/lib/Cloudflare/R2/R2Bucket.d.ts +1 -0
- package/lib/Cloudflare/R2/R2Bucket.d.ts.map +1 -1
- package/lib/Cloudflare/R2/R2Bucket.js +18 -0
- package/lib/Cloudflare/R2/R2Bucket.js.map +1 -1
- package/lib/Cloudflare/SecretsStore/Secret.d.ts.map +1 -1
- package/lib/Cloudflare/SecretsStore/Secret.js +13 -34
- package/lib/Cloudflare/SecretsStore/Secret.js.map +1 -1
- package/lib/Cloudflare/SecretsStore/SecretBinding.d.ts +3 -2
- package/lib/Cloudflare/SecretsStore/SecretBinding.d.ts.map +1 -1
- package/lib/Cloudflare/SecretsStore/SecretBinding.js +3 -2
- package/lib/Cloudflare/SecretsStore/SecretBinding.js.map +1 -1
- package/lib/Cloudflare/StateStore/Api.d.ts +5 -13
- package/lib/Cloudflare/StateStore/Api.d.ts.map +1 -1
- package/lib/Cloudflare/StateStore/Api.js +14 -8
- package/lib/Cloudflare/StateStore/Api.js.map +1 -1
- package/lib/Cloudflare/StateStore/State.d.ts +11 -65
- package/lib/Cloudflare/StateStore/State.d.ts.map +1 -1
- package/lib/Cloudflare/StateStore/State.js +320 -343
- package/lib/Cloudflare/StateStore/State.js.map +1 -1
- package/lib/Cloudflare/StateStore/Store.d.ts.map +1 -1
- package/lib/Cloudflare/StateStore/Store.js +21 -31
- package/lib/Cloudflare/StateStore/Store.js.map +1 -1
- package/lib/Cloudflare/Vectorize/VectorizeIndex.d.ts +114 -0
- package/lib/Cloudflare/Vectorize/VectorizeIndex.d.ts.map +1 -0
- package/lib/Cloudflare/Vectorize/VectorizeIndex.js +157 -0
- package/lib/Cloudflare/Vectorize/VectorizeIndex.js.map +1 -0
- package/lib/Cloudflare/Vectorize/VectorizeIndexBinding.d.ts +38 -0
- package/lib/Cloudflare/Vectorize/VectorizeIndexBinding.d.ts.map +1 -0
- package/lib/Cloudflare/Vectorize/VectorizeIndexBinding.js +44 -0
- package/lib/Cloudflare/Vectorize/VectorizeIndexBinding.js.map +1 -0
- package/lib/Cloudflare/Vectorize/VectorizeMetadataIndex.d.ts +72 -0
- package/lib/Cloudflare/Vectorize/VectorizeMetadataIndex.d.ts.map +1 -0
- package/lib/Cloudflare/Vectorize/VectorizeMetadataIndex.js +131 -0
- package/lib/Cloudflare/Vectorize/VectorizeMetadataIndex.js.map +1 -0
- package/lib/Cloudflare/Vectorize/index.d.ts +4 -0
- package/lib/Cloudflare/Vectorize/index.d.ts.map +1 -0
- package/lib/Cloudflare/Vectorize/index.js +4 -0
- package/lib/Cloudflare/Vectorize/index.js.map +1 -0
- package/lib/Cloudflare/VpcService/VpcService.d.ts +2 -2
- package/lib/Cloudflare/VpcService/VpcService.d.ts.map +1 -1
- package/lib/Cloudflare/Website/StaticSite.d.ts +5 -5
- package/lib/Cloudflare/Website/StaticSite.d.ts.map +1 -1
- package/lib/Cloudflare/Website/StaticSite.js +3 -0
- package/lib/Cloudflare/Website/StaticSite.js.map +1 -1
- package/lib/Cloudflare/Website/Vite.d.ts +5 -5
- package/lib/Cloudflare/Website/Vite.d.ts.map +1 -1
- package/lib/Cloudflare/Website/Vite.js.map +1 -1
- package/lib/Cloudflare/Workers/Assets.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Assets.js +1 -1
- package/lib/Cloudflare/Workers/Assets.js.map +1 -1
- package/lib/Cloudflare/Workers/DurableObjectBridge.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/DurableObjectBridge.js +4 -2
- package/lib/Cloudflare/Workers/DurableObjectBridge.js.map +1 -1
- package/lib/Cloudflare/Workers/DurableObjectNamespace.d.ts +183 -6
- package/lib/Cloudflare/Workers/DurableObjectNamespace.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/DurableObjectNamespace.js +279 -76
- package/lib/Cloudflare/Workers/DurableObjectNamespace.js.map +1 -1
- package/lib/Cloudflare/Workers/HttpServer.d.ts +6 -4
- package/lib/Cloudflare/Workers/HttpServer.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/HttpServer.js +20 -15
- package/lib/Cloudflare/Workers/HttpServer.js.map +1 -1
- package/lib/Cloudflare/Workers/InferEnv.d.ts +3 -2
- package/lib/Cloudflare/Workers/InferEnv.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts +4 -7
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js +111 -66
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
- package/lib/Cloudflare/Workers/Rpc.d.ts +16 -0
- package/lib/Cloudflare/Workers/Rpc.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Rpc.js +22 -0
- package/lib/Cloudflare/Workers/Rpc.js.map +1 -1
- package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.d.ts +285 -0
- package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.d.ts.map +1 -0
- package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.js +288 -0
- package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.js.map +1 -0
- package/lib/Cloudflare/Workers/RpcWorker.d.ts +305 -0
- package/lib/Cloudflare/Workers/RpcWorker.d.ts.map +1 -0
- package/lib/Cloudflare/Workers/RpcWorker.js +350 -0
- package/lib/Cloudflare/Workers/RpcWorker.js.map +1 -0
- package/lib/Cloudflare/Workers/Vite.d.ts +1 -1
- package/lib/Cloudflare/Workers/Vite.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Vite.js +2 -1
- package/lib/Cloudflare/Workers/Vite.js.map +1 -1
- package/lib/Cloudflare/Workers/Worker.d.ts +69 -24
- package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.js +168 -47
- package/lib/Cloudflare/Workers/Worker.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.d.ts +1 -1
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.js +166 -97
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBinding.d.ts +12 -23
- package/lib/Cloudflare/Workers/WorkerBinding.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBinding.js +3 -0
- package/lib/Cloudflare/Workers/WorkerBinding.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBridge.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBridge.js +5 -2
- package/lib/Cloudflare/Workers/WorkerBridge.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBundle.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBundle.js +4 -1
- package/lib/Cloudflare/Workers/WorkerBundle.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerRuntimeContext.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerRuntimeContext.js +9 -10
- package/lib/Cloudflare/Workers/WorkerRuntimeContext.js.map +1 -1
- package/lib/Cloudflare/Workers/Workflow.d.ts +5 -3
- package/lib/Cloudflare/Workers/Workflow.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Workflow.js +19 -1
- package/lib/Cloudflare/Workers/Workflow.js.map +1 -1
- package/lib/Cloudflare/Workers/index.d.ts +2 -0
- package/lib/Cloudflare/Workers/index.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/index.js +2 -0
- package/lib/Cloudflare/Workers/index.js.map +1 -1
- package/lib/Cloudflare/index.d.ts +2 -0
- package/lib/Cloudflare/index.d.ts.map +1 -1
- package/lib/Cloudflare/index.js +2 -0
- package/lib/Cloudflare/index.js.map +1 -1
- package/lib/Dependencies.d.ts +10 -0
- package/lib/Dependencies.d.ts.map +1 -0
- package/lib/Dependencies.js +1 -0
- package/lib/Dependencies.js.map +1 -0
- package/lib/Deploy.d.ts +2 -1
- package/lib/Deploy.d.ts.map +1 -1
- package/lib/Deploy.js +2 -2
- package/lib/Deploy.js.map +1 -1
- package/lib/Diff.d.ts +11 -0
- package/lib/Diff.d.ts.map +1 -1
- package/lib/Diff.js +11 -0
- package/lib/Diff.js.map +1 -1
- package/lib/Input.d.ts +2 -1
- package/lib/Input.d.ts.map +1 -1
- package/lib/KeyPair.d.ts +77 -0
- package/lib/KeyPair.d.ts.map +1 -0
- package/lib/KeyPair.js +102 -0
- package/lib/KeyPair.js.map +1 -0
- package/lib/Local/RpcProvider.d.ts +3 -1
- package/lib/Local/RpcProvider.d.ts.map +1 -1
- package/lib/Local/RpcProvider.js +28 -2
- package/lib/Local/RpcProvider.js.map +1 -1
- package/lib/Local/RpcServerEnvironment.js +1 -1
- package/lib/Local/RpcServerEnvironment.js.map +1 -1
- package/lib/Neon/Project.d.ts.map +1 -1
- package/lib/Neon/Project.js +14 -3
- package/lib/Neon/Project.js.map +1 -1
- package/lib/Output.d.ts.map +1 -1
- package/lib/Output.js +9 -2
- package/lib/Output.js.map +1 -1
- package/lib/Phase.d.ts +2 -1
- package/lib/Phase.d.ts.map +1 -1
- package/lib/Phase.js +6 -1
- package/lib/Phase.js.map +1 -1
- package/lib/Plan.d.ts.map +1 -1
- package/lib/Plan.js +14 -3
- package/lib/Plan.js.map +1 -1
- package/lib/Platform.d.ts +8 -6
- package/lib/Platform.d.ts.map +1 -1
- package/lib/Platform.js +33 -3
- package/lib/Platform.js.map +1 -1
- package/lib/Random.d.ts.map +1 -1
- package/lib/Random.js +9 -14
- package/lib/Random.js.map +1 -1
- package/lib/RuntimeContext.d.ts +21 -1
- package/lib/RuntimeContext.d.ts.map +1 -1
- package/lib/RuntimeContext.js +12 -0
- package/lib/RuntimeContext.js.map +1 -1
- package/lib/Stack.d.ts +3 -3
- package/lib/Stack.d.ts.map +1 -1
- package/lib/Stack.js.map +1 -1
- package/lib/State/HttpStateApi.d.ts +2 -2
- package/lib/State/HttpStateStore.d.ts +4 -0
- package/lib/State/HttpStateStore.d.ts.map +1 -1
- package/lib/State/HttpStateStore.js +13 -0
- package/lib/State/HttpStateStore.js.map +1 -1
- package/lib/State/StateEncoding.d.ts +8 -0
- package/lib/State/StateEncoding.d.ts.map +1 -1
- package/lib/State/StateEncoding.js +55 -5
- package/lib/State/StateEncoding.js.map +1 -1
- package/lib/Test/Bun.d.ts.map +1 -1
- package/lib/Test/Bun.js +0 -2
- package/lib/Test/Bun.js.map +1 -1
- package/lib/Test/Vitest.d.ts.map +1 -1
- package/lib/Test/Vitest.js +0 -2
- package/lib/Test/Vitest.js.map +1 -1
- package/lib/Util/Duration.d.ts +14 -0
- package/lib/Util/Duration.d.ts.map +1 -0
- package/lib/Util/Duration.js +18 -0
- package/lib/Util/Duration.js.map +1 -0
- package/lib/Util/index.d.ts +0 -6
- package/lib/Util/index.d.ts.map +1 -1
- package/lib/Util/index.js +0 -6
- package/lib/Util/index.js.map +1 -1
- package/lib/Util/poll.d.ts +30 -0
- package/lib/Util/poll.d.ts.map +1 -0
- package/lib/Util/poll.js +26 -0
- package/lib/Util/poll.js.map +1 -0
- package/lib/Util/types.d.ts +3 -1
- package/lib/Util/types.d.ts.map +1 -1
- package/lib/Util/types.js +5 -1
- package/lib/Util/types.js.map +1 -1
- package/lib/index.d.ts +2 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -3
- package/lib/index.js.map +1 -1
- package/lib/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +20 -19
- package/src/AWS/Lambda/Function.ts +87 -34
- package/src/AWS/Providers.ts +3 -0
- package/src/AlchemyContext.ts +0 -1
- package/src/Apply.ts +18 -1
- package/src/Auth/AuthProvider.ts +25 -5
- package/src/Auth/Credentials.ts +8 -7
- package/src/Cli/commands/_shared.ts +47 -4
- package/src/Cli/commands/cloudflare.ts +5 -3
- package/src/Cli/commands/dev.ts +13 -1
- package/src/Cli/commands/login.ts +20 -4
- package/src/Cli/commands/profile.ts +24 -34
- package/src/Cli/main.ts +0 -3
- package/src/Cloudflare/AiGateway/AiGateway.ts +2 -6
- package/src/Cloudflare/BrowserRendering/BrowserRendering.ts +132 -0
- package/src/Cloudflare/BrowserRendering/BrowserRenderingBinding.ts +137 -0
- package/src/Cloudflare/BrowserRendering/index.ts +11 -0
- package/src/Cloudflare/Container/Container.ts +3 -3
- package/src/Cloudflare/Container/StartContainer.ts +1 -2
- package/src/Cloudflare/D1/D1Database.ts +4 -1
- package/src/Cloudflare/D1/D1DatabaseBinding.ts +1 -1
- package/src/Cloudflare/Fetcher.ts +0 -2
- package/src/Cloudflare/Hyperdrive/Hyperdrive.ts +5 -0
- package/src/Cloudflare/Hyperdrive/HyperdriveBinding.ts +41 -43
- package/src/Cloudflare/KV/KVNamespace.ts +4 -0
- package/src/Cloudflare/Local.ts +1 -1
- package/src/Cloudflare/Providers.ts +32 -16
- package/src/Cloudflare/Queue/Queue.ts +3 -0
- package/src/Cloudflare/Queue/QueueConsumer.ts +21 -8
- package/src/Cloudflare/Queue/QueueEventSource.ts +33 -5
- package/src/Cloudflare/R2/R2Bucket.ts +26 -0
- package/src/Cloudflare/SecretsStore/Secret.ts +14 -41
- package/src/Cloudflare/SecretsStore/SecretBinding.ts +11 -11
- package/src/Cloudflare/StateStore/Api.ts +15 -15
- package/src/Cloudflare/StateStore/State.ts +468 -468
- package/src/Cloudflare/StateStore/Store.ts +27 -37
- package/src/Cloudflare/Vectorize/VectorizeIndex.ts +261 -0
- package/src/Cloudflare/Vectorize/VectorizeIndexBinding.ts +103 -0
- package/src/Cloudflare/Vectorize/VectorizeMetadataIndex.ts +208 -0
- package/src/Cloudflare/Vectorize/index.ts +3 -0
- package/src/Cloudflare/VpcService/VpcService.ts +2 -2
- package/src/Cloudflare/Website/StaticSite.ts +8 -10
- package/src/Cloudflare/Website/Vite.ts +4 -7
- package/src/Cloudflare/Workers/Assets.ts +1 -1
- package/src/Cloudflare/Workers/DurableObjectBridge.ts +7 -4
- package/src/Cloudflare/Workers/DurableObjectNamespace.ts +380 -121
- package/src/Cloudflare/Workers/HttpServer.ts +31 -25
- package/src/Cloudflare/Workers/InferEnv.ts +15 -8
- package/src/Cloudflare/Workers/LocalWorkerProvider.ts +139 -78
- package/src/Cloudflare/Workers/Rpc.ts +50 -0
- package/src/Cloudflare/Workers/RpcDurableObjectNamespace.ts +502 -0
- package/src/Cloudflare/Workers/RpcWorker.ts +562 -0
- package/src/Cloudflare/Workers/Vite.ts +2 -0
- package/src/Cloudflare/Workers/Worker.ts +274 -93
- package/src/Cloudflare/Workers/WorkerAsyncBindings.ts +165 -103
- package/src/Cloudflare/Workers/WorkerBinding.ts +12 -0
- package/src/Cloudflare/Workers/WorkerBridge.ts +7 -4
- package/src/Cloudflare/Workers/WorkerBundle.ts +4 -1
- package/src/Cloudflare/Workers/WorkerRuntimeContext.ts +8 -15
- package/src/Cloudflare/Workers/Workflow.ts +22 -3
- package/src/Cloudflare/Workers/index.ts +2 -0
- package/src/Cloudflare/index.ts +2 -0
- package/src/Dependencies.ts +10 -0
- package/src/Deploy.ts +3 -1
- package/src/Diff.ts +13 -0
- package/src/Input.ts +2 -0
- package/src/KeyPair.ts +146 -0
- package/src/Local/RpcProvider.ts +45 -1
- package/src/Local/RpcServerEnvironment.ts +1 -1
- package/src/Neon/Project.ts +16 -3
- package/src/Output.ts +8 -2
- package/src/Phase.ts +8 -0
- package/src/Plan.ts +16 -3
- package/src/Platform.ts +74 -27
- package/src/Random.ts +22 -27
- package/src/RuntimeContext.ts +23 -1
- package/src/Stack.ts +3 -3
- package/src/State/HttpStateStore.ts +28 -0
- package/src/State/StateEncoding.ts +58 -7
- package/src/Test/Bun.ts +0 -3
- package/src/Test/Vitest.ts +0 -3
- package/src/Util/Duration.ts +21 -0
- package/src/Util/index.ts +0 -6
- package/src/Util/poll.ts +47 -0
- package/src/Util/types.ts +9 -2
- package/src/index.ts +2 -3
- package/lib/Secret.d.ts +0 -50
- package/lib/Secret.d.ts.map +0 -1
- package/lib/Secret.js +0 -23
- package/lib/Secret.js.map +0 -1
- package/lib/Trait.d.ts +0 -43
- package/lib/Trait.d.ts.map +0 -1
- package/lib/Trait.js +0 -17
- package/lib/Trait.js.map +0 -1
- package/lib/Util/LocalhostDns.d.ts +0 -23
- package/lib/Util/LocalhostDns.d.ts.map +0 -1
- package/lib/Util/LocalhostDns.js +0 -46
- package/lib/Util/LocalhostDns.js.map +0 -1
- package/lib/Util/assert-never.d.ts +0 -12
- package/lib/Util/assert-never.d.ts.map +0 -1
- package/lib/Util/assert-never.js +0 -11
- package/lib/Util/assert-never.js.map +0 -1
- package/lib/Util/class.d.ts +0 -3
- package/lib/Util/class.d.ts.map +0 -1
- package/lib/Util/class.js +0 -1
- package/lib/Util/class.js.map +0 -1
- package/lib/Util/ignore.d.ts +0 -40
- package/lib/Util/ignore.d.ts.map +0 -1
- package/lib/Util/ignore.js +0 -591
- package/lib/Util/ignore.js.map +0 -1
- package/lib/Util/instance.d.ts +0 -4
- package/lib/Util/instance.d.ts.map +0 -1
- package/lib/Util/instance.js +0 -1
- package/lib/Util/instance.js.map +0 -1
- package/lib/Util/pointer.d.ts +0 -5
- package/lib/Util/pointer.d.ts.map +0 -1
- package/lib/Util/pointer.js +0 -1
- package/lib/Util/pointer.js.map +0 -1
- package/lib/Util/schema-to-type.d.ts +0 -42
- package/lib/Util/schema-to-type.d.ts.map +0 -1
- package/lib/Util/schema-to-type.js +0 -364
- package/lib/Util/schema-to-type.js.map +0 -1
- package/lib/Util/todo.d.ts +0 -3
- package/lib/Util/todo.d.ts.map +0 -1
- package/lib/Util/todo.js +0 -3
- package/lib/Util/todo.js.map +0 -1
- package/lib/Variable.d.ts +0 -29
- package/lib/Variable.d.ts.map +0 -1
- package/lib/Variable.js +0 -9
- package/lib/Variable.js.map +0 -1
- package/src/Secret.ts +0 -87
- package/src/Trait.ts +0 -105
- package/src/Util/LocalhostDns.ts +0 -52
- package/src/Util/assert-never.ts +0 -18
- package/src/Util/class.ts +0 -7
- package/src/Util/ignore.ts +0 -815
- package/src/Util/instance.ts +0 -9
- package/src/Util/pointer.ts +0 -5
- package/src/Util/schema-to-type.ts +0 -456
- package/src/Util/todo.ts +0 -4
- package/src/Variable.ts +0 -44
package/src/KeyPair.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import * as NodeCrypto from "node:crypto";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Redacted from "effect/Redacted";
|
|
4
|
+
import * as Provider from "./Provider.ts";
|
|
5
|
+
import { Resource } from "./Resource.ts";
|
|
6
|
+
|
|
7
|
+
export type KeyPairAlgorithm = "ed25519" | "rsa" | "ec";
|
|
8
|
+
|
|
9
|
+
export interface KeyPairProps {
|
|
10
|
+
/**
|
|
11
|
+
* Key algorithm used to generate the pair.
|
|
12
|
+
* @default "ed25519"
|
|
13
|
+
*/
|
|
14
|
+
algorithm?: KeyPairAlgorithm;
|
|
15
|
+
/**
|
|
16
|
+
* Modulus length in bits. Only used when {@link algorithm} is `"rsa"`.
|
|
17
|
+
* @default 2048
|
|
18
|
+
*/
|
|
19
|
+
modulusLength?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Named curve. Only used when {@link algorithm} is `"ec"`.
|
|
22
|
+
* @default "P-256"
|
|
23
|
+
*/
|
|
24
|
+
namedCurve?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type KeyPair = Resource<
|
|
28
|
+
"Alchemy.KeyPair",
|
|
29
|
+
KeyPairProps,
|
|
30
|
+
{
|
|
31
|
+
algorithm: KeyPairAlgorithm;
|
|
32
|
+
privateKey: Redacted.Redacted<string>;
|
|
33
|
+
publicKey: string;
|
|
34
|
+
}
|
|
35
|
+
>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A deterministic-in-state public/private keypair generator.
|
|
39
|
+
*
|
|
40
|
+
* The keypair is generated once on first reconcile and then persisted in
|
|
41
|
+
* state so subsequent deploys keep the same keys unless the resource is
|
|
42
|
+
* replaced. `privateKey` is PEM-encoded `pkcs8` and `publicKey` is
|
|
43
|
+
* PEM-encoded `spki`.
|
|
44
|
+
*
|
|
45
|
+
* @resource
|
|
46
|
+
*
|
|
47
|
+
* @section Generating a Keypair
|
|
48
|
+
* @example Default ed25519 keypair
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const keys = yield* KeyPair("signing-key");
|
|
51
|
+
* // keys.privateKey: Redacted<string> (PEM pkcs8)
|
|
52
|
+
* // keys.publicKey: string (PEM spki)
|
|
53
|
+
* // keys.algorithm: "ed25519"
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @example RSA keypair
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const keys = yield* KeyPair("rsa-key", {
|
|
59
|
+
* algorithm: "rsa",
|
|
60
|
+
* modulusLength: 2048,
|
|
61
|
+
* });
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @example EC keypair on a named curve
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const keys = yield* KeyPair("ec-key", {
|
|
67
|
+
* algorithm: "ec",
|
|
68
|
+
* namedCurve: "P-256",
|
|
69
|
+
* });
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @section Consuming the Keys
|
|
73
|
+
* @example Pass the private key to a Worker as a secret
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const keys = yield* KeyPair("signing-key");
|
|
76
|
+
* export const Worker = Cloudflare.Worker("Worker", {
|
|
77
|
+
* main: "./src/worker.ts",
|
|
78
|
+
* bindings: {
|
|
79
|
+
* SIGNING_KEY: keys.privateKey,
|
|
80
|
+
* PUBLIC_KEY: keys.publicKey,
|
|
81
|
+
* },
|
|
82
|
+
* });
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export const KeyPair = Resource<KeyPair>("Alchemy.KeyPair");
|
|
86
|
+
|
|
87
|
+
const pemEncoding = {
|
|
88
|
+
privateKeyEncoding: { type: "pkcs8", format: "pem" },
|
|
89
|
+
publicKeyEncoding: { type: "spki", format: "pem" },
|
|
90
|
+
} as const;
|
|
91
|
+
|
|
92
|
+
const generate = (
|
|
93
|
+
props: KeyPairProps,
|
|
94
|
+
): {
|
|
95
|
+
privateKey: string;
|
|
96
|
+
publicKey: string;
|
|
97
|
+
algorithm: KeyPairAlgorithm;
|
|
98
|
+
} => {
|
|
99
|
+
const algorithm = props.algorithm ?? "ed25519";
|
|
100
|
+
if (algorithm === "rsa") {
|
|
101
|
+
const { privateKey, publicKey } = NodeCrypto.generateKeyPairSync("rsa", {
|
|
102
|
+
modulusLength: props.modulusLength ?? 2048,
|
|
103
|
+
...pemEncoding,
|
|
104
|
+
});
|
|
105
|
+
return { algorithm, privateKey, publicKey };
|
|
106
|
+
}
|
|
107
|
+
if (algorithm === "ec") {
|
|
108
|
+
const { privateKey, publicKey } = NodeCrypto.generateKeyPairSync("ec", {
|
|
109
|
+
namedCurve: props.namedCurve ?? "P-256",
|
|
110
|
+
...pemEncoding,
|
|
111
|
+
});
|
|
112
|
+
return { algorithm, privateKey, publicKey };
|
|
113
|
+
}
|
|
114
|
+
const { privateKey, publicKey } = NodeCrypto.generateKeyPairSync(
|
|
115
|
+
"ed25519",
|
|
116
|
+
pemEncoding,
|
|
117
|
+
);
|
|
118
|
+
return { algorithm, privateKey, publicKey };
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export const KeyPairProvider = () =>
|
|
122
|
+
Provider.succeed(KeyPair, {
|
|
123
|
+
reconcile: Effect.fn(function* ({ news = {}, output }) {
|
|
124
|
+
// Observe — there is no remote state. The cached `output` is the
|
|
125
|
+
// authoritative current value; once minted the keypair is preserved
|
|
126
|
+
// across reconciles to keep it stable.
|
|
127
|
+
if (output?.privateKey && output?.publicKey) {
|
|
128
|
+
return output;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Ensure — no observed value: mint a fresh keypair. The next
|
|
132
|
+
// reconcile will see this in `output` and short-circuit above.
|
|
133
|
+
const generated = yield* Effect.sync(() => generate(news));
|
|
134
|
+
return {
|
|
135
|
+
algorithm: generated.algorithm,
|
|
136
|
+
privateKey: Redacted.make(generated.privateKey),
|
|
137
|
+
publicKey: generated.publicKey,
|
|
138
|
+
};
|
|
139
|
+
}),
|
|
140
|
+
delete: Effect.fn(function* () {
|
|
141
|
+
return undefined;
|
|
142
|
+
}),
|
|
143
|
+
read: Effect.fn(function* ({ output }) {
|
|
144
|
+
return output;
|
|
145
|
+
}),
|
|
146
|
+
});
|
package/src/Local/RpcProvider.ts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
import type * as Context from "effect/Context";
|
|
1
2
|
import * as Effect from "effect/Effect";
|
|
2
3
|
import * as Layer from "effect/Layer";
|
|
4
|
+
import * as Option from "effect/Option";
|
|
5
|
+
import * as Predicate from "effect/Predicate";
|
|
3
6
|
import type { Scope } from "effect/Scope";
|
|
7
|
+
import * as Stream from "effect/Stream";
|
|
8
|
+
import { InstanceId } from "../InstanceId.ts";
|
|
4
9
|
import type { Platform } from "../Platform.ts";
|
|
5
10
|
import * as Provider from "../Provider.ts";
|
|
6
11
|
import type { ResourceClass, ResourceLike } from "../Resource.ts";
|
|
12
|
+
import { Stack } from "../Stack.ts";
|
|
13
|
+
import { Stage } from "../Stage.ts";
|
|
7
14
|
import { RpcProviderProxy } from "./RpcProviderProxy.ts";
|
|
8
15
|
|
|
9
16
|
/**
|
|
@@ -69,11 +76,48 @@ export const effect = <
|
|
|
69
76
|
cls,
|
|
70
77
|
Effect.gen(function* () {
|
|
71
78
|
const client = yield* Effect.serviceOption(RpcProviderProxy);
|
|
72
|
-
|
|
79
|
+
const stack = yield* Stack;
|
|
80
|
+
|
|
81
|
+
if (client._tag === "None") {
|
|
82
|
+
const provider = yield* eff;
|
|
83
|
+
return new Proxy(provider, {
|
|
84
|
+
get: (target, prop) => {
|
|
85
|
+
const value = (target as any)[prop];
|
|
86
|
+
if (!Predicate.isFunction(value)) return value;
|
|
87
|
+
return (...args: any[]) => {
|
|
88
|
+
const result = value(...args);
|
|
89
|
+
const services = Layer.mergeAll(
|
|
90
|
+
layerFallback(Stack, stack),
|
|
91
|
+
layerFallback(Stage, stack.stage),
|
|
92
|
+
Predicate.hasProperty(args[0], "instanceId") &&
|
|
93
|
+
Predicate.isString(args[0].instanceId)
|
|
94
|
+
? layerFallback(InstanceId, args[0].instanceId)
|
|
95
|
+
: Layer.empty,
|
|
96
|
+
);
|
|
97
|
+
return result.pipe(
|
|
98
|
+
Stream.isStream(result)
|
|
99
|
+
? Stream.provide(services)
|
|
100
|
+
: Effect.provide(services),
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
73
106
|
return yield* client.value.get(serverEntryUrl, cls.Type);
|
|
74
107
|
}),
|
|
75
108
|
);
|
|
76
109
|
|
|
110
|
+
const layerFallback = <I, S>(
|
|
111
|
+
service: Context.Key<I, S>,
|
|
112
|
+
defaultValue: NoInfer<S>,
|
|
113
|
+
) =>
|
|
114
|
+
Layer.effect(
|
|
115
|
+
service,
|
|
116
|
+
Effect.serviceOption(service).pipe(
|
|
117
|
+
Effect.map(Option.getOrElse(() => defaultValue)),
|
|
118
|
+
),
|
|
119
|
+
);
|
|
120
|
+
|
|
77
121
|
/**
|
|
78
122
|
* Conditionally constructs a layer for use by an RpcProvider.
|
|
79
123
|
* If the {@link RpcProviderProxy} is present in context, the layer is empty because it will not be used in this process.
|
|
@@ -29,7 +29,7 @@ export const layer = (environment: RpcServerEnvironment) =>
|
|
|
29
29
|
CredentialsStoreLive,
|
|
30
30
|
Layer.succeed(AuthProviders, {}),
|
|
31
31
|
ConfigProvider.layer(
|
|
32
|
-
loadConfigProvider(Option.
|
|
32
|
+
loadConfigProvider(Option.fromNullishOr(environment.envFile)).pipe(
|
|
33
33
|
Effect.map((base) => withProfileOverride(base, environment.profile)),
|
|
34
34
|
),
|
|
35
35
|
),
|
package/src/Neon/Project.ts
CHANGED
|
@@ -136,7 +136,7 @@ const findProjectByName = (name: string) =>
|
|
|
136
136
|
Effect.gen(function* () {
|
|
137
137
|
const matches: ListProjectsOutput["projects"][number][] = [];
|
|
138
138
|
let cursor: string | undefined;
|
|
139
|
-
|
|
139
|
+
while (true) {
|
|
140
140
|
const page = yield* listProjects({
|
|
141
141
|
search: name,
|
|
142
142
|
...(cursor !== undefined ? { cursor } : {}),
|
|
@@ -144,8 +144,21 @@ const findProjectByName = (name: string) =>
|
|
|
144
144
|
for (const p of page.projects) {
|
|
145
145
|
if (p.name === name) matches.push(p);
|
|
146
146
|
}
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
const nextCursor = page.pagination?.cursor;
|
|
148
|
+
// Neon returns a `pagination.cursor` on every response — it's the
|
|
149
|
+
// `created_at` of the last row, not a "has next page" flag — so we
|
|
150
|
+
// can't loop on cursor presence alone or we spin forever re-fetching
|
|
151
|
+
// empty/identical pages. Stop once a page comes back empty or the
|
|
152
|
+
// cursor stops advancing.
|
|
153
|
+
if (
|
|
154
|
+
page.projects.length === 0 ||
|
|
155
|
+
nextCursor === undefined ||
|
|
156
|
+
nextCursor === cursor
|
|
157
|
+
) {
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
cursor = nextCursor;
|
|
161
|
+
}
|
|
149
162
|
return matches;
|
|
150
163
|
});
|
|
151
164
|
|
package/src/Output.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as Data from "effect/Data";
|
|
2
|
+
import * as Duration from "effect/Duration";
|
|
2
3
|
import * as Effect from "effect/Effect";
|
|
3
4
|
import { pipe } from "effect/Function";
|
|
4
5
|
import type { Pipeable } from "effect/Pipeable";
|
|
@@ -6,7 +7,7 @@ import * as Redacted from "effect/Redacted";
|
|
|
6
7
|
import { SingleShotGen } from "effect/Utils";
|
|
7
8
|
import { getRefMetadata, isRef, type Ref } from "./Ref.ts";
|
|
8
9
|
import { isResource, type Resource, type ResourceLike } from "./Resource.ts";
|
|
9
|
-
import { RuntimeContext } from "./RuntimeContext.ts";
|
|
10
|
+
import { RuntimeContext, sanitizeKey } from "./RuntimeContext.ts";
|
|
10
11
|
import { Stack } from "./Stack.ts";
|
|
11
12
|
import { Stage } from "./Stage.ts";
|
|
12
13
|
import * as State from "./State/State.ts";
|
|
@@ -112,9 +113,11 @@ export abstract class BaseExpr<A = any, Req = any> implements Output<A, Req> {
|
|
|
112
113
|
}
|
|
113
114
|
|
|
114
115
|
public bind(id: string): any {
|
|
116
|
+
// `set`/`get` store keys verbatim, so canonicalize here (the caller's job).
|
|
117
|
+
const key = sanitizeKey(id);
|
|
115
118
|
return RuntimeContext.pipe(
|
|
116
119
|
Effect.flatMap((ctx) =>
|
|
117
|
-
Effect.map(ctx.set(
|
|
120
|
+
Effect.map(ctx.set(key, this), (k) => ctx.get<A>(k)),
|
|
118
121
|
),
|
|
119
122
|
);
|
|
120
123
|
}
|
|
@@ -590,6 +593,9 @@ export const evaluate: <A, Req = never>(
|
|
|
590
593
|
return yield* Effect.all(expr.map((item) => evaluate(item, upstream)));
|
|
591
594
|
} else if (Redacted.isRedacted(expr)) {
|
|
592
595
|
return expr;
|
|
596
|
+
} else if (Duration.isDuration(expr)) {
|
|
597
|
+
// Opaque value — see resolveInput in Plan.ts for rationale.
|
|
598
|
+
return expr;
|
|
593
599
|
} else if (typeof expr === "object" && expr !== null) {
|
|
594
600
|
return Object.fromEntries(
|
|
595
601
|
yield* Effect.all(
|
package/src/Phase.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import * as Config from "effect/Config";
|
|
2
2
|
import * as Effect from "effect/Effect";
|
|
3
3
|
|
|
4
|
+
export type AlchemyPhase = "plan" | "runtime";
|
|
5
|
+
|
|
4
6
|
export const ALCHEMY_PHASE = Config.string("ALCHEMY_PHASE").pipe(
|
|
5
7
|
Config.withDefault("plan"),
|
|
8
|
+
Config.mapOrFail((value) => {
|
|
9
|
+
if (value !== "plan" && value !== "runtime") {
|
|
10
|
+
return Effect.die(new Error(`Invalid ALCHEMY_PHASE: ${value}`));
|
|
11
|
+
}
|
|
12
|
+
return Effect.succeed(value as AlchemyPhase);
|
|
13
|
+
}),
|
|
6
14
|
Effect.orDie,
|
|
7
15
|
);
|
package/src/Plan.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as Data from "effect/Data";
|
|
2
|
+
import * as Duration from "effect/Duration";
|
|
2
3
|
import * as Effect from "effect/Effect";
|
|
3
4
|
import * as Option from "effect/Option";
|
|
4
5
|
import * as Redacted from "effect/Redacted";
|
|
@@ -18,6 +19,7 @@ import {
|
|
|
18
19
|
makeScopedArtifacts,
|
|
19
20
|
} from "./Artifacts.ts";
|
|
20
21
|
import {
|
|
22
|
+
dedupeBindings,
|
|
21
23
|
diffBindings,
|
|
22
24
|
havePropsChanged,
|
|
23
25
|
isResolved,
|
|
@@ -309,7 +311,11 @@ export const make = <A>(
|
|
|
309
311
|
: oldState.props;
|
|
310
312
|
|
|
311
313
|
const oldBindings = oldState.bindings ?? [];
|
|
312
|
-
|
|
314
|
+
// Collapse duplicate bindings by sid so the binding set handed to
|
|
315
|
+
// `diff` matches what `reconcile` receives (see `dedupeBindings`).
|
|
316
|
+
const newBindings = dedupeBindings(
|
|
317
|
+
stack.bindings[resource.FQN] ?? [],
|
|
318
|
+
);
|
|
313
319
|
|
|
314
320
|
const diff = yield* provider.diff
|
|
315
321
|
? provider
|
|
@@ -375,6 +381,11 @@ export const make = <A>(
|
|
|
375
381
|
return yield* resolveOutput(input);
|
|
376
382
|
} else if (Redacted.isRedacted(input)) {
|
|
377
383
|
return input;
|
|
384
|
+
} else if (Duration.isDuration(input)) {
|
|
385
|
+
// Duration is an opaque value; walking its internal `.value`
|
|
386
|
+
// would destroy the prototype and produce a plain `{ value: ... }`
|
|
387
|
+
// object that downstream consumers can't interpret.
|
|
388
|
+
return input;
|
|
378
389
|
} else if (Array.isArray(input)) {
|
|
379
390
|
return yield* Effect.all(input.map(resolveInput), {
|
|
380
391
|
concurrency: "unbounded",
|
|
@@ -627,8 +638,10 @@ export const make = <A>(
|
|
|
627
638
|
const news = yield* resolveInput(resource.Props);
|
|
628
639
|
const downstream = newDownstreamDependencies[fqn] ?? [];
|
|
629
640
|
|
|
630
|
-
|
|
631
|
-
|
|
641
|
+
// Collapse duplicate bindings by sid so the binding set handed to
|
|
642
|
+
// `diff` matches what `reconcile` receives (see `dedupeBindings`).
|
|
643
|
+
const newBindings: ResourceBinding[] = dedupeBindings(
|
|
644
|
+
yield* resolveInput(stack.bindings[fqn] ?? []),
|
|
632
645
|
);
|
|
633
646
|
const persisted = yield* state.get({
|
|
634
647
|
stack: stackName,
|
package/src/Platform.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as ConfigError from "effect/Config";
|
|
2
|
+
import * as ConfigProvider from "effect/ConfigProvider";
|
|
1
3
|
import * as Context from "effect/Context";
|
|
2
4
|
import * as Effect from "effect/Effect";
|
|
3
5
|
import { pipe } from "effect/Function";
|
|
@@ -7,14 +9,21 @@ import type { Scope } from "effect/Scope";
|
|
|
7
9
|
import type { HttpClient } from "effect/unstable/http/HttpClient";
|
|
8
10
|
import { SingleShotGen } from "effect/Utils";
|
|
9
11
|
import type { PolicyLike } from "./Binding.ts";
|
|
12
|
+
import type { Dependencies } from "./Dependencies.ts";
|
|
10
13
|
import type { ExecutionContext } from "./ExecutionContext.ts";
|
|
11
14
|
import type { HttpEffect } from "./Http.ts";
|
|
12
15
|
import type { InputProps } from "./Input.ts";
|
|
16
|
+
import * as Output from "./Output.ts";
|
|
13
17
|
import { ALCHEMY_PHASE } from "./Phase.ts";
|
|
14
18
|
import type { Provider, ProviderCollectionLike } from "./Provider.ts";
|
|
15
19
|
import { Resource, type ResourceLike } from "./Resource.ts";
|
|
16
20
|
import type { Rpc } from "./Rpc.ts";
|
|
17
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
CurrentRuntimeContext,
|
|
23
|
+
RuntimeContext,
|
|
24
|
+
sanitizeKey,
|
|
25
|
+
type BaseRuntimeContext,
|
|
26
|
+
} from "./RuntimeContext.ts";
|
|
18
27
|
import { Self } from "./Self.ts";
|
|
19
28
|
import type { Stack, StackServices } from "./Stack.ts";
|
|
20
29
|
import type { Stage } from "./Stage.ts";
|
|
@@ -65,19 +74,19 @@ export interface Platform<
|
|
|
65
74
|
Type: Resource["Type"];
|
|
66
75
|
Provider: Provider<Resource>;
|
|
67
76
|
|
|
68
|
-
<Self, Shape>(): {
|
|
77
|
+
<Self, Shape, Deps = never>(): {
|
|
69
78
|
<PropsReq = never>(
|
|
70
79
|
id: string,
|
|
71
80
|
props:
|
|
72
81
|
| InputProps<Resource["Props"]>
|
|
73
82
|
| Effect.Effect<InputProps<Resource["Props"]>, never, PropsReq>,
|
|
74
83
|
): Effect.Effect<
|
|
75
|
-
Resource & Rpc<Self>,
|
|
84
|
+
Resource & Rpc<Self> & Dependencies<Deps>,
|
|
76
85
|
never,
|
|
77
|
-
|
|
86
|
+
Resource["Providers"] | PropsReq
|
|
78
87
|
> & {
|
|
79
88
|
make<InitReq = never>(
|
|
80
|
-
impl: Effect.Effect<Shape,
|
|
89
|
+
impl: Effect.Effect<Shape, ConfigError.ConfigError, InitReq>,
|
|
81
90
|
): Layer.Layer<
|
|
82
91
|
Self,
|
|
83
92
|
never,
|
|
@@ -98,7 +107,7 @@ export interface Platform<
|
|
|
98
107
|
props:
|
|
99
108
|
| InputProps<Resource["Props"]>
|
|
100
109
|
| Effect.Effect<Resource["Props"], never, PropsReq>,
|
|
101
|
-
impl: Effect.Effect<Shape,
|
|
110
|
+
impl: Effect.Effect<Shape, ConfigError.ConfigError, InitReq>,
|
|
102
111
|
): Effect.Effect<
|
|
103
112
|
Resource & Rpc<Self>,
|
|
104
113
|
never,
|
|
@@ -119,7 +128,7 @@ export interface Platform<
|
|
|
119
128
|
Resource["Providers"] | PropsReq
|
|
120
129
|
> & {
|
|
121
130
|
make<InitReq extends Services | PlatformServices = never>(
|
|
122
|
-
impl: Effect.Effect<Shape,
|
|
131
|
+
impl: Effect.Effect<Shape, ConfigError.ConfigError, InitReq>,
|
|
123
132
|
): Layer.Layer<
|
|
124
133
|
Self,
|
|
125
134
|
never,
|
|
@@ -158,7 +167,7 @@ export interface Platform<
|
|
|
158
167
|
props:
|
|
159
168
|
| InputProps<Resource["Props"]>
|
|
160
169
|
| Effect.Effect<InputProps<Resource["Props"]>, never, PropsReq>,
|
|
161
|
-
impl: Effect.Effect<Shape,
|
|
170
|
+
impl: Effect.Effect<Shape, ConfigError.ConfigError, InitReq>,
|
|
162
171
|
): Effect.Effect<
|
|
163
172
|
Resource & Rpc<Shape>,
|
|
164
173
|
never,
|
|
@@ -343,28 +352,66 @@ export const Platform = <
|
|
|
343
352
|
}) ?? Effect.die("No serve handler"))
|
|
344
353
|
: Effect.void,
|
|
345
354
|
),
|
|
355
|
+
|
|
346
356
|
Effect.provide(
|
|
347
|
-
Layer.
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
357
|
+
Layer.effect(
|
|
358
|
+
ConfigProvider.ConfigProvider,
|
|
359
|
+
Effect.gen(function* () {
|
|
360
|
+
// a Config Provider that we use to intercept config lookups and bind them to the RuntimeContext
|
|
361
|
+
const configProvider =
|
|
362
|
+
yield* ConfigProvider.ConfigProvider;
|
|
363
|
+
const phase = yield* ALCHEMY_PHASE;
|
|
364
|
+
|
|
365
|
+
return ConfigProvider.make(
|
|
366
|
+
Effect.fnUntraced(function* (path) {
|
|
367
|
+
const ctx = yield* CurrentRuntimeContext;
|
|
368
|
+
// `set`/`get` store keys verbatim, so canonicalize the
|
|
369
|
+
// logical config path here (the caller's job) before
|
|
370
|
+
// handing it to the RuntimeContext.
|
|
371
|
+
const key = sanitizeKey(
|
|
372
|
+
path.map((p) => p.toString()).join("_"),
|
|
373
|
+
);
|
|
374
|
+
const node = yield* configProvider.get(path);
|
|
375
|
+
if (phase === "plan" && node) {
|
|
376
|
+
// bind it to the RuntimeContext if running in plan phase
|
|
377
|
+
const output = Output.literal(node.value);
|
|
378
|
+
yield* ctx?.set(key, output) ?? Effect.void;
|
|
379
|
+
return node;
|
|
380
|
+
} else if (phase === "runtime" && ctx) {
|
|
381
|
+
// retrieve from the RuntimeContext if running in runtime phase
|
|
382
|
+
const value = yield* ctx.get<string>(key);
|
|
383
|
+
if (value) {
|
|
384
|
+
return ConfigProvider.makeValue(value as string);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
// fallback to the config provider otherwise
|
|
388
|
+
return node;
|
|
389
|
+
}),
|
|
390
|
+
);
|
|
391
|
+
}),
|
|
392
|
+
).pipe(
|
|
393
|
+
Layer.provideMerge(
|
|
394
|
+
Layer.mergeAll(
|
|
395
|
+
Layer.succeed(Platform.Platform, runtimeContext),
|
|
396
|
+
Layer.succeed(PlatformContext, runtimeContext),
|
|
397
|
+
Layer.succeed(RuntimeContext, runtimeContext),
|
|
398
|
+
Layer.succeed(resource.Self, instance),
|
|
399
|
+
Layer.succeed(Platform.Self, instance),
|
|
400
|
+
Layer.succeed(Self, instance),
|
|
401
|
+
runtimeContext.planServices
|
|
402
|
+
? Layer.unwrap(
|
|
403
|
+
ALCHEMY_PHASE.pipe(
|
|
404
|
+
Effect.map((phase) =>
|
|
405
|
+
phase === "plan"
|
|
406
|
+
? runtimeContext.planServices!
|
|
407
|
+
: Layer.empty,
|
|
408
|
+
),
|
|
362
409
|
),
|
|
363
|
-
)
|
|
364
|
-
|
|
365
|
-
|
|
410
|
+
)
|
|
411
|
+
: Layer.empty,
|
|
412
|
+
),
|
|
366
413
|
),
|
|
367
|
-
Layer.succeedContext(outerServices),
|
|
414
|
+
Layer.provideMerge(Layer.succeedContext(outerServices)),
|
|
368
415
|
),
|
|
369
416
|
),
|
|
370
417
|
);
|
package/src/Random.ts
CHANGED
|
@@ -32,34 +32,29 @@ export const Random = Resource<Random>("Alchemy.Random");
|
|
|
32
32
|
|
|
33
33
|
export const RandomProvider = () =>
|
|
34
34
|
Provider.succeed(Random, {
|
|
35
|
-
reconcile:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
reconcile: ({ news = {}, output }) =>
|
|
36
|
+
Effect.sync(() => {
|
|
37
|
+
// Observe — there is no remote state. The cached `output.text` is
|
|
38
|
+
// the authoritative current value; once minted it is preserved
|
|
39
|
+
// across reconciles to keep the secret stable.
|
|
40
|
+
if (output?.text) {
|
|
41
|
+
return output;
|
|
42
|
+
}
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const text = yield* Effect.sync(() => {
|
|
44
|
+
// Ensure — no observed value: mint a fresh random secret and
|
|
45
|
+
// return it. The next reconcile will see this in `output` and
|
|
46
|
+
// short-circuit above.
|
|
47
|
+
const byteLength = news.bytes ?? 32;
|
|
48
48
|
const bytes = new Uint8Array(byteLength);
|
|
49
49
|
crypto.getRandomValues(bytes);
|
|
50
|
-
return
|
|
51
|
-
|
|
52
|
-
.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return undefined;
|
|
61
|
-
}),
|
|
62
|
-
read: Effect.fn(function* ({ output }) {
|
|
63
|
-
return output;
|
|
64
|
-
}),
|
|
50
|
+
return {
|
|
51
|
+
text: Redacted.make(
|
|
52
|
+
Array.from(bytes)
|
|
53
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
54
|
+
.join(""),
|
|
55
|
+
),
|
|
56
|
+
};
|
|
57
|
+
}),
|
|
58
|
+
delete: () => Effect.void,
|
|
59
|
+
read: ({ output }) => Effect.succeed(output),
|
|
65
60
|
});
|
package/src/RuntimeContext.ts
CHANGED
|
@@ -9,7 +9,15 @@ export interface BaseRuntimeContext {
|
|
|
9
9
|
Type: string;
|
|
10
10
|
id: string;
|
|
11
11
|
env: Record<string, any>;
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Read a value by its (already-canonical) key. The key is used verbatim;
|
|
14
|
+
* callers must {@link sanitizeKey} first. See {@link sanitizeKey}.
|
|
15
|
+
*/
|
|
16
|
+
get<T>(key: string): Effect.Effect<T | undefined>;
|
|
17
|
+
/**
|
|
18
|
+
* Store an output under the given (already-canonical) key, returning the key.
|
|
19
|
+
* The key is used verbatim; callers must {@link sanitizeKey} first.
|
|
20
|
+
*/
|
|
13
21
|
set(id: string, output: Output): Effect.Effect<string>;
|
|
14
22
|
exports?: Effect.Effect<Record<string, any>>;
|
|
15
23
|
serve?<Req = never>(
|
|
@@ -21,6 +29,20 @@ export interface BaseRuntimeContext {
|
|
|
21
29
|
planServices?: Layer.Layer<any>;
|
|
22
30
|
}
|
|
23
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Canonicalize a logical key into a key that is safe to use as the name of an
|
|
34
|
+
* environment variable / binding (`[a-zA-Z][a-zA-Z0-9_]*`).
|
|
35
|
+
*
|
|
36
|
+
* `RuntimeContext.set`/`get` are dumb key/value stores: they read and write the
|
|
37
|
+
* key **verbatim**. It is the *caller's* responsibility to hand them a
|
|
38
|
+
* canonical key, since the caller is the one that knows the logical key may
|
|
39
|
+
* contain `.`/`-` (e.g. a dotted config name from `Platform`, or an
|
|
40
|
+
* `Output.toString()` like `"QueueSinkQueue.queueUrl"`). Callers run the key
|
|
41
|
+
* through this before calling `set`/`get` so both sides agree.
|
|
42
|
+
*/
|
|
43
|
+
export const sanitizeKey = (key: string): string =>
|
|
44
|
+
key.replaceAll(/[^a-zA-Z0-9]/g, "_");
|
|
45
|
+
|
|
24
46
|
/**
|
|
25
47
|
* Context of the runtime environment.
|
|
26
48
|
*
|
package/src/Stack.ts
CHANGED
|
@@ -10,6 +10,7 @@ import * as Scope from "effect/Scope";
|
|
|
10
10
|
import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
|
|
11
11
|
import type { HttpClient } from "effect/unstable/http/HttpClient";
|
|
12
12
|
import type { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner";
|
|
13
|
+
import type { ActionLike } from "./Action.ts";
|
|
13
14
|
import { AlchemyContext, AlchemyContextLive } from "./AlchemyContext.ts";
|
|
14
15
|
import { provideFreshArtifactStore } from "./Artifacts.ts";
|
|
15
16
|
import { AuthProviders } from "./Auth/AuthProvider.ts";
|
|
@@ -20,7 +21,6 @@ import type { Input, InputProps } from "./Input.ts";
|
|
|
20
21
|
import * as Output from "./Output.ts";
|
|
21
22
|
import type { ResourceBinding, ResourceLike } from "./Resource.ts";
|
|
22
23
|
import { Stage } from "./Stage.ts";
|
|
23
|
-
import type { ActionLike } from "./Action.ts";
|
|
24
24
|
import type { State } from "./State/State.ts";
|
|
25
25
|
import { loadConfigProvider } from "./Util/ConfigProvider.ts";
|
|
26
26
|
import { effectClass, taggedFunction } from "./Util/effect.ts";
|
|
@@ -291,8 +291,8 @@ const alchemy = (overrides?: { dev?: boolean }) =>
|
|
|
291
291
|
: AlchemyContextLive,
|
|
292
292
|
);
|
|
293
293
|
|
|
294
|
-
export const evalStack = <A, B, Err, Req>(
|
|
295
|
-
effect: StackEffect<CompiledStack<A>, Stage | AlchemyContext>,
|
|
294
|
+
export const evalStack = <A, B, StackErr, Err, Req>(
|
|
295
|
+
effect: StackEffect<CompiledStack<A>, StackErr, Stage | AlchemyContext>,
|
|
296
296
|
fn: (stack: CompiledStack<A>) => Effect.Effect<B, Err, Req>,
|
|
297
297
|
options: {
|
|
298
298
|
stage: string;
|