alchemy 2.0.0-beta.47 → 2.0.0-beta.49
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 +28 -5
- package/bin/exec.js.map +1 -1
- package/lib/AWS/Lambda/BucketEventSource.d.ts +1 -1
- package/lib/AWS/Lambda/BucketEventSource.d.ts.map +1 -1
- package/lib/AWS/Lambda/EventBridgeEventSource.d.ts +1 -1
- package/lib/AWS/Lambda/EventBridgeEventSource.d.ts.map +1 -1
- package/lib/AWS/Lambda/QueueEventSource.d.ts +1 -1
- package/lib/AWS/Lambda/QueueEventSource.d.ts.map +1 -1
- package/lib/AWS/Lambda/StreamEventSource.d.ts +1 -1
- package/lib/AWS/Lambda/StreamEventSource.d.ts.map +1 -1
- package/lib/AWS/Lambda/TableEventSource.d.ts +1 -1
- package/lib/AWS/Lambda/TableEventSource.d.ts.map +1 -1
- package/lib/AWS/Lambda/TopicEventSource.d.ts +1 -1
- package/lib/AWS/Lambda/TopicEventSource.d.ts.map +1 -1
- package/lib/AdoptPolicy.js +1 -1
- package/lib/AdoptPolicy.js.map +1 -1
- package/lib/Binding.d.ts +5 -1
- package/lib/Binding.d.ts.map +1 -1
- package/lib/Binding.js.map +1 -1
- package/lib/Cli/commands/cloudflare.d.ts +4 -1
- package/lib/Cli/commands/cloudflare.d.ts.map +1 -1
- package/lib/Cli/commands/cloudflare.js +274 -1
- package/lib/Cli/commands/cloudflare.js.map +1 -1
- package/lib/Cloudflare/AiGateway/AiGateway.d.ts +1 -1
- package/lib/Cloudflare/AiGateway/AiGateway.d.ts.map +1 -1
- package/lib/Cloudflare/AiGateway/AiGateway.js +2 -1
- package/lib/Cloudflare/AiGateway/AiGateway.js.map +1 -1
- package/lib/Cloudflare/ApiToken/AccountApiToken.d.ts +40 -2
- package/lib/Cloudflare/ApiToken/AccountApiToken.d.ts.map +1 -1
- package/lib/Cloudflare/ApiToken/AccountApiToken.js +49 -6
- package/lib/Cloudflare/ApiToken/AccountApiToken.js.map +1 -1
- package/lib/Cloudflare/ApiToken/Common.d.ts +36 -4
- package/lib/Cloudflare/ApiToken/Common.d.ts.map +1 -1
- package/lib/Cloudflare/ApiToken/Common.js +8 -0
- package/lib/Cloudflare/ApiToken/Common.js.map +1 -1
- package/lib/Cloudflare/ApiToken/UserApiToken.d.ts +38 -2
- package/lib/Cloudflare/ApiToken/UserApiToken.d.ts.map +1 -1
- package/lib/Cloudflare/ApiToken/UserApiToken.js +47 -6
- package/lib/Cloudflare/ApiToken/UserApiToken.js.map +1 -1
- package/lib/Cloudflare/Browser/Browser.d.ts +121 -0
- package/lib/Cloudflare/Browser/Browser.d.ts.map +1 -0
- package/lib/Cloudflare/{BrowserRendering/BrowserRendering.js → Browser/Browser.js} +19 -26
- package/lib/Cloudflare/Browser/Browser.js.map +1 -0
- package/lib/Cloudflare/Browser/BrowserBinding.d.ts +55 -0
- package/lib/Cloudflare/Browser/BrowserBinding.d.ts.map +1 -0
- package/lib/Cloudflare/{BrowserRendering/BrowserRenderingBinding.js → Browser/BrowserBinding.js} +11 -11
- package/lib/Cloudflare/Browser/BrowserBinding.js.map +1 -0
- package/lib/Cloudflare/Browser/index.d.ts +3 -0
- package/lib/Cloudflare/Browser/index.d.ts.map +1 -0
- package/lib/Cloudflare/Browser/index.js +3 -0
- package/lib/Cloudflare/Browser/index.js.map +1 -0
- package/lib/Cloudflare/Container/ContainerBinding.d.ts +2 -1
- package/lib/Cloudflare/Container/ContainerBinding.d.ts.map +1 -1
- 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/Dns/DnsBinding.d.ts +52 -0
- package/lib/Cloudflare/Dns/DnsBinding.d.ts.map +1 -0
- package/lib/Cloudflare/Dns/DnsBinding.js +59 -0
- package/lib/Cloudflare/Dns/DnsBinding.js.map +1 -0
- package/lib/Cloudflare/Dns/DnsRead.d.ts +80 -0
- package/lib/Cloudflare/Dns/DnsRead.d.ts.map +1 -0
- package/lib/Cloudflare/Dns/DnsRead.js +70 -0
- package/lib/Cloudflare/Dns/DnsRead.js.map +1 -0
- package/lib/Cloudflare/Dns/DnsReadWrite.d.ts +79 -0
- package/lib/Cloudflare/Dns/DnsReadWrite.d.ts.map +1 -0
- package/lib/Cloudflare/Dns/DnsReadWrite.js +72 -0
- package/lib/Cloudflare/Dns/DnsReadWrite.js.map +1 -0
- package/lib/Cloudflare/Dns/DnsWrite.d.ts +113 -0
- package/lib/Cloudflare/Dns/DnsWrite.d.ts.map +1 -0
- package/lib/Cloudflare/Dns/DnsWrite.js +100 -0
- package/lib/Cloudflare/Dns/DnsWrite.js.map +1 -0
- package/lib/Cloudflare/Dns/index.d.ts +5 -0
- package/lib/Cloudflare/Dns/index.d.ts.map +1 -0
- package/lib/Cloudflare/Dns/index.js +5 -0
- package/lib/Cloudflare/Dns/index.js.map +1 -0
- package/lib/Cloudflare/Email/EmailRouting.d.ts +1 -1
- package/lib/Cloudflare/Email/EmailRouting.d.ts.map +1 -1
- package/lib/Cloudflare/Email/EmailRouting.js +1 -1
- package/lib/Cloudflare/Email/EmailRouting.js.map +1 -1
- package/lib/Cloudflare/Email/EmailRule.d.ts +1 -1
- package/lib/Cloudflare/Email/EmailRule.d.ts.map +1 -1
- package/lib/Cloudflare/Email/EmailRule.js +1 -1
- package/lib/Cloudflare/Email/EmailRule.js.map +1 -1
- package/lib/Cloudflare/Hyperdrive/Hyperdrive.d.ts +1 -1
- package/lib/Cloudflare/Images/Images.d.ts +32 -23
- package/lib/Cloudflare/Images/Images.d.ts.map +1 -1
- package/lib/Cloudflare/Images/Images.js +10 -13
- package/lib/Cloudflare/Images/Images.js.map +1 -1
- package/lib/Cloudflare/KV/KVNamespace.d.ts +1 -1
- package/lib/Cloudflare/Providers.d.ts.map +1 -1
- package/lib/Cloudflare/Providers.js +14 -3
- package/lib/Cloudflare/Providers.js.map +1 -1
- package/lib/Cloudflare/Queue/Queue.d.ts +1 -1
- package/lib/Cloudflare/R2/R2Bucket.d.ts +2 -2
- package/lib/Cloudflare/R2/R2Bucket.d.ts.map +1 -1
- package/lib/Cloudflare/R2/R2Bucket.js +13 -7
- package/lib/Cloudflare/R2/R2Bucket.js.map +1 -1
- package/lib/Cloudflare/RateLimit/RateLimit.d.ts +132 -0
- package/lib/Cloudflare/RateLimit/RateLimit.d.ts.map +1 -0
- package/lib/Cloudflare/RateLimit/RateLimit.js +80 -0
- package/lib/Cloudflare/RateLimit/RateLimit.js.map +1 -0
- package/lib/Cloudflare/RateLimit/RateLimitBinding.d.ts +30 -0
- package/lib/Cloudflare/RateLimit/RateLimitBinding.d.ts.map +1 -0
- package/lib/Cloudflare/RateLimit/RateLimitBinding.js +50 -0
- package/lib/Cloudflare/RateLimit/RateLimitBinding.js.map +1 -0
- package/lib/Cloudflare/RateLimit/index.d.ts +3 -0
- package/lib/Cloudflare/RateLimit/index.d.ts.map +1 -0
- package/lib/Cloudflare/RateLimit/index.js +3 -0
- package/lib/Cloudflare/RateLimit/index.js.map +1 -0
- package/lib/Cloudflare/SecretsStore/Secret.d.ts +3 -2
- package/lib/Cloudflare/SecretsStore/Secret.d.ts.map +1 -1
- package/lib/Cloudflare/SecretsStore/Secret.js +7 -4
- package/lib/Cloudflare/SecretsStore/Secret.js.map +1 -1
- package/lib/Cloudflare/StateStore/Api.d.ts +1 -1
- package/lib/Cloudflare/Tunnel/Tunnel.d.ts +27 -0
- package/lib/Cloudflare/Tunnel/Tunnel.d.ts.map +1 -1
- package/lib/Cloudflare/Tunnel/Tunnel.js +27 -0
- package/lib/Cloudflare/Tunnel/Tunnel.js.map +1 -1
- package/lib/Cloudflare/Tunnel/TunnelBinding.d.ts +48 -0
- package/lib/Cloudflare/Tunnel/TunnelBinding.d.ts.map +1 -0
- package/lib/Cloudflare/Tunnel/TunnelBinding.js +56 -0
- package/lib/Cloudflare/Tunnel/TunnelBinding.js.map +1 -0
- package/lib/Cloudflare/Tunnel/TunnelRead.d.ts +83 -0
- package/lib/Cloudflare/Tunnel/TunnelRead.d.ts.map +1 -0
- package/lib/Cloudflare/Tunnel/TunnelRead.js +79 -0
- package/lib/Cloudflare/Tunnel/TunnelRead.js.map +1 -0
- package/lib/Cloudflare/Tunnel/TunnelReadWrite.d.ts +70 -0
- package/lib/Cloudflare/Tunnel/TunnelReadWrite.d.ts.map +1 -0
- package/lib/Cloudflare/Tunnel/TunnelReadWrite.js +63 -0
- package/lib/Cloudflare/Tunnel/TunnelReadWrite.js.map +1 -0
- package/lib/Cloudflare/Tunnel/TunnelWrite.d.ts +92 -0
- package/lib/Cloudflare/Tunnel/TunnelWrite.d.ts.map +1 -0
- package/lib/Cloudflare/Tunnel/TunnelWrite.js +88 -0
- package/lib/Cloudflare/Tunnel/TunnelWrite.js.map +1 -0
- package/lib/Cloudflare/Tunnel/index.d.ts +4 -0
- package/lib/Cloudflare/Tunnel/index.d.ts.map +1 -1
- package/lib/Cloudflare/Tunnel/index.js +4 -0
- package/lib/Cloudflare/Tunnel/index.js.map +1 -1
- package/lib/Cloudflare/Vectorize/VectorizeIndex.d.ts +1 -1
- package/lib/Cloudflare/Vectorize/VectorizeIndex.js +1 -0
- package/lib/Cloudflare/Vectorize/VectorizeIndex.js.map +1 -1
- package/lib/Cloudflare/VpcService/VpcService.d.ts +1 -1
- package/lib/Cloudflare/VpcService/VpcService.d.ts.map +1 -1
- package/lib/Cloudflare/VpcService/VpcService.js.map +1 -1
- package/lib/Cloudflare/Workers/DynamicWorkerLoader.d.ts +119 -11
- package/lib/Cloudflare/Workers/DynamicWorkerLoader.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/DynamicWorkerLoader.js +88 -9
- package/lib/Cloudflare/Workers/DynamicWorkerLoader.js.map +1 -1
- package/lib/Cloudflare/Workers/InferEnv.d.ts +1 -1
- package/lib/Cloudflare/Workers/InferEnv.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js +2 -0
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.js +18 -2
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBinding.d.ts +7 -5
- package/lib/Cloudflare/Workers/WorkerBinding.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBinding.js +1 -1
- package/lib/Cloudflare/Workers/WorkerBinding.js.map +1 -1
- package/lib/Cloudflare/Zaraz/ZarazConfig.d.ts +1 -1
- package/lib/Cloudflare/Zaraz/ZarazConfig.d.ts.map +1 -1
- package/lib/Cloudflare/Zaraz/ZarazConfig.js +1 -1
- package/lib/Cloudflare/Zaraz/ZarazConfig.js.map +1 -1
- package/lib/Cloudflare/Zone/Zone.d.ts +170 -0
- package/lib/Cloudflare/Zone/Zone.d.ts.map +1 -0
- package/lib/Cloudflare/Zone/Zone.js +180 -0
- package/lib/Cloudflare/Zone/Zone.js.map +1 -0
- package/lib/Cloudflare/Zone/index.d.ts +3 -0
- package/lib/Cloudflare/Zone/index.d.ts.map +1 -0
- package/lib/Cloudflare/Zone/index.js +3 -0
- package/lib/Cloudflare/Zone/index.js.map +1 -0
- package/lib/Cloudflare/Zone/lookup.d.ts +33 -0
- package/lib/Cloudflare/Zone/lookup.d.ts.map +1 -0
- package/lib/Cloudflare/{Zone.js → Zone/lookup.js} +2 -2
- package/lib/Cloudflare/Zone/lookup.js.map +1 -0
- package/lib/Cloudflare/index.d.ts +4 -1
- package/lib/Cloudflare/index.d.ts.map +1 -1
- package/lib/Cloudflare/index.js +4 -1
- package/lib/Cloudflare/index.js.map +1 -1
- package/lib/Output.d.ts +13 -1
- package/lib/Output.d.ts.map +1 -1
- package/lib/Output.js +43 -11
- package/lib/Output.js.map +1 -1
- package/lib/Plan.d.ts.map +1 -1
- package/lib/Plan.js +8 -0
- package/lib/Plan.js.map +1 -1
- package/lib/Platform.d.ts +5 -5
- package/lib/Platform.d.ts.map +1 -1
- package/lib/Platform.js +5 -2
- package/lib/Platform.js.map +1 -1
- package/lib/RemovalPolicy.js +2 -2
- package/lib/RemovalPolicy.js.map +1 -1
- package/lib/Resource.d.ts +15 -2
- package/lib/Resource.d.ts.map +1 -1
- package/lib/Resource.js +3 -2
- package/lib/Resource.js.map +1 -1
- package/lib/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/AdoptPolicy.ts +1 -1
- package/src/Binding.ts +5 -1
- package/src/Cli/commands/cloudflare.ts +394 -1
- package/src/Cloudflare/AiGateway/AiGateway.ts +2 -1
- package/src/Cloudflare/ApiToken/AccountApiToken.ts +60 -7
- package/src/Cloudflare/ApiToken/Common.ts +45 -6
- package/src/Cloudflare/ApiToken/UserApiToken.ts +58 -7
- package/src/Cloudflare/Browser/Browser.ts +140 -0
- package/src/Cloudflare/Browser/BrowserBinding.ts +128 -0
- package/src/Cloudflare/Browser/index.ts +11 -0
- package/src/Cloudflare/D1/D1Database.ts +6 -2
- package/src/Cloudflare/Dns/DnsBinding.ts +123 -0
- package/src/Cloudflare/Dns/DnsRead.ts +129 -0
- package/src/Cloudflare/Dns/DnsReadWrite.ts +99 -0
- package/src/Cloudflare/Dns/DnsWrite.ts +209 -0
- package/src/Cloudflare/Dns/index.ts +4 -0
- package/src/Cloudflare/Email/EmailRouting.ts +1 -1
- package/src/Cloudflare/Email/EmailRule.ts +6 -6
- package/src/Cloudflare/Images/Images.ts +40 -27
- package/src/Cloudflare/Providers.ts +22 -3
- package/src/Cloudflare/R2/R2Bucket.ts +17 -9
- package/src/Cloudflare/RateLimit/RateLimit.ts +160 -0
- package/src/Cloudflare/RateLimit/RateLimitBinding.ts +90 -0
- package/src/Cloudflare/RateLimit/index.ts +2 -0
- package/src/Cloudflare/SecretsStore/Secret.ts +12 -6
- package/src/Cloudflare/Tunnel/Tunnel.ts +27 -0
- package/src/Cloudflare/Tunnel/TunnelBinding.ts +114 -0
- package/src/Cloudflare/Tunnel/TunnelRead.ts +168 -0
- package/src/Cloudflare/Tunnel/TunnelReadWrite.ts +88 -0
- package/src/Cloudflare/Tunnel/TunnelWrite.ts +194 -0
- package/src/Cloudflare/Tunnel/index.ts +4 -0
- package/src/Cloudflare/Vectorize/VectorizeIndex.ts +2 -1
- package/src/Cloudflare/VpcService/VpcService.ts +4 -2
- package/src/Cloudflare/Workers/DynamicWorkerLoader.ts +139 -13
- package/src/Cloudflare/Workers/InferEnv.ts +19 -15
- package/src/Cloudflare/Workers/LocalWorkerProvider.ts +13 -2
- package/src/Cloudflare/Workers/WorkerAsyncBindings.ts +16 -2
- package/src/Cloudflare/Workers/WorkerBinding.ts +6 -2
- package/src/Cloudflare/Zaraz/ZarazConfig.ts +1 -1
- package/src/Cloudflare/Zone/Zone.ts +349 -0
- package/src/Cloudflare/Zone/index.ts +2 -0
- package/src/Cloudflare/{Zone.ts → Zone/lookup.ts} +16 -3
- package/src/Cloudflare/index.ts +4 -1
- package/src/Output.ts +67 -11
- package/src/Plan.ts +9 -0
- package/src/Platform.ts +19 -15
- package/src/RemovalPolicy.ts +2 -2
- package/src/Resource.ts +19 -2
- package/lib/Cloudflare/BrowserRendering/BrowserRendering.d.ts +0 -116
- package/lib/Cloudflare/BrowserRendering/BrowserRendering.d.ts.map +0 -1
- package/lib/Cloudflare/BrowserRendering/BrowserRendering.js.map +0 -1
- package/lib/Cloudflare/BrowserRendering/BrowserRenderingBinding.d.ts +0 -55
- package/lib/Cloudflare/BrowserRendering/BrowserRenderingBinding.d.ts.map +0 -1
- package/lib/Cloudflare/BrowserRendering/BrowserRenderingBinding.js.map +0 -1
- package/lib/Cloudflare/BrowserRendering/index.d.ts +0 -3
- package/lib/Cloudflare/BrowserRendering/index.d.ts.map +0 -1
- package/lib/Cloudflare/BrowserRendering/index.js +0 -3
- package/lib/Cloudflare/BrowserRendering/index.js.map +0 -1
- package/lib/Cloudflare/Zone.d.ts +0 -14
- package/lib/Cloudflare/Zone.d.ts.map +0 -1
- package/lib/Cloudflare/Zone.js.map +0 -1
- package/src/Cloudflare/BrowserRendering/BrowserRendering.ts +0 -132
- package/src/Cloudflare/BrowserRendering/BrowserRenderingBinding.ts +0 -137
- package/src/Cloudflare/BrowserRendering/index.ts +0 -11
|
@@ -18,17 +18,19 @@ import * as AnalyticsEngine from "./AnalyticsEngine/index.ts";
|
|
|
18
18
|
import * as ApiToken from "./ApiToken/index.ts";
|
|
19
19
|
import * as Artifacts from "./Artifacts/index.ts";
|
|
20
20
|
import { CloudflareAuth } from "./Auth/AuthProvider.ts";
|
|
21
|
-
import * as
|
|
21
|
+
import * as Browser from "./Browser/index.ts";
|
|
22
22
|
import * as CloudflareEnvironment from "./CloudflareEnvironment.ts";
|
|
23
23
|
import * as Containers from "./Container/index.ts";
|
|
24
24
|
import * as Credentials from "./Credentials.ts";
|
|
25
25
|
import * as D1 from "./D1/index.ts";
|
|
26
|
+
import * as Dns from "./Dns/index.ts";
|
|
26
27
|
import * as Email from "./Email/index.ts";
|
|
27
28
|
import * as Hyperdrive from "./Hyperdrive/index.ts";
|
|
28
29
|
import * as Images from "./Images/index.ts";
|
|
29
30
|
import * as KV from "./KV/index.ts";
|
|
30
31
|
import * as Queue from "./Queue/index.ts";
|
|
31
32
|
import * as R2 from "./R2/index.ts";
|
|
33
|
+
import * as RateLimit from "./RateLimit/index.ts";
|
|
32
34
|
import * as SecretsStore from "./SecretsStore/index.ts";
|
|
33
35
|
import * as Tunnel from "./Tunnel/index.ts";
|
|
34
36
|
import * as Vectorize from "./Vectorize/index.ts";
|
|
@@ -36,6 +38,7 @@ import * as VpcService from "./VpcService/index.ts";
|
|
|
36
38
|
import * as Workers from "./Workers/index.ts";
|
|
37
39
|
import * as Workflows from "./Workers/Workflow.ts";
|
|
38
40
|
import * as Zaraz from "./Zaraz/index.ts";
|
|
41
|
+
import * as Zone from "./Zone/index.ts";
|
|
39
42
|
|
|
40
43
|
export { Credentials } from "@distilled.cloud/cloudflare/Credentials";
|
|
41
44
|
|
|
@@ -58,11 +61,14 @@ export const providers = () =>
|
|
|
58
61
|
AiGateway.AiGatewayBindingPolicy,
|
|
59
62
|
AnalyticsEngine.AnalyticsEngineDatasetBindingPolicy,
|
|
60
63
|
Artifacts.ArtifactsBindingPolicy,
|
|
61
|
-
|
|
64
|
+
Browser.BrowserBindingPolicy,
|
|
62
65
|
Command,
|
|
63
66
|
Containers.Container,
|
|
64
67
|
D1.D1ConnectionPolicy,
|
|
65
68
|
D1.D1Database,
|
|
69
|
+
Dns.DnsReadPolicy,
|
|
70
|
+
Dns.DnsReadWritePolicy,
|
|
71
|
+
Dns.DnsWritePolicy,
|
|
66
72
|
Email.EmailAddress,
|
|
67
73
|
Email.EmailRouting,
|
|
68
74
|
Email.EmailRule,
|
|
@@ -78,10 +84,14 @@ export const providers = () =>
|
|
|
78
84
|
Queue.QueueEventSourcePolicy,
|
|
79
85
|
R2.R2Bucket,
|
|
80
86
|
R2.R2BucketBindingPolicy,
|
|
87
|
+
RateLimit.RateLimitBindingPolicy,
|
|
81
88
|
SecretsStore.SecretBindingPolicy,
|
|
82
89
|
SecretsStore.SecretsStore,
|
|
83
90
|
SecretsStore.Secret,
|
|
84
91
|
Tunnel.Tunnel,
|
|
92
|
+
Tunnel.TunnelReadPolicy,
|
|
93
|
+
Tunnel.TunnelReadWritePolicy,
|
|
94
|
+
Tunnel.TunnelWritePolicy,
|
|
85
95
|
Vectorize.VectorizeIndexBindingPolicy,
|
|
86
96
|
Vectorize.VectorizeIndex,
|
|
87
97
|
Vectorize.VectorizeMetadataIndex,
|
|
@@ -94,6 +104,7 @@ export const providers = () =>
|
|
|
94
104
|
Workers.Worker,
|
|
95
105
|
Workflows.WorkflowResource,
|
|
96
106
|
Zaraz.ZarazConfig,
|
|
107
|
+
Zone.Zone,
|
|
97
108
|
]),
|
|
98
109
|
).pipe(
|
|
99
110
|
Layer.provide(
|
|
@@ -104,10 +115,13 @@ export const providers = () =>
|
|
|
104
115
|
AiGateway.AiGatewayBindingPolicyLive,
|
|
105
116
|
AnalyticsEngine.AnalyticsEngineDatasetBindingPolicyLive,
|
|
106
117
|
Artifacts.ArtifactsBindingPolicyLive,
|
|
107
|
-
|
|
118
|
+
Browser.BrowserBindingPolicyLive,
|
|
108
119
|
Containers.ContainerProvider(),
|
|
109
120
|
D1.D1ConnectionPolicyLive,
|
|
110
121
|
D1.DatabaseProvider(),
|
|
122
|
+
Dns.DnsReadPolicyLive,
|
|
123
|
+
Dns.DnsReadWritePolicyLive,
|
|
124
|
+
Dns.DnsWritePolicyLive,
|
|
111
125
|
Email.EmailAddressProvider(),
|
|
112
126
|
Email.EmailRoutingProvider(),
|
|
113
127
|
Email.EmailRuleProvider(),
|
|
@@ -123,10 +137,14 @@ export const providers = () =>
|
|
|
123
137
|
Queue.QueueConsumerProvider(),
|
|
124
138
|
R2.R2BucketBindingPolicyLive,
|
|
125
139
|
R2.R2BucketProvider(),
|
|
140
|
+
RateLimit.RateLimitBindingPolicyLive,
|
|
126
141
|
SecretsStore.SecretBindingPolicyLive,
|
|
127
142
|
SecretsStore.SecretsStoreProvider(),
|
|
128
143
|
SecretsStore.StoreSecretProvider(),
|
|
129
144
|
Tunnel.TunnelProvider(),
|
|
145
|
+
Tunnel.TunnelReadPolicyLive,
|
|
146
|
+
Tunnel.TunnelReadWritePolicyLive,
|
|
147
|
+
Tunnel.TunnelWritePolicyLive,
|
|
130
148
|
Vectorize.VectorizeIndexBindingPolicyLive,
|
|
131
149
|
Vectorize.VectorizeIndexProvider(),
|
|
132
150
|
Vectorize.VectorizeMetadataIndexProvider(),
|
|
@@ -137,6 +155,7 @@ export const providers = () =>
|
|
|
137
155
|
Workers.WorkerProvider(),
|
|
138
156
|
Workflows.WorkflowProvider(),
|
|
139
157
|
Zaraz.ZarazConfigProvider(),
|
|
158
|
+
Zone.ZoneProvider(),
|
|
140
159
|
),
|
|
141
160
|
),
|
|
142
161
|
Layer.provideMerge(
|
|
@@ -9,7 +9,7 @@ import * as Provider from "../../Provider.ts";
|
|
|
9
9
|
import { Resource } from "../../Resource.ts";
|
|
10
10
|
import { CloudflareEnvironment } from "../CloudflareEnvironment.ts";
|
|
11
11
|
import type * as Cloudflare from "../Providers.ts";
|
|
12
|
-
import * as Zone from "../Zone.ts";
|
|
12
|
+
import * as Zone from "../Zone/index.ts";
|
|
13
13
|
import { R2BucketBinding } from "./R2BucketBinding.ts";
|
|
14
14
|
|
|
15
15
|
export const isR2Bucket = (value: unknown): value is R2Bucket =>
|
|
@@ -684,8 +684,11 @@ export const R2BucketProvider = () =>
|
|
|
684
684
|
|
|
685
685
|
const attrs = {
|
|
686
686
|
bucketName: observed.name!,
|
|
687
|
-
|
|
688
|
-
|
|
687
|
+
// Distilled widened generated string enums to open unions.
|
|
688
|
+
storageClass: (observed.storageClass ??
|
|
689
|
+
"Standard") as R2Bucket.StorageClass,
|
|
690
|
+
jurisdiction: (observed.jurisdiction ??
|
|
691
|
+
"default") as R2Bucket.Jurisdiction,
|
|
689
692
|
location: normalizeLocation(observed.location),
|
|
690
693
|
accountId: acct,
|
|
691
694
|
};
|
|
@@ -738,8 +741,11 @@ export const R2BucketProvider = () =>
|
|
|
738
741
|
}).pipe(
|
|
739
742
|
Effect.map((bucket) => ({
|
|
740
743
|
bucketName: bucket.name!,
|
|
741
|
-
|
|
742
|
-
|
|
744
|
+
// Distilled widened generated string enums to open unions.
|
|
745
|
+
storageClass: (bucket.storageClass ??
|
|
746
|
+
"Standard") as R2Bucket.StorageClass,
|
|
747
|
+
jurisdiction: (bucket.jurisdiction ??
|
|
748
|
+
"default") as R2Bucket.Jurisdiction,
|
|
743
749
|
location: normalizeLocation(bucket.location),
|
|
744
750
|
accountId: acct,
|
|
745
751
|
domains: output?.domains ?? [],
|
|
@@ -760,13 +766,15 @@ const r2BucketEndpointConsistencySchedule = Schedule.exponential(100).pipe(
|
|
|
760
766
|
Schedule.both(Schedule.recurs(5)),
|
|
761
767
|
);
|
|
762
768
|
|
|
769
|
+
// Distilled widened generated string enums to open unions (`string & {}`); the
|
|
770
|
+
// API only ever returns the known variants, narrowed in `toCustomDomainAttributes`.
|
|
763
771
|
type CustomDomainResponse = {
|
|
764
772
|
domain: string;
|
|
765
773
|
zoneId?: string | null;
|
|
766
774
|
enabled?: boolean | null;
|
|
767
775
|
ciphers?: string[] | null;
|
|
768
|
-
minTLS?:
|
|
769
|
-
status?:
|
|
776
|
+
minTLS?: string | null;
|
|
777
|
+
status?: { ownership: string; ssl: string } | null;
|
|
770
778
|
};
|
|
771
779
|
|
|
772
780
|
const toCustomDomainAttributes = (
|
|
@@ -776,8 +784,8 @@ const toCustomDomainAttributes = (
|
|
|
776
784
|
zoneId: domain.zoneId ?? undefined,
|
|
777
785
|
enabled: domain.enabled ?? true,
|
|
778
786
|
ciphers: domain.ciphers ?? undefined,
|
|
779
|
-
minTLS: domain.minTLS ?? undefined,
|
|
780
|
-
status: domain.status,
|
|
787
|
+
minTLS: (domain.minTLS ?? undefined) as R2Bucket.CustomDomain["minTLS"],
|
|
788
|
+
status: (domain.status ?? undefined) as R2Bucket.CustomDomain["status"],
|
|
781
789
|
});
|
|
782
790
|
|
|
783
791
|
const sameCustomDomainConfig = (
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import type * as Effect from "effect/Effect";
|
|
2
|
+
import { SingleShotGen } from "effect/Utils";
|
|
3
|
+
import { RateLimitBinding, type RateLimitClient } from "./RateLimitBinding.ts";
|
|
4
|
+
|
|
5
|
+
type RateLimitTypeId = typeof RateLimitTypeId;
|
|
6
|
+
const RateLimitTypeId = "Cloudflare.RateLimit" as const;
|
|
7
|
+
|
|
8
|
+
export type RateLimitPeriod = 10 | 60;
|
|
9
|
+
|
|
10
|
+
export type RateLimitProps = {
|
|
11
|
+
/**
|
|
12
|
+
* Binding name used when `RateLimit` is bound from inside a Worker init
|
|
13
|
+
* phase (`yield* Cloudflare.RateLimit(...)`). When passed through
|
|
14
|
+
* `Worker({ env: { ... } })`, the object key remains the binding name.
|
|
15
|
+
*
|
|
16
|
+
* @default "RATE_LIMIT"
|
|
17
|
+
*/
|
|
18
|
+
name?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Positive integer or string that uniquely identifies this rate limit
|
|
21
|
+
* configuration.
|
|
22
|
+
*/
|
|
23
|
+
namespaceId: number | string;
|
|
24
|
+
/**
|
|
25
|
+
* Simple rate limiting configuration.
|
|
26
|
+
*/
|
|
27
|
+
simple: {
|
|
28
|
+
/**
|
|
29
|
+
* The number of requests allowed within the period.
|
|
30
|
+
*/
|
|
31
|
+
limit: number;
|
|
32
|
+
/**
|
|
33
|
+
* The period, in seconds, over which requests are counted.
|
|
34
|
+
*/
|
|
35
|
+
period: RateLimitPeriod;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The Effect yielded when a `RateLimit` is used inside a Worker init phase:
|
|
41
|
+
* it attaches the `ratelimit` binding to the surrounding Worker and resolves
|
|
42
|
+
* to the runtime {@link RateLimitClient}.
|
|
43
|
+
*/
|
|
44
|
+
type BindEffect = Effect.Effect<RateLimitClient, never, RateLimitBinding>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* A Cloudflare Rate Limit binding marker.
|
|
48
|
+
*
|
|
49
|
+
* It is a plain data structure (so it can be declared directly on a Worker's
|
|
50
|
+
* `env`) that is **also** yieldable inside an Effect-native Worker. Yielding it
|
|
51
|
+
* (`yield* Cloudflare.RateLimit(...)`) attaches the binding to the surrounding
|
|
52
|
+
* Worker and returns the runtime {@link RateLimitClient} — no separate
|
|
53
|
+
* `.bind(...)` step required.
|
|
54
|
+
*
|
|
55
|
+
* The divergence is achieved via `[Symbol.iterator]`: the object is not an
|
|
56
|
+
* `Effect` (so `InferEnv` resolves it to the native `cf.RateLimit` in the
|
|
57
|
+
* `env` position), but it is iterable as one when `yield*`-ed.
|
|
58
|
+
*/
|
|
59
|
+
export interface RateLimit {
|
|
60
|
+
kind: RateLimitTypeId;
|
|
61
|
+
name: string;
|
|
62
|
+
namespaceId: string;
|
|
63
|
+
simple: {
|
|
64
|
+
limit: number;
|
|
65
|
+
period: RateLimitPeriod;
|
|
66
|
+
};
|
|
67
|
+
asEffect(): BindEffect;
|
|
68
|
+
[Symbol.iterator](): SingleShotGen<BindEffect, RateLimitClient>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const isRateLimit = (value: unknown): value is RateLimit =>
|
|
72
|
+
typeof value === "object" &&
|
|
73
|
+
value !== null &&
|
|
74
|
+
"kind" in value &&
|
|
75
|
+
(value as RateLimit).kind === RateLimitTypeId;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* A Cloudflare Rate Limit binding for counting arbitrary keys inside Workers.
|
|
79
|
+
*
|
|
80
|
+
* Rate Limit bindings are configured directly on Workers and do not have a
|
|
81
|
+
* standalone provisioning API. The Worker provider sees this object in
|
|
82
|
+
* `env: { ... }` and emits the corresponding `{ type: "ratelimit" }` metadata
|
|
83
|
+
* binding to the script.
|
|
84
|
+
*
|
|
85
|
+
* @section Declaring on a Worker's env
|
|
86
|
+
* @example Async (non-Effect) Worker
|
|
87
|
+
* ```typescript
|
|
88
|
+
* export const Worker = Cloudflare.Worker("Worker", {
|
|
89
|
+
* main: "./src/worker.ts",
|
|
90
|
+
* env: {
|
|
91
|
+
* THROTTLE: Cloudflare.RateLimit({
|
|
92
|
+
* namespaceId: 1001,
|
|
93
|
+
* simple: { limit: 10, period: 60 },
|
|
94
|
+
* }),
|
|
95
|
+
* },
|
|
96
|
+
* });
|
|
97
|
+
*
|
|
98
|
+
* export type WorkerEnv = Cloudflare.InferEnv<typeof Worker>;
|
|
99
|
+
* // { THROTTLE: RateLimit } — the native Cloudflare binding
|
|
100
|
+
*
|
|
101
|
+
* // worker.ts
|
|
102
|
+
* export default {
|
|
103
|
+
* fetch: async (req: Request, env: WorkerEnv) => {
|
|
104
|
+
* const { success } = await env.THROTTLE.limit({ key: "ip" });
|
|
105
|
+
* return new Response(success ? "ok" : "rate limited");
|
|
106
|
+
* },
|
|
107
|
+
* };
|
|
108
|
+
* ```
|
|
109
|
+
*
|
|
110
|
+
* @section Binding inside an Effect-native Worker
|
|
111
|
+
* @example yield* RateLimit does the binding
|
|
112
|
+
* ```typescript
|
|
113
|
+
* Cloudflare.Worker("Worker", { main: "./src/worker.ts" },
|
|
114
|
+
* Effect.gen(function* () {
|
|
115
|
+
* // Attaches the binding to this Worker AND returns the runtime client.
|
|
116
|
+
* const throttle = yield* Cloudflare.RateLimit({
|
|
117
|
+
* namespaceId: 1001,
|
|
118
|
+
* simple: { limit: 10, period: 60 },
|
|
119
|
+
* });
|
|
120
|
+
*
|
|
121
|
+
* return {
|
|
122
|
+
* fetch: Effect.gen(function* () {
|
|
123
|
+
* const { success } = yield* throttle.limit({ key: "ip" });
|
|
124
|
+
* return HttpServerResponse.text(success ? "ok" : "rate limited");
|
|
125
|
+
* }),
|
|
126
|
+
* };
|
|
127
|
+
* }).pipe(Effect.provide(Cloudflare.RateLimitBindingLive)),
|
|
128
|
+
* );
|
|
129
|
+
* ```
|
|
130
|
+
*
|
|
131
|
+
* @see https://developers.cloudflare.com/workers/runtime-apis/bindings/rate-limit/
|
|
132
|
+
*/
|
|
133
|
+
export const RateLimit: {
|
|
134
|
+
(props: RateLimitProps): RateLimit;
|
|
135
|
+
/**
|
|
136
|
+
* Bind an existing `RateLimit` marker to the surrounding Worker, returning
|
|
137
|
+
* the runtime client. Equivalent to `yield* rateLimit` — prefer yielding the
|
|
138
|
+
* marker directly.
|
|
139
|
+
*/
|
|
140
|
+
bind: typeof RateLimitBinding.bind;
|
|
141
|
+
} = Object.assign(
|
|
142
|
+
(props: RateLimitProps): RateLimit => {
|
|
143
|
+
const self: RateLimit = {
|
|
144
|
+
kind: RateLimitTypeId,
|
|
145
|
+
name: props.name ?? "RATE_LIMIT",
|
|
146
|
+
namespaceId: String(props.namespaceId),
|
|
147
|
+
simple: {
|
|
148
|
+
limit: props.simple.limit,
|
|
149
|
+
period: props.simple.period,
|
|
150
|
+
},
|
|
151
|
+
asEffect: () => RateLimitBinding.bind(self),
|
|
152
|
+
[Symbol.iterator]: () => new SingleShotGen(RateLimitBinding.bind(self)),
|
|
153
|
+
};
|
|
154
|
+
return self;
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
bind: (...args: Parameters<typeof RateLimitBinding.bind>) =>
|
|
158
|
+
RateLimitBinding.bind(...args),
|
|
159
|
+
},
|
|
160
|
+
);
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
+
|
|
3
|
+
import type * as cf from "@cloudflare/workers-types";
|
|
4
|
+
import * as Data from "effect/Data";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Layer from "effect/Layer";
|
|
7
|
+
import * as Binding from "../../Binding.ts";
|
|
8
|
+
import type { ResourceLike } from "../../Resource.ts";
|
|
9
|
+
import { isWorker, WorkerEnvironment } from "../Workers/Worker.ts";
|
|
10
|
+
import { type RateLimit as RateLimitLike } from "./RateLimit.ts";
|
|
11
|
+
|
|
12
|
+
export class RateLimitError extends Data.TaggedError("RateLimitError")<{
|
|
13
|
+
message: string;
|
|
14
|
+
cause: unknown;
|
|
15
|
+
}> {}
|
|
16
|
+
|
|
17
|
+
export interface RateLimitClient {
|
|
18
|
+
raw: Effect.Effect<cf.RateLimit, never, WorkerEnvironment>;
|
|
19
|
+
limit(
|
|
20
|
+
options: Parameters<cf.RateLimit["limit"]>[0],
|
|
21
|
+
): Effect.Effect<
|
|
22
|
+
Awaited<ReturnType<cf.RateLimit["limit"]>>,
|
|
23
|
+
RateLimitError,
|
|
24
|
+
WorkerEnvironment
|
|
25
|
+
>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class RateLimitBinding extends Binding.Service<
|
|
29
|
+
RateLimitBinding,
|
|
30
|
+
(rateLimit: RateLimitLike) => Effect.Effect<RateLimitClient>
|
|
31
|
+
>()("Cloudflare.RateLimit.Binding") {}
|
|
32
|
+
|
|
33
|
+
export const RateLimitBindingLive = Layer.effect(
|
|
34
|
+
RateLimitBinding,
|
|
35
|
+
Effect.gen(function* () {
|
|
36
|
+
const Policy = yield* RateLimitBindingPolicy;
|
|
37
|
+
|
|
38
|
+
return Effect.fn(function* (rateLimit: RateLimitLike) {
|
|
39
|
+
yield* Policy(rateLimit);
|
|
40
|
+
const raw = WorkerEnvironment.useSync(
|
|
41
|
+
(env) => (env as Record<string, cf.RateLimit>)[rateLimit.name]!,
|
|
42
|
+
);
|
|
43
|
+
return {
|
|
44
|
+
raw,
|
|
45
|
+
limit: (options) =>
|
|
46
|
+
raw.pipe(
|
|
47
|
+
Effect.flatMap((binding) =>
|
|
48
|
+
Effect.tryPromise({
|
|
49
|
+
try: () => binding.limit(options),
|
|
50
|
+
catch: (error) =>
|
|
51
|
+
new RateLimitError({
|
|
52
|
+
message:
|
|
53
|
+
error instanceof Error
|
|
54
|
+
? error.message
|
|
55
|
+
: "Unknown RateLimit error",
|
|
56
|
+
cause: error,
|
|
57
|
+
}),
|
|
58
|
+
}),
|
|
59
|
+
),
|
|
60
|
+
),
|
|
61
|
+
} satisfies RateLimitClient;
|
|
62
|
+
});
|
|
63
|
+
}),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
export class RateLimitBindingPolicy extends Binding.Policy<
|
|
67
|
+
RateLimitBindingPolicy,
|
|
68
|
+
(rateLimit: RateLimitLike) => Effect.Effect<void>
|
|
69
|
+
>()("Cloudflare.RateLimit.Binding") {}
|
|
70
|
+
|
|
71
|
+
export const RateLimitBindingPolicyLive = RateLimitBindingPolicy.layer.succeed(
|
|
72
|
+
Effect.fn(function* (host: ResourceLike, rateLimit: RateLimitLike) {
|
|
73
|
+
if (isWorker(host)) {
|
|
74
|
+
yield* host.bind(rateLimit.name, {
|
|
75
|
+
bindings: [
|
|
76
|
+
{
|
|
77
|
+
type: "ratelimit",
|
|
78
|
+
name: rateLimit.name,
|
|
79
|
+
namespaceId: rateLimit.namespaceId,
|
|
80
|
+
simple: rateLimit.simple,
|
|
81
|
+
} as any,
|
|
82
|
+
],
|
|
83
|
+
});
|
|
84
|
+
} else {
|
|
85
|
+
return yield* Effect.die(
|
|
86
|
+
new Error(`RateLimitBinding does not support runtime '${host.Type}'`),
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}),
|
|
90
|
+
);
|
|
@@ -46,7 +46,7 @@ export type Secret = Resource<
|
|
|
46
46
|
secretName: string;
|
|
47
47
|
storeId: string;
|
|
48
48
|
accountId: string;
|
|
49
|
-
status:
|
|
49
|
+
status: SecretStatus;
|
|
50
50
|
scopes: string[];
|
|
51
51
|
comment: string | undefined;
|
|
52
52
|
},
|
|
@@ -54,6 +54,12 @@ export type Secret = Resource<
|
|
|
54
54
|
Providers
|
|
55
55
|
>;
|
|
56
56
|
|
|
57
|
+
export type SecretStatus = "pending" | "active" | "deleted";
|
|
58
|
+
|
|
59
|
+
// Distilled widened generated string enums to open unions (`string & {}`); the
|
|
60
|
+
// API only ever returns the known variants, so narrow at the boundary.
|
|
61
|
+
const asSecretStatus = (status: string): SecretStatus => status as SecretStatus;
|
|
62
|
+
|
|
57
63
|
/**
|
|
58
64
|
* A single secret stored inside a Cloudflare Secrets Store.
|
|
59
65
|
*
|
|
@@ -132,7 +138,7 @@ export const StoreSecretProvider = () =>
|
|
|
132
138
|
id: string;
|
|
133
139
|
name: string;
|
|
134
140
|
storeId: string;
|
|
135
|
-
status:
|
|
141
|
+
status: string;
|
|
136
142
|
comment?: string | null;
|
|
137
143
|
}
|
|
138
144
|
| undefined;
|
|
@@ -188,7 +194,7 @@ export const StoreSecretProvider = () =>
|
|
|
188
194
|
secretName: secret.name,
|
|
189
195
|
storeId: secret.storeId,
|
|
190
196
|
accountId,
|
|
191
|
-
status: secret.status,
|
|
197
|
+
status: asSecretStatus(secret.status),
|
|
192
198
|
scopes,
|
|
193
199
|
comment: secret.comment ?? undefined,
|
|
194
200
|
};
|
|
@@ -223,7 +229,7 @@ export const StoreSecretProvider = () =>
|
|
|
223
229
|
secretName: observed.name,
|
|
224
230
|
storeId: observed.storeId,
|
|
225
231
|
accountId,
|
|
226
|
-
status: patched.status,
|
|
232
|
+
status: asSecretStatus(patched.status),
|
|
227
233
|
scopes,
|
|
228
234
|
comment: patched.comment ?? undefined,
|
|
229
235
|
};
|
|
@@ -253,7 +259,7 @@ export const StoreSecretProvider = () =>
|
|
|
253
259
|
secretName: secret.name,
|
|
254
260
|
storeId: secret.storeId,
|
|
255
261
|
accountId: output.accountId,
|
|
256
|
-
status: secret.status,
|
|
262
|
+
status: asSecretStatus(secret.status),
|
|
257
263
|
scopes: output.scopes,
|
|
258
264
|
comment: secret.comment ?? undefined,
|
|
259
265
|
})),
|
|
@@ -286,7 +292,7 @@ export const StoreSecretProvider = () =>
|
|
|
286
292
|
secretName: match.name,
|
|
287
293
|
storeId: match.storeId,
|
|
288
294
|
accountId: olds.store.accountId,
|
|
289
|
-
status: match.status,
|
|
295
|
+
status: asSecretStatus(match.status),
|
|
290
296
|
scopes: resolveScopes(olds.scopes),
|
|
291
297
|
comment: match.comment ?? undefined,
|
|
292
298
|
});
|
|
@@ -120,6 +120,33 @@ export type Tunnel = Resource<
|
|
|
120
120
|
* ],
|
|
121
121
|
* });
|
|
122
122
|
* ```
|
|
123
|
+
*
|
|
124
|
+
* @section Managing Tunnels at Runtime
|
|
125
|
+
* The `Tunnel` resource manages a single, statically-declared tunnel as part of
|
|
126
|
+
* a stack. To create, read, update, or delete tunnels *on the fly* from inside
|
|
127
|
+
* a deployed Worker, bind one of the runtime tunnel clients instead. Each
|
|
128
|
+
* provisions a least-privilege {@link AccountApiToken} and injects it into the
|
|
129
|
+
* Worker:
|
|
130
|
+
*
|
|
131
|
+
* - {@link TunnelRead} — read-only (`get`, `list`, `getToken`,
|
|
132
|
+
* `getConfiguration`); scoped to `Cloudflare Tunnel Read`.
|
|
133
|
+
* - {@link TunnelWrite} — mutating (`create`, `update`, `delete`,
|
|
134
|
+
* `putConfiguration`); scoped to `Cloudflare Tunnel Write`.
|
|
135
|
+
* - {@link TunnelReadWrite} — the full CRUD surface; scoped to both.
|
|
136
|
+
*
|
|
137
|
+
* @example Create a tunnel on demand from a Worker
|
|
138
|
+
* ```typescript
|
|
139
|
+
* // init
|
|
140
|
+
* const tunnels = yield* Cloudflare.TunnelReadWrite.bind();
|
|
141
|
+
*
|
|
142
|
+
* return {
|
|
143
|
+
* fetch: Effect.gen(function* () {
|
|
144
|
+
* const tunnel = yield* tunnels.create({ name: "on-demand-tunnel" });
|
|
145
|
+
* const token = yield* tunnels.getToken(tunnel.id!);
|
|
146
|
+
* return HttpServerResponse.json({ id: tunnel.id, token });
|
|
147
|
+
* }),
|
|
148
|
+
* };
|
|
149
|
+
* ```
|
|
123
150
|
*/
|
|
124
151
|
export const Tunnel = Resource<Tunnel>("Cloudflare.Tunnel");
|
|
125
152
|
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Credentials,
|
|
3
|
+
fromApiToken,
|
|
4
|
+
} from "@distilled.cloud/cloudflare/Credentials";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Layer from "effect/Layer";
|
|
7
|
+
import * as Redacted from "effect/Redacted";
|
|
8
|
+
import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
|
|
9
|
+
import type { HttpClient } from "effect/unstable/http/HttpClient";
|
|
10
|
+
import type * as Binding from "../../Binding.ts";
|
|
11
|
+
import { RuntimeContext } from "../../RuntimeContext.ts";
|
|
12
|
+
import { AccountApiToken } from "../ApiToken/AccountApiToken.ts";
|
|
13
|
+
import type { ApiTokenPermissionGroupRef } from "../ApiToken/Common.ts";
|
|
14
|
+
import { CloudflareEnvironment } from "../CloudflareEnvironment.ts";
|
|
15
|
+
import { Worker } from "../Workers/Worker.ts";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Runtime accessors for a tunnel binding's token, obtained by binding the
|
|
19
|
+
* {@link AccountApiToken}'s outputs in the Worker's Init phase. Each accessor
|
|
20
|
+
* reads the value back from the Worker's environment at runtime.
|
|
21
|
+
*/
|
|
22
|
+
export interface TunnelToken {
|
|
23
|
+
/** The token's plaintext value (injected as a `secret_text` binding). */
|
|
24
|
+
value: Effect.Effect<Redacted.Redacted<string>>;
|
|
25
|
+
/** The account id the token is scoped to. */
|
|
26
|
+
accountId: Effect.Effect<string>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Bind an {@link AccountApiToken}'s outputs into the Worker so they can be read
|
|
31
|
+
* at runtime: `token.value` is injected as a `secret_text` binding and
|
|
32
|
+
* `token.accountId` as `plain_text`. Returns the {@link TunnelToken} accessors.
|
|
33
|
+
*/
|
|
34
|
+
export const bindTunnelToken = (token: AccountApiToken) =>
|
|
35
|
+
Effect.gen(function* () {
|
|
36
|
+
const value = yield* token.value;
|
|
37
|
+
const accountId = yield* token.accountId;
|
|
38
|
+
return { value, accountId } satisfies TunnelToken;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Resolve credentials from a bound token and provide them (plus the
|
|
43
|
+
* fetch-based HTTP client) to a raw SDK operation.
|
|
44
|
+
*/
|
|
45
|
+
export const authorizeWith =
|
|
46
|
+
(token: TunnelToken) =>
|
|
47
|
+
<A, E>(
|
|
48
|
+
eff: Effect.Effect<A, E, Credentials | HttpClient>,
|
|
49
|
+
): Effect.Effect<A, E, RuntimeContext> =>
|
|
50
|
+
token.value.pipe(
|
|
51
|
+
Effect.flatMap((value) =>
|
|
52
|
+
eff.pipe(
|
|
53
|
+
Effect.provide(
|
|
54
|
+
fromApiToken({ apiToken: Redacted.value(value) }).pipe(
|
|
55
|
+
Layer.provideMerge(FetchHttpClient.layer),
|
|
56
|
+
),
|
|
57
|
+
),
|
|
58
|
+
),
|
|
59
|
+
),
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Shared runtime body for a tunnel binding: create a scoped token, attach the
|
|
64
|
+
* (narrow) policy, bind the token's outputs into the Worker, then build the
|
|
65
|
+
* client. Pass the result to `Layer.effect(<Binding>, ...)`.
|
|
66
|
+
*/
|
|
67
|
+
export const makeTunnelClient = <C>(
|
|
68
|
+
Policy: Binding.Policy<
|
|
69
|
+
any,
|
|
70
|
+
any,
|
|
71
|
+
(token: AccountApiToken) => Effect.Effect<void>
|
|
72
|
+
>,
|
|
73
|
+
makeClient: (token: TunnelToken) => C,
|
|
74
|
+
) =>
|
|
75
|
+
Effect.gen(function* () {
|
|
76
|
+
const Token = yield* AccountApiToken;
|
|
77
|
+
const attach = yield* Policy;
|
|
78
|
+
|
|
79
|
+
return Effect.fn(function* () {
|
|
80
|
+
const ctx = yield* Worker;
|
|
81
|
+
const token = yield* Token(`${ctx.LogicalId}Token`);
|
|
82
|
+
yield* attach(token);
|
|
83
|
+
return makeClient(yield* bindTunnelToken(token));
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Build the deploy-time policy layer for a tunnel binding: attach an allow
|
|
89
|
+
* policy with the given permission groups to the binding's token.
|
|
90
|
+
*/
|
|
91
|
+
export const makeTunnelPolicyLive = <Self, Id extends string>(
|
|
92
|
+
Policy: Binding.Policy<
|
|
93
|
+
Self,
|
|
94
|
+
Id,
|
|
95
|
+
(token: AccountApiToken) => Effect.Effect<void>
|
|
96
|
+
>,
|
|
97
|
+
sid: string,
|
|
98
|
+
permissionGroups: ApiTokenPermissionGroupRef[],
|
|
99
|
+
) =>
|
|
100
|
+
Policy.layer.effect(
|
|
101
|
+
Effect.gen(function* () {
|
|
102
|
+
const { accountId } = yield* CloudflareEnvironment;
|
|
103
|
+
return (_host, token) =>
|
|
104
|
+
token.bind(sid, {
|
|
105
|
+
policies: [
|
|
106
|
+
{
|
|
107
|
+
effect: "allow",
|
|
108
|
+
permissionGroups,
|
|
109
|
+
resources: { [`com.cloudflare.api.account.${accountId}`]: "*" },
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
});
|
|
113
|
+
}),
|
|
114
|
+
);
|