alchemy 2.0.0-beta.44 → 2.0.0-beta.45
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/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/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 +21 -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 +11 -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.map +1 -1
- package/lib/Cloudflare/StateStore/State.js +45 -9
- 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 +5 -2
- package/lib/Cloudflare/StateStore/Store.js.map +1 -1
- 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 +158 -97
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBinding.d.ts +11 -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 +1 -0
- package/lib/Cloudflare/index.d.ts.map +1 -1
- package/lib/Cloudflare/index.js +1 -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/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/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/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/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 +25 -16
- package/src/Cloudflare/Queue/Queue.ts +3 -0
- package/src/Cloudflare/Queue/QueueConsumer.ts +23 -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 +68 -6
- package/src/Cloudflare/StateStore/Store.ts +5 -2
- 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 +158 -103
- package/src/Cloudflare/Workers/WorkerBinding.ts +10 -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 +1 -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/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/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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as queues from "@distilled.cloud/cloudflare/queues";
|
|
2
|
+
import * as Console from "effect/Console";
|
|
2
3
|
import * as Effect from "effect/Effect";
|
|
3
4
|
import * as Option from "effect/Option";
|
|
4
5
|
import * as Schedule from "effect/Schedule";
|
|
@@ -118,11 +119,11 @@ type ObservedConsumer = {
|
|
|
118
119
|
|
|
119
120
|
const toObserved = (c: {
|
|
120
121
|
consumerId?: string | null;
|
|
121
|
-
|
|
122
|
+
scriptName?: string | null;
|
|
122
123
|
type?: "worker" | "http_pull" | null;
|
|
123
124
|
}): ObservedConsumer | undefined =>
|
|
124
125
|
c.consumerId && c.type === "worker"
|
|
125
|
-
? { consumerId: c.consumerId, script: c.
|
|
126
|
+
? { consumerId: c.consumerId, script: c.scriptName ?? undefined }
|
|
126
127
|
: undefined;
|
|
127
128
|
|
|
128
129
|
export const QueueConsumerProvider = () =>
|
|
@@ -139,10 +140,7 @@ export const QueueConsumerProvider = () =>
|
|
|
139
140
|
// first match in the paginated stream is the only one. Using
|
|
140
141
|
// `.items` defeats single-page lookups that would otherwise
|
|
141
142
|
// miss late-arriving consumers under eventual consistency.
|
|
142
|
-
const findWorkerConsumer = (
|
|
143
|
-
acct: string,
|
|
144
|
-
queueId: string,
|
|
145
|
-
): Effect.Effect<ObservedConsumer | undefined, any, any> =>
|
|
143
|
+
const findWorkerConsumer = (acct: string, queueId: string) =>
|
|
146
144
|
queues.listConsumers.items({ accountId: acct, queueId }).pipe(
|
|
147
145
|
Stream.map(toObserved),
|
|
148
146
|
Stream.filter((c): c is ObservedConsumer => c !== undefined),
|
|
@@ -367,6 +365,22 @@ export const QueueConsumerProvider = () =>
|
|
|
367
365
|
}),
|
|
368
366
|
);
|
|
369
367
|
|
|
368
|
+
yield* getConsumer({ accountId: acct, queueId, consumerId }).pipe(
|
|
369
|
+
Effect.tap(Console.log),
|
|
370
|
+
Effect.flatMap((fetched) =>
|
|
371
|
+
toObserved(fetched)?.script === news.scriptName
|
|
372
|
+
? Effect.void
|
|
373
|
+
: Effect.fail("ScriptUnbound" as const),
|
|
374
|
+
),
|
|
375
|
+
Effect.catchTag("ConsumerNotFound", () =>
|
|
376
|
+
Effect.fail("ScriptUnbound" as const),
|
|
377
|
+
),
|
|
378
|
+
Effect.retry({
|
|
379
|
+
while: (e) => e === "ScriptUnbound",
|
|
380
|
+
schedule: queueHandlerReadinessSchedule,
|
|
381
|
+
}),
|
|
382
|
+
);
|
|
383
|
+
|
|
370
384
|
return {
|
|
371
385
|
consumerId,
|
|
372
386
|
queueId,
|
|
@@ -418,8 +432,9 @@ export const QueueConsumerProvider = () =>
|
|
|
418
432
|
consumerId: fetched.consumerId!,
|
|
419
433
|
queueId: output.queueId,
|
|
420
434
|
scriptName:
|
|
421
|
-
("
|
|
422
|
-
|
|
435
|
+
("scriptName" in fetched &&
|
|
436
|
+
typeof fetched.scriptName === "string"
|
|
437
|
+
? fetched.scriptName
|
|
423
438
|
: output.scriptName) ?? output.scriptName,
|
|
424
439
|
accountId: output.accountId,
|
|
425
440
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type * as cf from "@cloudflare/workers-types";
|
|
2
2
|
import * as Cause from "effect/Cause";
|
|
3
3
|
import * as Context from "effect/Context";
|
|
4
|
+
import * as Duration from "effect/Duration";
|
|
4
5
|
import * as Effect from "effect/Effect";
|
|
5
6
|
import * as Layer from "effect/Layer";
|
|
6
7
|
import * as Stream from "effect/Stream";
|
|
@@ -8,6 +9,7 @@ import * as Binding from "../../Binding.ts";
|
|
|
8
9
|
import type { ResourceLike } from "../../Resource.ts";
|
|
9
10
|
import { RuntimeContext } from "../../RuntimeContext.ts";
|
|
10
11
|
import type { FunctionContext } from "../../Serverless/Function.ts";
|
|
12
|
+
import * as DurationUtil from "../../Util/Duration.ts";
|
|
11
13
|
import { isWorker, isWorkerEvent } from "../Workers/Worker.ts";
|
|
12
14
|
import type { Queue } from "./Queue.ts";
|
|
13
15
|
import { QueueConsumer } from "./QueueConsumer.ts";
|
|
@@ -25,14 +27,37 @@ export interface MessagesProps {
|
|
|
25
27
|
maxConcurrency?: number;
|
|
26
28
|
/** Maximum delivery attempts before dead-lettering. */
|
|
27
29
|
maxRetries?: number;
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Wait time before flushing a partial batch. Rounded up to whole
|
|
32
|
+
* milliseconds when forwarded to Cloudflare.
|
|
33
|
+
*/
|
|
34
|
+
maxWaitTime?: Duration.Input;
|
|
35
|
+
/**
|
|
36
|
+
* Backoff applied to a retry. Rounded up to whole seconds when
|
|
37
|
+
* forwarded to Cloudflare.
|
|
38
|
+
*/
|
|
39
|
+
retryDelay?: Duration.Input;
|
|
32
40
|
/** Optional dead-letter queue name. */
|
|
33
41
|
deadLetterQueue?: string;
|
|
34
42
|
}
|
|
35
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Convert a {@link MessagesProps} (with `Duration.Input` time fields)
|
|
46
|
+
* into the numeric settings shape Cloudflare's `QueueConsumer` API
|
|
47
|
+
* expects. `maxWaitTime` is rounded up to whole milliseconds and
|
|
48
|
+
* `retryDelay` to whole seconds.
|
|
49
|
+
*
|
|
50
|
+
* Exposed for testing and for callers that want to mirror the
|
|
51
|
+
* conversion when wiring `QueueConsumer` directly.
|
|
52
|
+
*/
|
|
53
|
+
export const toConsumerSettings = (props: MessagesProps) => ({
|
|
54
|
+
batchSize: props.batchSize,
|
|
55
|
+
maxConcurrency: props.maxConcurrency,
|
|
56
|
+
maxRetries: props.maxRetries,
|
|
57
|
+
maxWaitTimeMs: DurationUtil.toMillis(props.maxWaitTime),
|
|
58
|
+
retryDelay: DurationUtil.toSeconds(props.retryDelay),
|
|
59
|
+
});
|
|
60
|
+
|
|
36
61
|
/**
|
|
37
62
|
* A single queue message handed to the subscribe handler. Mirrors
|
|
38
63
|
* Cloudflare's runtime `Message<Body>` shape so per-message
|
|
@@ -63,12 +88,15 @@ export type QueueMessage<Body = unknown> = cf.Message<Body>;
|
|
|
63
88
|
* @example
|
|
64
89
|
* ```typescript
|
|
65
90
|
* import * as Cloudflare from "alchemy/Cloudflare";
|
|
91
|
+
* import * as Duration from "effect/Duration";
|
|
66
92
|
* import * as Effect from "effect/Effect";
|
|
67
93
|
* import * as Stream from "effect/Stream";
|
|
68
94
|
*
|
|
69
95
|
* yield* Cloudflare.messages<MyEvent>(queueResource, {
|
|
70
96
|
* batchSize: 25,
|
|
71
97
|
* maxRetries: 3,
|
|
98
|
+
* maxWaitTime: "5 seconds",
|
|
99
|
+
* retryDelay: Duration.seconds(30),
|
|
72
100
|
* }).subscribe((stream) =>
|
|
73
101
|
* Stream.runForEach(stream, (msg) =>
|
|
74
102
|
* Effect.log(`event ${msg.body.id}`),
|
|
@@ -148,7 +176,7 @@ export const QueueEventSourcePolicyLive = QueueEventSourcePolicy.layer.succeed(
|
|
|
148
176
|
yield* QueueConsumer(`${queue.LogicalId}Consumer`, {
|
|
149
177
|
queueId: queue.queueId,
|
|
150
178
|
scriptName: host.workerName,
|
|
151
|
-
settings: props,
|
|
179
|
+
settings: toConsumerSettings(props),
|
|
152
180
|
deadLetterQueue: props.deadLetterQueue,
|
|
153
181
|
});
|
|
154
182
|
})) as unknown as (
|
|
@@ -12,6 +12,9 @@ import type * as Cloudflare from "../Providers.ts";
|
|
|
12
12
|
import * as Zone from "../Zone.ts";
|
|
13
13
|
import { R2BucketBinding } from "./R2BucketBinding.ts";
|
|
14
14
|
|
|
15
|
+
export const isR2Bucket = (value: unknown): value is R2Bucket =>
|
|
16
|
+
typeof value === "object" && (value as any)?.Type === "Cloudflare.R2Bucket";
|
|
17
|
+
|
|
15
18
|
export type R2BucketName = string;
|
|
16
19
|
|
|
17
20
|
export type R2BucketCustomDomainZone = Zone.ZoneReference;
|
|
@@ -520,6 +523,10 @@ export const R2BucketProvider = () =>
|
|
|
520
523
|
while: isNoSuchBucket,
|
|
521
524
|
schedule: r2BucketEndpointConsistencySchedule,
|
|
522
525
|
}),
|
|
526
|
+
Effect.retry({
|
|
527
|
+
while: isDomainInUseConflict,
|
|
528
|
+
schedule: r2CustomDomainConflictSchedule,
|
|
529
|
+
}),
|
|
523
530
|
);
|
|
524
531
|
return toCustomDomainAttributes({ ...created, zoneId });
|
|
525
532
|
}
|
|
@@ -842,3 +849,22 @@ const isNoSuchBucket = (error: unknown): boolean =>
|
|
|
842
849
|
error !== null &&
|
|
843
850
|
"_tag" in error &&
|
|
844
851
|
(error as { _tag: unknown })._tag === "NoSuchBucket";
|
|
852
|
+
|
|
853
|
+
// Cloudflare keys a custom domain to a single bucket at the zone level. After a
|
|
854
|
+
// domain is deleted, re-attaching the same hostname can transiently 409 with
|
|
855
|
+
// "Domain already in use" until the prior association is fully released. Treat
|
|
856
|
+
// that narrow conflict as eventual consistency and retry it on create.
|
|
857
|
+
const isDomainInUseConflict = (error: unknown): boolean =>
|
|
858
|
+
typeof error === "object" &&
|
|
859
|
+
error !== null &&
|
|
860
|
+
"_tag" in error &&
|
|
861
|
+
(error as { _tag: unknown })._tag === "Conflict" &&
|
|
862
|
+
"message" in error &&
|
|
863
|
+
typeof (error as { message: unknown }).message === "string" &&
|
|
864
|
+
(error as { message: string }).message.toLowerCase().includes("in use");
|
|
865
|
+
|
|
866
|
+
// Releasing a custom domain after delete can lag a few seconds, so give the
|
|
867
|
+
// conflict a longer, bounded budget than the bucket-endpoint lag above.
|
|
868
|
+
const r2CustomDomainConflictSchedule = Schedule.spaced("2 seconds").pipe(
|
|
869
|
+
Schedule.both(Schedule.recurs(8)),
|
|
870
|
+
);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as secretsStore from "@distilled.cloud/cloudflare/secrets-store";
|
|
2
|
+
import * as Console from "effect/Console";
|
|
2
3
|
import * as Effect from "effect/Effect";
|
|
3
4
|
import * as Option from "effect/Option";
|
|
4
5
|
import * as Redacted from "effect/Redacted";
|
|
@@ -100,9 +101,6 @@ export const StoreSecretProvider = () =>
|
|
|
100
101
|
const getStoreSecret = yield* secretsStore.getStoreSecret;
|
|
101
102
|
const listStoreSecrets = secretsStore.listStoreSecrets;
|
|
102
103
|
|
|
103
|
-
const arraysEqual = (a: string[], b: string[]) =>
|
|
104
|
-
a.length === b.length && a.every((v, i) => v === b[i]);
|
|
105
|
-
|
|
106
104
|
return {
|
|
107
105
|
stables: ["secretId", "secretName", "storeId", "accountId"],
|
|
108
106
|
diff: Effect.fn(function* ({ id, olds = {} as any, news, output }) {
|
|
@@ -117,7 +115,7 @@ export const StoreSecretProvider = () =>
|
|
|
117
115
|
const oldValue = olds.value ? Redacted.value(olds.value) : undefined;
|
|
118
116
|
const newValue = Redacted.value(news.value);
|
|
119
117
|
if (oldValue !== newValue) {
|
|
120
|
-
return { action: "
|
|
118
|
+
return { action: "update" } as const;
|
|
121
119
|
}
|
|
122
120
|
}),
|
|
123
121
|
reconcile: Effect.fn(function* ({ id, news, output }) {
|
|
@@ -212,49 +210,22 @@ export const StoreSecretProvider = () =>
|
|
|
212
210
|
observed = existing;
|
|
213
211
|
}
|
|
214
212
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
!output ||
|
|
224
|
-
(output.comment ?? undefined) !== (news.comment ?? undefined);
|
|
225
|
-
if (scopesChanged || commentChanged) {
|
|
226
|
-
const patched = yield* patchStoreSecret({
|
|
227
|
-
accountId,
|
|
228
|
-
storeId,
|
|
229
|
-
secretId: observed.id,
|
|
230
|
-
scopes: scopesChanged ? scopes : undefined,
|
|
231
|
-
comment: commentChanged ? news.comment : undefined,
|
|
232
|
-
}).pipe(
|
|
233
|
-
Effect.catchTag("SecretNotFound", () =>
|
|
234
|
-
Effect.succeed(undefined),
|
|
235
|
-
),
|
|
236
|
-
);
|
|
237
|
-
if (patched) {
|
|
238
|
-
return {
|
|
239
|
-
secretId: observed.id,
|
|
240
|
-
secretName: observed.name,
|
|
241
|
-
storeId: observed.storeId,
|
|
242
|
-
accountId,
|
|
243
|
-
status: patched.status,
|
|
244
|
-
scopes,
|
|
245
|
-
comment: patched.comment ?? undefined,
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
213
|
+
const patched = yield* patchStoreSecret({
|
|
214
|
+
accountId,
|
|
215
|
+
storeId,
|
|
216
|
+
secretId: observed.id,
|
|
217
|
+
scopes,
|
|
218
|
+
comment: news.comment,
|
|
219
|
+
value: Redacted.value(news.value),
|
|
220
|
+
});
|
|
250
221
|
return {
|
|
251
222
|
secretId: observed.id,
|
|
252
223
|
secretName: observed.name,
|
|
253
224
|
storeId: observed.storeId,
|
|
254
225
|
accountId,
|
|
255
|
-
status:
|
|
226
|
+
status: patched.status,
|
|
256
227
|
scopes,
|
|
257
|
-
comment:
|
|
228
|
+
comment: patched.comment ?? undefined,
|
|
258
229
|
};
|
|
259
230
|
}),
|
|
260
231
|
delete: Effect.fn(function* ({ output }) {
|
|
@@ -263,6 +234,8 @@ export const StoreSecretProvider = () =>
|
|
|
263
234
|
storeId: output.storeId,
|
|
264
235
|
secretId: output.secretId,
|
|
265
236
|
}).pipe(
|
|
237
|
+
Effect.tap(() => Effect.log(`deleted ${output.secretId}`)),
|
|
238
|
+
Effect.tapError(Console.log),
|
|
266
239
|
Effect.catchTag("SecretNotFound", () => Effect.void),
|
|
267
240
|
Effect.catchTag("StoreNotFound", () => Effect.void),
|
|
268
241
|
Effect.catchTag("NotFound", () => Effect.void),
|
|
@@ -2,6 +2,7 @@ import type * as runtime from "@cloudflare/workers-types";
|
|
|
2
2
|
import * as Data from "effect/Data";
|
|
3
3
|
import * as Effect from "effect/Effect";
|
|
4
4
|
import * as Layer from "effect/Layer";
|
|
5
|
+
import * as Redacted from "effect/Redacted";
|
|
5
6
|
import * as Binding from "../../Binding.ts";
|
|
6
7
|
import type { ResourceLike } from "../../Resource.ts";
|
|
7
8
|
import type { RuntimeContext } from "../../RuntimeContext.ts";
|
|
@@ -20,7 +21,7 @@ export class SecretError extends Data.TaggedError("SecretError")<{
|
|
|
20
21
|
* `SecretsStoreSecret` binding.
|
|
21
22
|
*/
|
|
22
23
|
export interface SecretClient extends Effect.Effect<
|
|
23
|
-
string
|
|
24
|
+
Redacted.Redacted<string>,
|
|
24
25
|
SecretError,
|
|
25
26
|
RuntimeContext
|
|
26
27
|
> {
|
|
@@ -31,7 +32,7 @@ export interface SecretClient extends Effect.Effect<
|
|
|
31
32
|
/**
|
|
32
33
|
* Read the current value of the secret.
|
|
33
34
|
*/
|
|
34
|
-
get(): Effect.Effect<string
|
|
35
|
+
get(): Effect.Effect<Redacted.Redacted<string>, SecretError, RuntimeContext>;
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
export class SecretBinding extends Binding.Service<
|
|
@@ -63,17 +64,16 @@ export const SecretBindingLive = Layer.effect(
|
|
|
63
64
|
}),
|
|
64
65
|
});
|
|
65
66
|
|
|
66
|
-
const getEffect
|
|
67
|
-
Effect.flatMap((raw) =>
|
|
67
|
+
const getEffect = raw.pipe(
|
|
68
|
+
Effect.flatMap((raw) =>
|
|
69
|
+
tryPromise(() => raw.get().then(Redacted.make)),
|
|
70
|
+
),
|
|
68
71
|
);
|
|
69
72
|
|
|
70
|
-
return Object.assign(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
get: () => getEffect,
|
|
75
|
-
},
|
|
76
|
-
) as SecretClient;
|
|
73
|
+
return Object.assign(getEffect, {
|
|
74
|
+
raw,
|
|
75
|
+
get: () => getEffect,
|
|
76
|
+
});
|
|
77
77
|
});
|
|
78
78
|
}),
|
|
79
79
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Redacted } from "effect";
|
|
1
2
|
import * as Effect from "effect/Effect";
|
|
2
3
|
import * as Layer from "effect/Layer";
|
|
3
4
|
import * as Path from "effect/Path";
|
|
@@ -12,7 +13,7 @@ import {
|
|
|
12
13
|
StateApi,
|
|
13
14
|
StateAuthLive,
|
|
14
15
|
} from "../../State/HttpStateApi.ts";
|
|
15
|
-
import
|
|
16
|
+
import { Secret } from "../SecretsStore/Secret.ts";
|
|
16
17
|
import { SecretBindingLive } from "../SecretsStore/SecretBinding.ts";
|
|
17
18
|
import { Worker } from "../Workers/Worker.ts";
|
|
18
19
|
import Store from "./Store.ts";
|
|
@@ -29,7 +30,7 @@ export const STATE_STORE_SCRIPT_NAME = "alchemy-state-store" as const;
|
|
|
29
30
|
* compare against this constant; a mismatch (or 404) triggers a
|
|
30
31
|
* forced redeploy via the bootstrap flow.
|
|
31
32
|
*/
|
|
32
|
-
export const STATE_STORE_VERSION =
|
|
33
|
+
export const STATE_STORE_VERSION = 6 as const;
|
|
33
34
|
|
|
34
35
|
/**
|
|
35
36
|
* Hard-coded OTLP/HTTP endpoints. Point at the public ingest relay
|
|
@@ -108,22 +109,21 @@ export default Worker(
|
|
|
108
109
|
},
|
|
109
110
|
},
|
|
110
111
|
Effect.gen(function* () {
|
|
111
|
-
const
|
|
112
|
+
const remoteSecret = yield* Secret.bind(AuthToken);
|
|
112
113
|
const store = yield* Store;
|
|
113
114
|
|
|
114
|
-
const bearerTokenValidator = Layer.
|
|
115
|
+
const bearerTokenValidator = Layer.succeed(
|
|
115
116
|
BearerTokenValidator,
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
),
|
|
125
|
-
|
|
126
|
-
),
|
|
117
|
+
BearerTokenValidator.of({
|
|
118
|
+
// @ts-expect-error - TODO(sam): fix RuntimeContext color here
|
|
119
|
+
validate: Effect.fnUntraced(function* (token) {
|
|
120
|
+
const expected = yield* remoteSecret.get();
|
|
121
|
+
return !!expected &&
|
|
122
|
+
timingSafeEqual(token.trim(), Redacted.value(expected).trim())
|
|
123
|
+
? yield* Effect.void
|
|
124
|
+
: yield* Effect.fail(new HttpApiError.Unauthorized());
|
|
125
|
+
}),
|
|
126
|
+
}),
|
|
127
127
|
);
|
|
128
128
|
|
|
129
129
|
const versionApi = HttpApiBuilder.group(StateApi, "version", (handlers) =>
|
|
@@ -41,7 +41,7 @@ import * as Access from "../Access.ts";
|
|
|
41
41
|
import { CloudflareAuth } from "../Auth/AuthProvider.ts";
|
|
42
42
|
import { EdgeSessionError, createEdgeSession } from "../EdgeSession.ts";
|
|
43
43
|
import Api, { STATE_STORE_SCRIPT_NAME, STATE_STORE_VERSION } from "./Api.ts";
|
|
44
|
-
import { AuthTokenSecretName, TokenValue } from "./Token.ts";
|
|
44
|
+
import { AuthToken, AuthTokenSecretName, TokenValue } from "./Token.ts";
|
|
45
45
|
|
|
46
46
|
/** Filename used for stored credentials under the profile directory. */
|
|
47
47
|
const CREDENTIALS_FILE = "cloudflare-state-store";
|
|
@@ -145,7 +145,13 @@ export const bootstrap = (options: BootstrapOptions = {}) =>
|
|
|
145
145
|
yield* Clank.info(
|
|
146
146
|
`Resuming Cloudflare State Store '${scriptName}' deployment...`,
|
|
147
147
|
);
|
|
148
|
-
yield* finishBootstrap({
|
|
148
|
+
yield* finishBootstrap({
|
|
149
|
+
scriptName,
|
|
150
|
+
profileName,
|
|
151
|
+
localState,
|
|
152
|
+
isCI,
|
|
153
|
+
force,
|
|
154
|
+
});
|
|
149
155
|
yield* Clank.success(`Cloudflare State Store '${scriptName}' is ready.`);
|
|
150
156
|
return;
|
|
151
157
|
}
|
|
@@ -178,6 +184,7 @@ export const bootstrap = (options: BootstrapOptions = {}) =>
|
|
|
178
184
|
localState,
|
|
179
185
|
isCI,
|
|
180
186
|
url: credentials.url,
|
|
187
|
+
force,
|
|
181
188
|
});
|
|
182
189
|
yield* Clank.success(`Cloudflare State Store '${scriptName}' is ready.`);
|
|
183
190
|
return;
|
|
@@ -191,7 +198,13 @@ export const bootstrap = (options: BootstrapOptions = {}) =>
|
|
|
191
198
|
yield* Clank.info(`Deploying Cloudflare State Store '${scriptName}'...`);
|
|
192
199
|
}
|
|
193
200
|
|
|
194
|
-
yield* finishBootstrap({
|
|
201
|
+
yield* finishBootstrap({
|
|
202
|
+
scriptName,
|
|
203
|
+
profileName,
|
|
204
|
+
localState,
|
|
205
|
+
isCI,
|
|
206
|
+
force,
|
|
207
|
+
});
|
|
195
208
|
yield* Clank.success(`Cloudflare State Store '${scriptName}' is ready.`);
|
|
196
209
|
}).pipe(
|
|
197
210
|
Effect.withSpan("state_store.bootstrap", {
|
|
@@ -221,6 +234,7 @@ export const state = () =>
|
|
|
221
234
|
"alchemy.state_store.script_name": scriptName,
|
|
222
235
|
"alchemy.state_store.profile": profileName,
|
|
223
236
|
"alchemy.state_store.ci": isCI,
|
|
237
|
+
"alchemy.state_store.force": false,
|
|
224
238
|
});
|
|
225
239
|
yield* annotateAccountHash(
|
|
226
240
|
yield* Config.boolean("NO_TRACK").pipe(Config.withDefault(false)),
|
|
@@ -255,6 +269,7 @@ export const state = () =>
|
|
|
255
269
|
profileName,
|
|
256
270
|
localState,
|
|
257
271
|
isCI,
|
|
272
|
+
force: false,
|
|
258
273
|
});
|
|
259
274
|
}
|
|
260
275
|
|
|
@@ -270,6 +285,7 @@ export const state = () =>
|
|
|
270
285
|
localState,
|
|
271
286
|
isCI,
|
|
272
287
|
url: credentials.url,
|
|
288
|
+
force: false,
|
|
273
289
|
});
|
|
274
290
|
if (fresh) return fresh;
|
|
275
291
|
|
|
@@ -311,6 +327,7 @@ export const state = () =>
|
|
|
311
327
|
localState,
|
|
312
328
|
isCI,
|
|
313
329
|
url: credentials.url,
|
|
330
|
+
force: false,
|
|
314
331
|
});
|
|
315
332
|
if (fresh) return fresh;
|
|
316
333
|
|
|
@@ -346,6 +363,7 @@ export const state = () =>
|
|
|
346
363
|
profileName,
|
|
347
364
|
localState,
|
|
348
365
|
isCI,
|
|
366
|
+
force: false,
|
|
349
367
|
});
|
|
350
368
|
}).pipe(recordStateStoreInit, Effect.orDie),
|
|
351
369
|
).pipe(
|
|
@@ -423,14 +441,20 @@ const finishBootstrap = ({
|
|
|
423
441
|
profileName,
|
|
424
442
|
localState,
|
|
425
443
|
isCI,
|
|
444
|
+
force,
|
|
426
445
|
}: {
|
|
427
446
|
scriptName: string;
|
|
428
447
|
profileName: string;
|
|
429
448
|
localState: StateService;
|
|
430
449
|
isCI: boolean;
|
|
450
|
+
force: boolean;
|
|
431
451
|
}) =>
|
|
432
452
|
Effect.gen(function* () {
|
|
433
|
-
yield* deployStateStore(
|
|
453
|
+
const { authToken } = yield* deployStateStore(
|
|
454
|
+
scriptName,
|
|
455
|
+
localState,
|
|
456
|
+
force,
|
|
457
|
+
);
|
|
434
458
|
|
|
435
459
|
// Don't trust the `authToken` returned by `deploy(...)`: when
|
|
436
460
|
// adoption kicks in (the Secrets Store secret already existed),
|
|
@@ -442,7 +466,7 @@ const finishBootstrap = ({
|
|
|
442
466
|
// actually deployed. `loginWithCloudflare` also persists the
|
|
443
467
|
// credentials file (skipping the write in CI), so we don't need
|
|
444
468
|
// to do that explicitly here.
|
|
445
|
-
const { url
|
|
469
|
+
const { url } = yield* loginWithCloudflare();
|
|
446
470
|
const httpState = yield* makeCloudflareStateStore({ url, authToken });
|
|
447
471
|
// `profileName` is intentionally unused here — `loginWithCloudflare`
|
|
448
472
|
// resolves it itself. Reference it to keep the surrounding API
|
|
@@ -476,7 +500,11 @@ const finishBootstrap = ({
|
|
|
476
500
|
}),
|
|
477
501
|
);
|
|
478
502
|
|
|
479
|
-
const deployStateStore = (
|
|
503
|
+
const deployStateStore = (
|
|
504
|
+
scriptName: string,
|
|
505
|
+
state?: StateService,
|
|
506
|
+
force?: boolean,
|
|
507
|
+
) =>
|
|
480
508
|
Effect.gen(function* () {
|
|
481
509
|
yield* annotateAccountHash();
|
|
482
510
|
const localState = state ?? (yield* makeLocalState());
|
|
@@ -485,6 +513,7 @@ const deployStateStore = (scriptName: string, state?: StateService) =>
|
|
|
485
513
|
const { url, authToken } = yield* deploy({
|
|
486
514
|
// use the script name as the stage name (so the user can have multiple state stores)
|
|
487
515
|
stage: scriptName,
|
|
516
|
+
force,
|
|
488
517
|
stack: Alchemy.Stack(
|
|
489
518
|
"CloudflareStateStore",
|
|
490
519
|
{
|
|
@@ -494,6 +523,7 @@ const deployStateStore = (scriptName: string, state?: StateService) =>
|
|
|
494
523
|
Effect.gen(function* () {
|
|
495
524
|
const token = yield* TokenValue;
|
|
496
525
|
const api = yield* Api;
|
|
526
|
+
yield* AuthToken; // make sure it's in the Secrets Store
|
|
497
527
|
|
|
498
528
|
// Surface the bearer token so tests and clients can authenticate
|
|
499
529
|
// after deploy. The underlying value lives in the Cloudflare
|
|
@@ -514,6 +544,9 @@ const deployStateStore = (scriptName: string, state?: StateService) =>
|
|
|
514
544
|
// TODO(sam): we should not need to do this, but types do complain. fix deploy
|
|
515
545
|
Effect.provide(stateLayer),
|
|
516
546
|
);
|
|
547
|
+
|
|
548
|
+
yield* writeCredentials(url, authToken);
|
|
549
|
+
|
|
517
550
|
// Cloudflare's worker upload is eventually consistent: the deploy
|
|
518
551
|
// call returns as soon as the script upload is accepted, but the
|
|
519
552
|
// edge can keep serving the previous version for several seconds
|
|
@@ -582,6 +615,13 @@ export const loginWithCloudflare = () =>
|
|
|
582
615
|
STATE_STORE_SCRIPT_NAME,
|
|
583
616
|
store.id,
|
|
584
617
|
AuthTokenSecretName,
|
|
618
|
+
).pipe(
|
|
619
|
+
Effect.retry({
|
|
620
|
+
while: isWorkersPreviewConfigurationError,
|
|
621
|
+
schedule: Schedule.exponential(200).pipe(
|
|
622
|
+
Schedule.both(Schedule.recurs(15)),
|
|
623
|
+
),
|
|
624
|
+
}),
|
|
585
625
|
);
|
|
586
626
|
|
|
587
627
|
// 3. Derive the deployed worker URL.
|
|
@@ -634,6 +674,25 @@ export const loginWithCloudflare = () =>
|
|
|
634
674
|
}),
|
|
635
675
|
);
|
|
636
676
|
|
|
677
|
+
const writeCredentials = (url: string, authToken: string) =>
|
|
678
|
+
Effect.gen(function* () {
|
|
679
|
+
const profileName = yield* ALCHEMY_PROFILE;
|
|
680
|
+
const credStore = yield* CredentialsStore;
|
|
681
|
+
yield* credStore.write<HttpStateStoreCredentials>(
|
|
682
|
+
profileName,
|
|
683
|
+
CREDENTIALS_FILE,
|
|
684
|
+
{
|
|
685
|
+
url,
|
|
686
|
+
authToken,
|
|
687
|
+
},
|
|
688
|
+
);
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
const isWorkersPreviewConfigurationError = (error: unknown) =>
|
|
692
|
+
error instanceof EdgeSessionError &&
|
|
693
|
+
(error.message.includes("Invalid Workers Preview configuration") ||
|
|
694
|
+
error.message.includes("Error 1031"));
|
|
695
|
+
|
|
637
696
|
/**
|
|
638
697
|
* Run {@link finishBootstrap} iff the worker at `url` fails the
|
|
639
698
|
* version probe; otherwise resolve to `undefined`. Centralises the
|
|
@@ -646,12 +705,14 @@ const redeployIfStale = ({
|
|
|
646
705
|
profileName,
|
|
647
706
|
localState,
|
|
648
707
|
isCI,
|
|
708
|
+
force,
|
|
649
709
|
}: {
|
|
650
710
|
url: string;
|
|
651
711
|
scriptName: string;
|
|
652
712
|
profileName: string;
|
|
653
713
|
localState: StateService;
|
|
654
714
|
isCI: boolean;
|
|
715
|
+
force: boolean;
|
|
655
716
|
}) =>
|
|
656
717
|
Effect.gen(function* () {
|
|
657
718
|
const { matches, expected, observed } = yield* checkStateStoreVersion(url);
|
|
@@ -665,6 +726,7 @@ const redeployIfStale = ({
|
|
|
665
726
|
profileName,
|
|
666
727
|
localState,
|
|
667
728
|
isCI,
|
|
729
|
+
force,
|
|
668
730
|
});
|
|
669
731
|
}).pipe(
|
|
670
732
|
Effect.withSpan("state_store.redeploy_if_stale", {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Redacted from "effect/Redacted";
|
|
2
3
|
|
|
4
|
+
import { pipe } from "effect/Function";
|
|
3
5
|
import type {
|
|
4
6
|
ReplacedResourceState,
|
|
5
7
|
ResourceState,
|
|
6
8
|
} from "../../State/ResourceState.ts";
|
|
7
9
|
import { encodeState } from "../../State/StateEncoding.ts";
|
|
8
|
-
import { pipe } from "effect/Function";
|
|
9
10
|
import * as Secret from "../SecretsStore/Secret.ts";
|
|
10
11
|
import { DurableObjectNamespace } from "../Workers/DurableObjectNamespace.ts";
|
|
11
12
|
import { DurableObjectState } from "../Workers/DurableObjectState.ts";
|
|
@@ -25,7 +26,9 @@ export default class Store extends DurableObjectNamespace<Store>()(
|
|
|
25
26
|
const doState = yield* DurableObjectState;
|
|
26
27
|
const storage = doState.storage;
|
|
27
28
|
|
|
28
|
-
const keyHex = yield* encryptionSecret
|
|
29
|
+
const keyHex = yield* encryptionSecret
|
|
30
|
+
.get()
|
|
31
|
+
.pipe(Effect.map(Redacted.value), Effect.orDie);
|
|
29
32
|
const cryptoKey = yield* Effect.tryPromise(() =>
|
|
30
33
|
crypto.subtle.importKey(
|
|
31
34
|
"raw",
|
|
@@ -77,7 +77,7 @@ export declare namespace VpcService {
|
|
|
77
77
|
export type VpcServiceAttributes = {
|
|
78
78
|
serviceId: string;
|
|
79
79
|
serviceName: string;
|
|
80
|
-
serviceType: "http";
|
|
80
|
+
serviceType: "http" | "tcp";
|
|
81
81
|
httpPort: number | undefined;
|
|
82
82
|
httpsPort: number | undefined;
|
|
83
83
|
host: VpcService.Host;
|
|
@@ -262,7 +262,7 @@ export const formatVpcService = (
|
|
|
262
262
|
service: {
|
|
263
263
|
serviceId?: string | null;
|
|
264
264
|
name: string;
|
|
265
|
-
type: "http";
|
|
265
|
+
type: "http" | "tcp";
|
|
266
266
|
createdAt?: string | null;
|
|
267
267
|
updatedAt?: string | null;
|
|
268
268
|
httpPort?: number | null;
|