alchemy 2.0.0-beta.50 → 2.0.0-beta.52
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 +133 -135
- package/bin/exec.js.map +1 -1
- package/lib/AWS/Lambda/BucketEventSource.d.ts.map +1 -1
- package/lib/AWS/Lambda/BucketEventSource.js +13 -2
- package/lib/AWS/Lambda/BucketEventSource.js.map +1 -1
- package/lib/AWS/S3/Bucket.d.ts.map +1 -1
- package/lib/AWS/S3/Bucket.js +49 -0
- package/lib/AWS/S3/Bucket.js.map +1 -1
- package/lib/AWS/S3/BucketNotifications.d.ts +10 -0
- package/lib/AWS/S3/BucketNotifications.d.ts.map +1 -1
- package/lib/AWS/S3/BucketNotifications.js.map +1 -1
- package/lib/Apply.js +15 -3
- package/lib/Apply.js.map +1 -1
- package/lib/Auth/AuthProvider.js +1 -1
- package/lib/Auth/AuthProvider.js.map +1 -1
- package/lib/Binding.d.ts.map +1 -1
- package/lib/Binding.js +12 -8
- package/lib/Binding.js.map +1 -1
- package/lib/Build/DevServer.d.ts +113 -0
- package/lib/Build/DevServer.d.ts.map +1 -0
- package/lib/Build/DevServer.js +212 -0
- package/lib/Build/DevServer.js.map +1 -0
- package/lib/Build/Local.d.ts +2 -0
- package/lib/Build/Local.d.ts.map +1 -0
- package/lib/Build/Local.js +4 -0
- package/lib/Build/Local.js.map +1 -0
- package/lib/Bundle/Bundle.js +1 -1
- package/lib/Bundle/Bundle.js.map +1 -1
- package/lib/Cli/commands/cloudflare.d.ts +1 -1
- package/lib/Cloudflare/Access.js +1 -1
- package/lib/Cloudflare/Access.js.map +1 -1
- package/lib/Cloudflare/AiGateway/AiGateway.d.ts +1 -1
- package/lib/Cloudflare/AiGateway/AiGateway.js +1 -1
- package/lib/Cloudflare/AiGateway/AiGatewayBinding.d.ts +1 -1
- package/lib/Cloudflare/AiGateway/AiGatewayBinding.d.ts.map +1 -1
- package/lib/Cloudflare/AiGateway/AiGatewayBinding.js +6 -2
- package/lib/Cloudflare/AiGateway/AiGatewayBinding.js.map +1 -1
- package/lib/Cloudflare/Browser/Browser.d.ts +84 -12
- package/lib/Cloudflare/Browser/Browser.d.ts.map +1 -1
- package/lib/Cloudflare/Browser/Browser.js +80 -9
- package/lib/Cloudflare/Browser/Browser.js.map +1 -1
- package/lib/Cloudflare/Browser/BrowserBinding.d.ts +90 -16
- package/lib/Cloudflare/Browser/BrowserBinding.d.ts.map +1 -1
- package/lib/Cloudflare/Browser/BrowserBinding.js +41 -6
- package/lib/Cloudflare/Browser/BrowserBinding.js.map +1 -1
- package/lib/Cloudflare/Browser/index.d.ts +1 -1
- package/lib/Cloudflare/Browser/index.d.ts.map +1 -1
- package/lib/Cloudflare/Browser/index.js.map +1 -1
- package/lib/Cloudflare/Container/ContainerBinding.d.ts.map +1 -1
- package/lib/Cloudflare/Container/ContainerBinding.js +2 -4
- package/lib/Cloudflare/Container/ContainerBinding.js.map +1 -1
- package/lib/Cloudflare/Images/Images.d.ts +4 -3
- package/lib/Cloudflare/Images/Images.d.ts.map +1 -1
- package/lib/Cloudflare/Images/Images.js.map +1 -1
- package/lib/Cloudflare/Providers.d.ts +1 -1
- package/lib/Cloudflare/Providers.d.ts.map +1 -1
- package/lib/Cloudflare/Providers.js +6 -1
- package/lib/Cloudflare/Providers.js.map +1 -1
- package/lib/Cloudflare/RateLimit/RateLimit.d.ts +4 -3
- package/lib/Cloudflare/RateLimit/RateLimit.d.ts.map +1 -1
- package/lib/Cloudflare/RateLimit/RateLimit.js.map +1 -1
- package/lib/Cloudflare/Ruleset/Ruleset.d.ts +82 -0
- package/lib/Cloudflare/Ruleset/Ruleset.d.ts.map +1 -0
- package/lib/Cloudflare/Ruleset/Ruleset.js +126 -0
- package/lib/Cloudflare/Ruleset/Ruleset.js.map +1 -0
- package/lib/Cloudflare/Ruleset/index.d.ts +2 -0
- package/lib/Cloudflare/Ruleset/index.d.ts.map +1 -0
- package/lib/Cloudflare/Ruleset/index.js +2 -0
- package/lib/Cloudflare/Ruleset/index.js.map +1 -0
- package/lib/Cloudflare/SecretsStore/Secret.d.ts +1 -0
- package/lib/Cloudflare/SecretsStore/Secret.d.ts.map +1 -1
- package/lib/Cloudflare/SecretsStore/Secret.js +2 -0
- package/lib/Cloudflare/SecretsStore/Secret.js.map +1 -1
- package/lib/Cloudflare/StateStore/State.d.ts +1 -1
- package/lib/Cloudflare/StateStore/State.d.ts.map +1 -1
- package/lib/Cloudflare/Website/StaticSite.d.ts +64 -12
- package/lib/Cloudflare/Website/StaticSite.d.ts.map +1 -1
- package/lib/Cloudflare/Website/StaticSite.js +80 -30
- package/lib/Cloudflare/Website/StaticSite.js.map +1 -1
- package/lib/Cloudflare/Website/Vite.d.ts +36 -7
- package/lib/Cloudflare/Website/Vite.d.ts.map +1 -1
- package/lib/Cloudflare/Website/Vite.js +26 -8
- package/lib/Cloudflare/Website/Vite.js.map +1 -1
- package/lib/Cloudflare/Workers/Assets.d.ts +10 -4
- package/lib/Cloudflare/Workers/Assets.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Assets.js +6 -6
- package/lib/Cloudflare/Workers/Assets.js.map +1 -1
- package/lib/Cloudflare/Workers/DurableObjectChatPersistence.d.ts +69 -0
- package/lib/Cloudflare/Workers/DurableObjectChatPersistence.d.ts.map +1 -0
- package/lib/Cloudflare/Workers/DurableObjectChatPersistence.js +104 -0
- package/lib/Cloudflare/Workers/DurableObjectChatPersistence.js.map +1 -0
- package/lib/Cloudflare/Workers/DynamicWorkerLoader.d.ts +4 -4
- package/lib/Cloudflare/Workers/InferEnv.d.ts +1 -1
- package/lib/Cloudflare/Workers/InferEnv.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js +45 -11
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
- package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.d.ts +5 -4
- package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.js +4 -2
- package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.js.map +1 -1
- package/lib/Cloudflare/Workers/RpcWorker.d.ts +3 -2
- package/lib/Cloudflare/Workers/RpcWorker.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/RpcWorker.js +5 -3
- package/lib/Cloudflare/Workers/RpcWorker.js.map +1 -1
- package/lib/Cloudflare/Workers/VersionMetadata.d.ts +99 -0
- package/lib/Cloudflare/Workers/VersionMetadata.d.ts.map +1 -0
- package/lib/Cloudflare/Workers/VersionMetadata.js +65 -0
- package/lib/Cloudflare/Workers/VersionMetadata.js.map +1 -0
- package/lib/Cloudflare/Workers/VersionMetadataBinding.d.ts +35 -0
- package/lib/Cloudflare/Workers/VersionMetadataBinding.d.ts.map +1 -0
- package/lib/Cloudflare/Workers/VersionMetadataBinding.js +31 -0
- package/lib/Cloudflare/Workers/VersionMetadataBinding.js.map +1 -0
- package/lib/Cloudflare/Workers/Worker.d.ts +20 -19
- package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.js +23 -37
- package/lib/Cloudflare/Workers/Worker.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.js +16 -0
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBinding.d.ts +3 -1
- package/lib/Cloudflare/Workers/WorkerBinding.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBinding.js.map +1 -1
- package/lib/Cloudflare/Workers/Workflow.d.ts +8 -1
- package/lib/Cloudflare/Workers/Workflow.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Workflow.js +1 -0
- package/lib/Cloudflare/Workers/Workflow.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkflowBridge.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkflowBridge.js +31 -2
- package/lib/Cloudflare/Workers/WorkflowBridge.js.map +1 -1
- package/lib/Cloudflare/Workers/index.d.ts +3 -0
- package/lib/Cloudflare/Workers/index.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/index.js +3 -0
- package/lib/Cloudflare/Workers/index.js.map +1 -1
- package/lib/Cloudflare/Zaraz/ZarazConfig.d.ts.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/Deploy.d.ts +3 -2
- package/lib/Deploy.d.ts.map +1 -1
- package/lib/Deploy.js.map +1 -1
- package/lib/Destroy.d.ts +3 -2
- package/lib/Destroy.d.ts.map +1 -1
- package/lib/Destroy.js.map +1 -1
- package/lib/Diff.d.ts.map +1 -1
- package/lib/Diff.js +7 -0
- package/lib/Diff.js.map +1 -1
- package/lib/Drizzle/Postgres.d.ts +13 -12
- package/lib/Drizzle/Postgres.d.ts.map +1 -1
- package/lib/Drizzle/Postgres.js +13 -12
- package/lib/Drizzle/Postgres.js.map +1 -1
- package/lib/Drizzle/Schema.d.ts +1 -1
- package/lib/Drizzle/Schema.d.ts.map +1 -1
- package/lib/Drizzle/Schema.js +20 -9
- package/lib/Drizzle/Schema.js.map +1 -1
- package/lib/Local/RpcSerialization.js +5 -2
- package/lib/Local/RpcSerialization.js.map +1 -1
- package/lib/Output.d.ts.map +1 -1
- package/lib/Output.js +11 -10
- package/lib/Output.js.map +1 -1
- package/lib/Plan.d.ts.map +1 -1
- package/lib/Plan.js +5 -1
- package/lib/Plan.js.map +1 -1
- package/lib/Planetscale/MySQL/MySQLDatabase.d.ts +0 -2
- package/lib/Planetscale/MySQL/MySQLDatabase.d.ts.map +1 -1
- package/lib/Planetscale/MySQL/MySQLDatabase.js +1 -3
- package/lib/Planetscale/MySQL/MySQLDatabase.js.map +1 -1
- package/lib/Planetscale/Postgres/PostgresDatabase.d.ts +0 -2
- package/lib/Planetscale/Postgres/PostgresDatabase.d.ts.map +1 -1
- package/lib/Planetscale/Postgres/PostgresDatabase.js +1 -3
- package/lib/Planetscale/Postgres/PostgresDatabase.js.map +1 -1
- package/lib/Platform.d.ts +4 -4
- package/lib/Platform.d.ts.map +1 -1
- package/lib/Platform.js +27 -25
- package/lib/Platform.js.map +1 -1
- package/lib/Resource.d.ts +7 -1
- package/lib/Resource.d.ts.map +1 -1
- package/lib/Resource.js +11 -12
- package/lib/Resource.js.map +1 -1
- package/lib/Runtime.d.ts +1 -1
- package/lib/Runtime.d.ts.map +1 -1
- package/lib/Runtime.js +3 -4
- package/lib/Runtime.js.map +1 -1
- package/lib/Stack.d.ts +5 -4
- package/lib/Stack.d.ts.map +1 -1
- package/lib/Stack.js.map +1 -1
- package/lib/Test/Core.d.ts +2 -2
- package/lib/Test/Core.d.ts.map +1 -1
- package/lib/Util/effect.d.ts.map +1 -1
- package/lib/Util/effect.js +13 -15
- package/lib/Util/effect.js.map +1 -1
- package/lib/Util/poll.d.ts +0 -1
- package/lib/Util/poll.d.ts.map +1 -1
- package/lib/Util/poll.js +2 -2
- package/lib/Util/poll.js.map +1 -1
- package/lib/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +20 -20
- package/src/AWS/Lambda/BucketEventSource.ts +16 -1
- package/src/AWS/S3/Bucket.ts +78 -0
- package/src/AWS/S3/BucketNotifications.ts +10 -0
- package/src/Apply.ts +22 -3
- package/src/Auth/AuthProvider.ts +1 -1
- package/src/Binding.ts +45 -38
- package/src/Build/DevServer.ts +330 -0
- package/src/Build/Local.ts +4 -0
- package/src/Bundle/Bundle.ts +1 -1
- package/src/Cloudflare/Access.ts +1 -1
- package/src/Cloudflare/AiGateway/AiGateway.ts +1 -1
- package/src/Cloudflare/AiGateway/AiGatewayBinding.ts +8 -3
- package/src/Cloudflare/Browser/Browser.ts +84 -12
- package/src/Cloudflare/Browser/BrowserBinding.ts +205 -33
- package/src/Cloudflare/Browser/index.ts +15 -2
- package/src/Cloudflare/Container/ContainerBinding.ts +5 -10
- package/src/Cloudflare/Images/Images.ts +4 -3
- package/src/Cloudflare/Providers.ts +8 -0
- package/src/Cloudflare/RateLimit/RateLimit.ts +4 -3
- package/src/Cloudflare/Ruleset/Ruleset.ts +223 -0
- package/src/Cloudflare/Ruleset/index.ts +1 -0
- package/src/Cloudflare/SecretsStore/Secret.ts +4 -0
- package/src/Cloudflare/Website/StaticSite.ts +154 -41
- package/src/Cloudflare/Website/Vite.ts +73 -25
- package/src/Cloudflare/Workers/Assets.ts +10 -8
- package/src/Cloudflare/Workers/DurableObjectChatPersistence.ts +131 -0
- package/src/Cloudflare/Workers/DynamicWorkerLoader.ts +4 -4
- package/src/Cloudflare/Workers/InferEnv.ts +14 -12
- package/src/Cloudflare/Workers/LocalWorkerProvider.ts +54 -13
- package/src/Cloudflare/Workers/RpcDurableObjectNamespace.ts +11 -8
- package/src/Cloudflare/Workers/RpcWorker.ts +8 -7
- package/src/Cloudflare/Workers/VersionMetadata.ts +129 -0
- package/src/Cloudflare/Workers/VersionMetadataBinding.ts +82 -0
- package/src/Cloudflare/Workers/Worker.ts +66 -82
- package/src/Cloudflare/Workers/WorkerAsyncBindings.ts +14 -0
- package/src/Cloudflare/Workers/WorkerBinding.ts +4 -0
- package/src/Cloudflare/Workers/Workflow.ts +12 -1
- package/src/Cloudflare/Workers/WorkflowBridge.ts +47 -6
- package/src/Cloudflare/Workers/index.ts +3 -0
- package/src/Cloudflare/index.ts +1 -0
- package/src/Deploy.ts +2 -1
- package/src/Destroy.ts +2 -1
- package/src/Diff.ts +7 -0
- package/src/Drizzle/Postgres.ts +13 -12
- package/src/Drizzle/Schema.ts +27 -9
- package/src/Local/RpcSerialization.ts +5 -2
- package/src/Output.ts +12 -10
- package/src/Plan.ts +5 -1
- package/src/Planetscale/MySQL/MySQLDatabase.ts +1 -6
- package/src/Planetscale/Postgres/PostgresDatabase.ts +1 -5
- package/src/Platform.ts +48 -36
- package/src/Resource.ts +22 -13
- package/src/Runtime.ts +3 -7
- package/src/Stack.ts +11 -10
- package/src/Util/effect.ts +13 -17
- package/src/Util/poll.ts +3 -3
|
@@ -2,8 +2,10 @@ import type * as cf 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 Stream from "effect/Stream";
|
|
5
6
|
import * as Binding from "../../Binding.ts";
|
|
6
7
|
import type { ResourceLike } from "../../Resource.ts";
|
|
8
|
+
import type { RuntimeContext } from "../../RuntimeContext.ts";
|
|
7
9
|
import { isWorker, WorkerEnvironment } from "../Workers/Worker.ts";
|
|
8
10
|
import type { Browser as BrowserLike } from "./Browser.ts";
|
|
9
11
|
|
|
@@ -12,39 +14,143 @@ export class BrowserError extends Data.TaggedError("BrowserError")<{
|
|
|
12
14
|
cause: unknown;
|
|
13
15
|
}> {}
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
17
|
+
/** The `Response` type returned by the Cloudflare Browser Rendering binding. */
|
|
18
|
+
type BrowserResponse = Awaited<ReturnType<cf.BrowserRun["fetch"]>>;
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
/** An Effect produced by a {@link BrowserClient} operation. */
|
|
21
|
+
type BrowserEffect<A> = Effect.Effect<A, BrowserError, RuntimeContext>;
|
|
22
|
+
|
|
23
|
+
/** A byte stream produced by a binary {@link BrowserClient} action. */
|
|
24
|
+
type BrowserByteStream = Stream.Stream<
|
|
25
|
+
Uint8Array,
|
|
26
|
+
BrowserError,
|
|
27
|
+
RuntimeContext
|
|
28
|
+
>;
|
|
29
|
+
|
|
30
|
+
// Quick action option types, re-exported so callers don't reach into the
|
|
31
|
+
// `@cloudflare/workers-types` namespace directly.
|
|
32
|
+
export type BrowserScreenshotOptions = cf.BrowserRunScreenshotOptions;
|
|
33
|
+
export type BrowserPDFOptions = cf.BrowserRunPDFOptions;
|
|
34
|
+
export type BrowserContentOptions = cf.BrowserRunContentOptions;
|
|
35
|
+
export type BrowserScrapeOptions = cf.BrowserRunScrapeOptions;
|
|
36
|
+
export type BrowserLinksOptions = cf.BrowserRunLinksOptions;
|
|
37
|
+
export type BrowserSnapshotOptions = cf.BrowserRunSnapshotOptions;
|
|
38
|
+
export type BrowserJsonOptions = cf.BrowserRunJsonOptions;
|
|
39
|
+
export type BrowserMarkdownOptions = cf.BrowserRunMarkdownOptions;
|
|
40
|
+
|
|
41
|
+
// Quick action success payloads.
|
|
42
|
+
export type BrowserContentResult = cf.BrowserRunContentSuccessResponse;
|
|
43
|
+
export type BrowserScrapeResult = cf.BrowserRunScrapeSuccessResponse;
|
|
44
|
+
export type BrowserLinksResult = cf.BrowserRunLinksSuccessResponse;
|
|
45
|
+
export type BrowserSnapshotResult = cf.BrowserRunSnapshotSuccessResponse;
|
|
46
|
+
export type BrowserJsonResult = cf.BrowserRunJsonSuccessResponse;
|
|
47
|
+
export type BrowserMarkdownResult = cf.BrowserRunMarkdownSuccessResponse;
|
|
48
|
+
export type BrowserErrorResponse = cf.BrowserRunErrorResponse;
|
|
22
49
|
|
|
23
50
|
/**
|
|
24
51
|
* Effect-native client for a Cloudflare Browser Rendering binding.
|
|
25
52
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
53
|
+
* Mirrors the runtime {@link cf.BrowserRun} binding, translating its shapes
|
|
54
|
+
* into Effect-native ones: JSON quick actions resolve to their parsed success
|
|
55
|
+
* payload, and binary actions (`screenshot`, `pdf`) resolve to a `Stream` of
|
|
56
|
+
* the response bytes. Non-success responses fail with {@link BrowserError}, so
|
|
57
|
+
* callers never touch a `Promise` or `Response.json()` themselves. Use
|
|
58
|
+
* `Cloudflare.Browser.bind(browser)` (or `yield* Cloudflare.Browser(...)`)
|
|
59
|
+
* inside a Worker's init phase to obtain it.
|
|
60
|
+
*
|
|
61
|
+
* The {@link raw} accessor and {@link fetch} are the only promise-shaped
|
|
62
|
+
* escape hatches — they exist for libraries like `@cloudflare/puppeteer` that
|
|
63
|
+
* consume the binding directly.
|
|
29
64
|
*/
|
|
30
65
|
export interface BrowserClient {
|
|
31
66
|
/**
|
|
32
67
|
* Effect resolving to the raw Cloudflare Browser Rendering runtime binding.
|
|
68
|
+
*
|
|
69
|
+
* Pass it to `@cloudflare/puppeteer`'s `puppeteer.launch(binding)` to drive a
|
|
70
|
+
* full browser session.
|
|
71
|
+
*/
|
|
72
|
+
raw: Effect.Effect<cf.BrowserRun, never, RuntimeContext>;
|
|
73
|
+
/**
|
|
74
|
+
* Send a raw HTTP request to the Browser Run API and resolve to the raw
|
|
75
|
+
* `Response`. Used by libraries like `@cloudflare/puppeteer` to acquire and
|
|
76
|
+
* connect to a browser instance.
|
|
77
|
+
*/
|
|
78
|
+
fetch(
|
|
79
|
+
...args: Parameters<cf.BrowserRun["fetch"]>
|
|
80
|
+
): BrowserEffect<BrowserResponse>;
|
|
81
|
+
/**
|
|
82
|
+
* Run a Browser Run quick action, resolving to the parsed success payload
|
|
83
|
+
* (or a byte `Stream` for binary actions). Mirrors
|
|
84
|
+
* `cf.BrowserRun["quickAction"]`; the {@link screenshot}, {@link pdf},
|
|
85
|
+
* {@link content}, {@link scrape}, {@link links}, {@link snapshot},
|
|
86
|
+
* {@link json}, and {@link markdown} methods are thin wrappers over the
|
|
87
|
+
* corresponding action.
|
|
88
|
+
*/
|
|
89
|
+
quickAction(
|
|
90
|
+
action: "screenshot",
|
|
91
|
+
options: BrowserScreenshotOptions,
|
|
92
|
+
): BrowserByteStream;
|
|
93
|
+
quickAction(action: "pdf", options: BrowserPDFOptions): BrowserByteStream;
|
|
94
|
+
quickAction(
|
|
95
|
+
action: "content",
|
|
96
|
+
options: BrowserContentOptions,
|
|
97
|
+
): BrowserEffect<BrowserContentResult>;
|
|
98
|
+
quickAction(
|
|
99
|
+
action: "scrape",
|
|
100
|
+
options: BrowserScrapeOptions,
|
|
101
|
+
): BrowserEffect<BrowserScrapeResult>;
|
|
102
|
+
quickAction(
|
|
103
|
+
action: "links",
|
|
104
|
+
options: BrowserLinksOptions,
|
|
105
|
+
): BrowserEffect<BrowserLinksResult>;
|
|
106
|
+
quickAction(
|
|
107
|
+
action: "snapshot",
|
|
108
|
+
options: BrowserSnapshotOptions,
|
|
109
|
+
): BrowserEffect<BrowserSnapshotResult>;
|
|
110
|
+
quickAction(
|
|
111
|
+
action: "json",
|
|
112
|
+
options: BrowserJsonOptions,
|
|
113
|
+
): BrowserEffect<BrowserJsonResult>;
|
|
114
|
+
quickAction(
|
|
115
|
+
action: "markdown",
|
|
116
|
+
options: BrowserMarkdownOptions,
|
|
117
|
+
): BrowserEffect<BrowserMarkdownResult>;
|
|
118
|
+
/**
|
|
119
|
+
* Take a screenshot of a web page, streaming the raw image bytes.
|
|
120
|
+
*/
|
|
121
|
+
screenshot(options: BrowserScreenshotOptions): BrowserByteStream;
|
|
122
|
+
/**
|
|
123
|
+
* Generate a PDF of a web page, streaming the raw PDF bytes.
|
|
124
|
+
*/
|
|
125
|
+
pdf(options: BrowserPDFOptions): BrowserByteStream;
|
|
126
|
+
/**
|
|
127
|
+
* Get the HTML content of a web page.
|
|
128
|
+
*/
|
|
129
|
+
content(options: BrowserContentOptions): BrowserEffect<BrowserContentResult>;
|
|
130
|
+
/**
|
|
131
|
+
* Scrape elements from a web page by CSS selector.
|
|
132
|
+
*/
|
|
133
|
+
scrape(options: BrowserScrapeOptions): BrowserEffect<BrowserScrapeResult>;
|
|
134
|
+
/**
|
|
135
|
+
* Extract all links from a web page.
|
|
136
|
+
*/
|
|
137
|
+
links(options: BrowserLinksOptions): BrowserEffect<BrowserLinksResult>;
|
|
138
|
+
/**
|
|
139
|
+
* Get both the HTML content and a base64-encoded screenshot of a web page.
|
|
33
140
|
*/
|
|
34
|
-
|
|
141
|
+
snapshot(
|
|
142
|
+
options: BrowserSnapshotOptions,
|
|
143
|
+
): BrowserEffect<BrowserSnapshotResult>;
|
|
35
144
|
/**
|
|
36
|
-
*
|
|
145
|
+
* Extract structured JSON data from a web page using AI.
|
|
37
146
|
*/
|
|
38
|
-
|
|
39
|
-
puppeteer: BrowserPuppeteer<Browser>,
|
|
40
|
-
): Effect.Effect<Browser, BrowserError, WorkerEnvironment>;
|
|
147
|
+
json(options: BrowserJsonOptions): BrowserEffect<BrowserJsonResult>;
|
|
41
148
|
/**
|
|
42
|
-
*
|
|
149
|
+
* Convert a web page to Markdown.
|
|
43
150
|
*/
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
): Effect.Effect<A, BrowserError | E, WorkerEnvironment | R>;
|
|
151
|
+
markdown(
|
|
152
|
+
options: BrowserMarkdownOptions,
|
|
153
|
+
): BrowserEffect<BrowserMarkdownResult>;
|
|
48
154
|
}
|
|
49
155
|
|
|
50
156
|
export class BrowserBinding extends Binding.Service<
|
|
@@ -56,14 +162,14 @@ export const BrowserBindingLive = Layer.effect(
|
|
|
56
162
|
BrowserBinding,
|
|
57
163
|
Effect.gen(function* () {
|
|
58
164
|
const Policy = yield* BrowserBindingPolicy;
|
|
165
|
+
const env = yield* WorkerEnvironment;
|
|
59
166
|
|
|
60
167
|
return Effect.fn(function* (browser: BrowserLike) {
|
|
61
168
|
yield* Policy(browser);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
);
|
|
169
|
+
const raw: Effect.Effect<cf.BrowserRun, never, RuntimeContext> =
|
|
170
|
+
Effect.sync(
|
|
171
|
+
() => (env as Record<string, cf.BrowserRun>)[browser.name]!,
|
|
172
|
+
);
|
|
67
173
|
return makeBrowserClient(raw);
|
|
68
174
|
});
|
|
69
175
|
}),
|
|
@@ -106,23 +212,89 @@ const tryPromise = <T>(fn: () => Promise<T>): Effect.Effect<T, BrowserError> =>
|
|
|
106
212
|
}),
|
|
107
213
|
});
|
|
108
214
|
|
|
215
|
+
/** Actions whose successful response is raw binary rather than JSON. */
|
|
216
|
+
const BINARY_ACTIONS = new Set(["screenshot", "pdf"]);
|
|
217
|
+
|
|
218
|
+
/** Build a {@link BrowserError} from a non-success Browser Run response. */
|
|
219
|
+
const failResponse = (
|
|
220
|
+
action: string,
|
|
221
|
+
response: BrowserResponse,
|
|
222
|
+
): Effect.Effect<never, BrowserError> =>
|
|
223
|
+
tryPromise(() => response.text()).pipe(
|
|
224
|
+
Effect.flatMap((body) => {
|
|
225
|
+
let cause: unknown = body;
|
|
226
|
+
try {
|
|
227
|
+
cause = JSON.parse(body);
|
|
228
|
+
} catch {
|
|
229
|
+
// keep the raw text as the cause
|
|
230
|
+
}
|
|
231
|
+
const message =
|
|
232
|
+
(cause as cf.BrowserRunErrorResponse | undefined)?.errors?.[0]
|
|
233
|
+
?.message ??
|
|
234
|
+
`Browser Rendering '${action}' failed with status ${response.status}`;
|
|
235
|
+
return Effect.fail(new BrowserError({ message, cause }));
|
|
236
|
+
}),
|
|
237
|
+
);
|
|
238
|
+
|
|
109
239
|
/** @internal */
|
|
110
240
|
export const makeBrowserClient = (
|
|
111
|
-
raw: Effect.Effect<cf.
|
|
241
|
+
raw: Effect.Effect<cf.BrowserRun, never, RuntimeContext>,
|
|
112
242
|
): BrowserClient => {
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
243
|
+
const respond = (
|
|
244
|
+
action: string,
|
|
245
|
+
options: unknown,
|
|
246
|
+
): Effect.Effect<BrowserResponse, BrowserError, RuntimeContext> =>
|
|
116
247
|
raw.pipe(
|
|
117
|
-
Effect.flatMap((binding) =>
|
|
248
|
+
Effect.flatMap((binding) =>
|
|
249
|
+
tryPromise(() => binding.quickAction(action as any, options as any)),
|
|
250
|
+
),
|
|
251
|
+
Effect.flatMap((response) =>
|
|
252
|
+
response.ok ? Effect.succeed(response) : failResponse(action, response),
|
|
253
|
+
),
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
const jsonAction = <T>(action: string, options: unknown): BrowserEffect<T> =>
|
|
257
|
+
respond(action, options).pipe(
|
|
258
|
+
Effect.flatMap((response) =>
|
|
259
|
+
tryPromise(() => response.json() as Promise<T>),
|
|
260
|
+
),
|
|
118
261
|
);
|
|
119
262
|
|
|
263
|
+
const streamAction = (action: string, options: unknown): BrowserByteStream =>
|
|
264
|
+
respond(action, options).pipe(
|
|
265
|
+
Effect.map((response) =>
|
|
266
|
+
Stream.fromReadableStream({
|
|
267
|
+
evaluate: () =>
|
|
268
|
+
response.body as any as ReadableStream<Uint8Array<ArrayBufferLike>>,
|
|
269
|
+
onError: (cause) =>
|
|
270
|
+
new BrowserError({
|
|
271
|
+
message: `Browser Rendering '${action}' stream failed`,
|
|
272
|
+
cause,
|
|
273
|
+
}),
|
|
274
|
+
}),
|
|
275
|
+
),
|
|
276
|
+
Stream.unwrap,
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
const quickAction = ((action: string, options: unknown) =>
|
|
280
|
+
BINARY_ACTIONS.has(action)
|
|
281
|
+
? streamAction(action, options)
|
|
282
|
+
: jsonAction(action, options)) as BrowserClient["quickAction"];
|
|
283
|
+
|
|
120
284
|
return {
|
|
121
285
|
raw,
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
tryPromise(() => browser.close()),
|
|
286
|
+
fetch: (...args) =>
|
|
287
|
+
raw.pipe(
|
|
288
|
+
Effect.flatMap((binding) => tryPromise(() => binding.fetch(...args))),
|
|
126
289
|
),
|
|
290
|
+
quickAction,
|
|
291
|
+
screenshot: (options) => streamAction("screenshot", options),
|
|
292
|
+
pdf: (options) => streamAction("pdf", options),
|
|
293
|
+
content: (options) => jsonAction("content", options),
|
|
294
|
+
scrape: (options) => jsonAction("scrape", options),
|
|
295
|
+
links: (options) => jsonAction("links", options),
|
|
296
|
+
snapshot: (options) => jsonAction("snapshot", options),
|
|
297
|
+
json: (options) => jsonAction("json", options),
|
|
298
|
+
markdown: (options) => jsonAction("markdown", options),
|
|
127
299
|
} satisfies BrowserClient;
|
|
128
300
|
};
|
|
@@ -6,6 +6,19 @@ export {
|
|
|
6
6
|
BrowserBindingPolicyLive,
|
|
7
7
|
BrowserError,
|
|
8
8
|
type BrowserClient,
|
|
9
|
-
type
|
|
10
|
-
type
|
|
9
|
+
type BrowserScreenshotOptions,
|
|
10
|
+
type BrowserPDFOptions,
|
|
11
|
+
type BrowserContentOptions,
|
|
12
|
+
type BrowserScrapeOptions,
|
|
13
|
+
type BrowserLinksOptions,
|
|
14
|
+
type BrowserSnapshotOptions,
|
|
15
|
+
type BrowserJsonOptions,
|
|
16
|
+
type BrowserMarkdownOptions,
|
|
17
|
+
type BrowserContentResult,
|
|
18
|
+
type BrowserScrapeResult,
|
|
19
|
+
type BrowserLinksResult,
|
|
20
|
+
type BrowserSnapshotResult,
|
|
21
|
+
type BrowserJsonResult,
|
|
22
|
+
type BrowserMarkdownResult,
|
|
23
|
+
type BrowserErrorResponse,
|
|
11
24
|
} from "./BrowserBinding.ts";
|
|
@@ -18,16 +18,11 @@ export const bindContainer = Effect.fnUntraced(function* <Shape, Req = never>(
|
|
|
18
18
|
) {
|
|
19
19
|
const namespace = yield* DurableObjectNamespace;
|
|
20
20
|
|
|
21
|
-
const container =
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
: Effect.isEffect(containerEff)
|
|
27
|
-
? yield* containerEff as unknown as Effect.Effect<
|
|
28
|
-
ContainerApplication & Rpc<Shape>
|
|
29
|
-
>
|
|
30
|
-
: containerEff;
|
|
21
|
+
const container = Effect.isEffect(containerEff)
|
|
22
|
+
? yield* containerEff as unknown as Effect.Effect<
|
|
23
|
+
ContainerApplication & Rpc<Shape>
|
|
24
|
+
>
|
|
25
|
+
: containerEff;
|
|
31
26
|
|
|
32
27
|
yield* container.bind`${namespace}`({
|
|
33
28
|
durableObjects: {
|
|
@@ -32,9 +32,10 @@ type BindEffect = Effect.Effect<ImagesClient, never, ImagesBinding>;
|
|
|
32
32
|
* Worker and returns the runtime {@link ImagesClient} — no separate `.bind(...)`
|
|
33
33
|
* step required.
|
|
34
34
|
*
|
|
35
|
-
* The divergence is achieved via `[Symbol.iterator]`: the object is
|
|
36
|
-
* `Effect` (so `InferEnv`
|
|
37
|
-
*
|
|
35
|
+
* The divergence is achieved via `[Symbol.iterator]`: the object is
|
|
36
|
+
* deliberately not an `Effect` (so `InferEnv` and the Worker `env` resolver
|
|
37
|
+
* keep it as the native `ImagesBinding` rather than `yield*`-ing it), but it
|
|
38
|
+
* is iterable as one when `yield*`-ed.
|
|
38
39
|
*/
|
|
39
40
|
export interface Images {
|
|
40
41
|
kind: ImagesTypeId;
|
|
@@ -8,6 +8,7 @@ import * as Schedule from "effect/Schedule";
|
|
|
8
8
|
import { CredentialsStoreLive } from "../Auth/Credentials.ts";
|
|
9
9
|
import { ProfileLive } from "../Auth/Profile.ts";
|
|
10
10
|
import { Command } from "../Build/Command.ts";
|
|
11
|
+
import { DevServer, DevServerProvider } from "../Build/DevServer.ts";
|
|
11
12
|
import * as Build from "../Build/index.ts";
|
|
12
13
|
import { KeyPair, KeyPairProvider } from "../KeyPair.ts";
|
|
13
14
|
import * as Provider from "../Provider.ts";
|
|
@@ -31,6 +32,7 @@ import * as KV from "./KV/index.ts";
|
|
|
31
32
|
import * as Queue from "./Queue/index.ts";
|
|
32
33
|
import * as R2 from "./R2/index.ts";
|
|
33
34
|
import * as RateLimit from "./RateLimit/index.ts";
|
|
35
|
+
import * as Ruleset from "./Ruleset/index.ts";
|
|
34
36
|
import * as SecretsStore from "./SecretsStore/index.ts";
|
|
35
37
|
import * as Tunnel from "./Tunnel/index.ts";
|
|
36
38
|
import * as Vectorize from "./Vectorize/index.ts";
|
|
@@ -66,6 +68,7 @@ export const providers = () =>
|
|
|
66
68
|
Containers.Container,
|
|
67
69
|
D1.D1ConnectionPolicy,
|
|
68
70
|
D1.D1Database,
|
|
71
|
+
DevServer,
|
|
69
72
|
Dns.DnsReadPolicy,
|
|
70
73
|
Dns.DnsReadWritePolicy,
|
|
71
74
|
Dns.DnsWritePolicy,
|
|
@@ -85,6 +88,7 @@ export const providers = () =>
|
|
|
85
88
|
R2.R2Bucket,
|
|
86
89
|
R2.R2BucketBindingPolicy,
|
|
87
90
|
RateLimit.RateLimitBindingPolicy,
|
|
91
|
+
Ruleset.Ruleset,
|
|
88
92
|
SecretsStore.SecretBindingPolicy,
|
|
89
93
|
SecretsStore.SecretsStore,
|
|
90
94
|
SecretsStore.Secret,
|
|
@@ -101,6 +105,7 @@ export const providers = () =>
|
|
|
101
105
|
Workers.BindWorkerPolicy,
|
|
102
106
|
Workers.CronEventSourcePolicy,
|
|
103
107
|
Workers.FetchPolicy,
|
|
108
|
+
Workers.VersionMetadataBindingPolicy,
|
|
104
109
|
Workers.Worker,
|
|
105
110
|
Workflows.WorkflowResource,
|
|
106
111
|
Zaraz.ZarazConfig,
|
|
@@ -119,6 +124,7 @@ export const providers = () =>
|
|
|
119
124
|
Containers.ContainerProvider(),
|
|
120
125
|
D1.D1ConnectionPolicyLive,
|
|
121
126
|
D1.DatabaseProvider(),
|
|
127
|
+
DevServerProvider(),
|
|
122
128
|
Dns.DnsReadPolicyLive,
|
|
123
129
|
Dns.DnsReadWritePolicyLive,
|
|
124
130
|
Dns.DnsWritePolicyLive,
|
|
@@ -138,6 +144,7 @@ export const providers = () =>
|
|
|
138
144
|
R2.R2BucketBindingPolicyLive,
|
|
139
145
|
R2.R2BucketProvider(),
|
|
140
146
|
RateLimit.RateLimitBindingPolicyLive,
|
|
147
|
+
Ruleset.RulesetProvider(),
|
|
141
148
|
SecretsStore.SecretBindingPolicyLive,
|
|
142
149
|
SecretsStore.SecretsStoreProvider(),
|
|
143
150
|
SecretsStore.StoreSecretProvider(),
|
|
@@ -152,6 +159,7 @@ export const providers = () =>
|
|
|
152
159
|
Workers.BindWorkerPolicyLive,
|
|
153
160
|
Workers.CronEventSourcePolicyLive,
|
|
154
161
|
Workers.FetchPolicyLive,
|
|
162
|
+
Workers.VersionMetadataBindingPolicyLive,
|
|
155
163
|
Workers.WorkerProvider(),
|
|
156
164
|
Workflows.WorkflowProvider(),
|
|
157
165
|
Zaraz.ZarazConfigProvider(),
|
|
@@ -52,9 +52,10 @@ type BindEffect = Effect.Effect<RateLimitClient, never, RateLimitBinding>;
|
|
|
52
52
|
* Worker and returns the runtime {@link RateLimitClient} — no separate
|
|
53
53
|
* `.bind(...)` step required.
|
|
54
54
|
*
|
|
55
|
-
* The divergence is achieved via `[Symbol.iterator]`: the object is
|
|
56
|
-
* `Effect` (so `InferEnv`
|
|
57
|
-
* `
|
|
55
|
+
* The divergence is achieved via `[Symbol.iterator]`: the object is
|
|
56
|
+
* deliberately not an `Effect` (so `InferEnv` and the Worker `env` resolver
|
|
57
|
+
* keep it as the native `cf.RateLimit` rather than `yield*`-ing it), but it is
|
|
58
|
+
* iterable as one when `yield*`-ed.
|
|
58
59
|
*/
|
|
59
60
|
export interface RateLimit {
|
|
60
61
|
kind: RateLimitTypeId;
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import * as rulesets from "@distilled.cloud/cloudflare/rulesets";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import { deepEqual, isResolved } from "../../Diff.ts";
|
|
4
|
+
import { createPhysicalName } from "../../PhysicalName.ts";
|
|
5
|
+
import * as Provider from "../../Provider.ts";
|
|
6
|
+
import { Resource } from "../../Resource.ts";
|
|
7
|
+
import type { Providers } from "../Providers.ts";
|
|
8
|
+
import type { Zone, ZoneAttributes } from "../Zone/index.ts";
|
|
9
|
+
|
|
10
|
+
export type RulesetPhase = rulesets.CreateRulesetForZoneRequest["phase"];
|
|
11
|
+
export type RulesetRule = NonNullable<
|
|
12
|
+
rulesets.PutPhasForZoneRequest["rules"]
|
|
13
|
+
>[number];
|
|
14
|
+
export type RulesetOutputRule = Omit<
|
|
15
|
+
NonNullable<rulesets.GetPhasResponse["rules"]>[number],
|
|
16
|
+
"lastUpdated" | "version"
|
|
17
|
+
>;
|
|
18
|
+
|
|
19
|
+
export type RulesetProps = {
|
|
20
|
+
/**
|
|
21
|
+
* Zone to apply the ruleset to. Pass a `Cloudflare.Zone`.
|
|
22
|
+
*/
|
|
23
|
+
zone: Zone;
|
|
24
|
+
/**
|
|
25
|
+
* Ruleset phase entrypoint to own.
|
|
26
|
+
*/
|
|
27
|
+
phase: RulesetPhase;
|
|
28
|
+
/**
|
|
29
|
+
* Rules to apply to the phase entrypoint.
|
|
30
|
+
*/
|
|
31
|
+
rules: RulesetRule[];
|
|
32
|
+
/**
|
|
33
|
+
* Human-readable name for the ruleset.
|
|
34
|
+
* @default ${app}-${stage}-${id}
|
|
35
|
+
*/
|
|
36
|
+
name?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Description for the ruleset.
|
|
39
|
+
*/
|
|
40
|
+
description?: string;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export type RulesetKind =
|
|
44
|
+
| "managed"
|
|
45
|
+
| "custom"
|
|
46
|
+
| "root"
|
|
47
|
+
| "zone"
|
|
48
|
+
| (string & {});
|
|
49
|
+
|
|
50
|
+
export type Ruleset = Resource<
|
|
51
|
+
"Cloudflare.Ruleset",
|
|
52
|
+
RulesetProps,
|
|
53
|
+
{
|
|
54
|
+
/** The unique ID of the ruleset (Cloudflare `id`). */
|
|
55
|
+
rulesetId: string;
|
|
56
|
+
/**
|
|
57
|
+
* Zone the ruleset phase entrypoint belongs to. Alchemy-flattened
|
|
58
|
+
* identifier — not part of Cloudflare's phase-entrypoint response.
|
|
59
|
+
*/
|
|
60
|
+
zoneId: string;
|
|
61
|
+
/** The kind of the ruleset. */
|
|
62
|
+
kind: RulesetKind;
|
|
63
|
+
/** The human-readable name of the ruleset. */
|
|
64
|
+
name: string;
|
|
65
|
+
/** The phase of the ruleset. */
|
|
66
|
+
phase: RulesetPhase;
|
|
67
|
+
/** An informative description of the ruleset. */
|
|
68
|
+
description: string | undefined;
|
|
69
|
+
/** The list of rules in the ruleset. */
|
|
70
|
+
rules: RulesetOutputRule[];
|
|
71
|
+
/** The timestamp of when the ruleset was last modified. */
|
|
72
|
+
lastUpdated: string;
|
|
73
|
+
/** The version of the ruleset. */
|
|
74
|
+
version: string;
|
|
75
|
+
},
|
|
76
|
+
never,
|
|
77
|
+
Providers
|
|
78
|
+
>;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* A Cloudflare Ruleset phase entrypoint for a zone.
|
|
82
|
+
*
|
|
83
|
+
* This resource owns the entire ruleset for a phase entrypoint. Rules managed
|
|
84
|
+
* elsewhere in the same phase can be overwritten on deploy.
|
|
85
|
+
*
|
|
86
|
+
* @section WAF Rules
|
|
87
|
+
* @example Block probes in the custom firewall phase
|
|
88
|
+
* ```typescript
|
|
89
|
+
* const zone = yield* Cloudflare.Zone("MyZone", { name: "example.com" });
|
|
90
|
+
* const waf = yield* Cloudflare.Ruleset("WafRules", {
|
|
91
|
+
* zone,
|
|
92
|
+
* phase: "http_request_firewall_custom",
|
|
93
|
+
* rules: [
|
|
94
|
+
* {
|
|
95
|
+
* description: "Block exploit probes",
|
|
96
|
+
* expression: `lower(http.request.uri.path) contains "/.env"`,
|
|
97
|
+
* action: "block",
|
|
98
|
+
* },
|
|
99
|
+
* ],
|
|
100
|
+
* });
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export const Ruleset = Resource<Ruleset>("Cloudflare.Ruleset")({});
|
|
104
|
+
|
|
105
|
+
const isNotFoundError = (error: unknown): boolean =>
|
|
106
|
+
typeof error === "object" &&
|
|
107
|
+
error !== null &&
|
|
108
|
+
(("status" in error && (error as { status: unknown }).status === 404) ||
|
|
109
|
+
("_tag" in error && (error as { _tag: unknown })._tag === "NotFound"));
|
|
110
|
+
|
|
111
|
+
// A `Zone` prop is resolved to its attributes before a lifecycle op runs, so
|
|
112
|
+
// `zone.zoneId` is normally a plain string even though the `Zone` resource
|
|
113
|
+
// type statically exposes it as an `Output`. During `diff` (plan time) the
|
|
114
|
+
// zone can still be unresolved — e.g. when it's being created in the same
|
|
115
|
+
// deploy — in which case `zoneId` is not yet a string. Callers must treat a
|
|
116
|
+
// non-string result as "not resolved yet".
|
|
117
|
+
const zoneIdOf = (zone: Zone): string | undefined => {
|
|
118
|
+
const zoneId = (zone as unknown as Partial<ZoneAttributes>).zoneId;
|
|
119
|
+
return typeof zoneId === "string" ? zoneId : undefined;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const RulesetProvider = () =>
|
|
123
|
+
Provider.effect(
|
|
124
|
+
Ruleset,
|
|
125
|
+
Effect.gen(function* () {
|
|
126
|
+
const getPhas = yield* rulesets.getPhasForZone;
|
|
127
|
+
const putPhas = yield* rulesets.putPhasForZone;
|
|
128
|
+
|
|
129
|
+
const createRulesetName = (id: string, name: string | undefined) =>
|
|
130
|
+
Effect.gen(function* () {
|
|
131
|
+
return name ?? (yield* createPhysicalName({ id }));
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
stables: ["zoneId", "phase"],
|
|
136
|
+
diff: Effect.fn(function* ({ id, olds, news, output }) {
|
|
137
|
+
if (!isResolved(news)) return undefined;
|
|
138
|
+
const desiredZoneId = zoneIdOf(news.zone);
|
|
139
|
+
|
|
140
|
+
// The desired zone id may still be an unresolved Output (e.g. the
|
|
141
|
+
// zone is being created in the same deploy). Only make a zone-change
|
|
142
|
+
// replacement decision once we have a concrete id.
|
|
143
|
+
if (desiredZoneId !== undefined) {
|
|
144
|
+
if (output?.zoneId && desiredZoneId !== output.zoneId) {
|
|
145
|
+
return { action: "replace" } as const;
|
|
146
|
+
}
|
|
147
|
+
const oldZoneId = olds.zone ? zoneIdOf(olds.zone) : undefined;
|
|
148
|
+
if (oldZoneId !== undefined && oldZoneId !== desiredZoneId) {
|
|
149
|
+
return { action: "replace" } as const;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (olds.phase !== news.phase) {
|
|
153
|
+
return { action: "replace" } as const;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const oldName =
|
|
157
|
+
output?.name ?? (yield* createRulesetName(id, olds.name));
|
|
158
|
+
const name = yield* createRulesetName(id, news.name);
|
|
159
|
+
if (
|
|
160
|
+
oldName !== name ||
|
|
161
|
+
olds.description !== news.description ||
|
|
162
|
+
!deepEqual(olds.rules, news.rules)
|
|
163
|
+
) {
|
|
164
|
+
return { action: "update" } as const;
|
|
165
|
+
}
|
|
166
|
+
}),
|
|
167
|
+
reconcile: Effect.fn(function* ({ id, news, output }) {
|
|
168
|
+
const zoneId = output?.zoneId ?? zoneIdOf(news.zone);
|
|
169
|
+
if (zoneId === undefined) {
|
|
170
|
+
return yield* Effect.fail(
|
|
171
|
+
new Error("Cloudflare Ruleset: zone id is not resolved"),
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
const name = yield* createRulesetName(id, news.name ?? output?.name);
|
|
175
|
+
const ruleset = yield* putPhas({
|
|
176
|
+
zoneId,
|
|
177
|
+
rulesetPhase: news.phase,
|
|
178
|
+
name,
|
|
179
|
+
description: news.description,
|
|
180
|
+
rules: news.rules,
|
|
181
|
+
});
|
|
182
|
+
return toRulesetAttributes(zoneId, ruleset);
|
|
183
|
+
}),
|
|
184
|
+
delete: Effect.fn(function* ({ olds, output }) {
|
|
185
|
+
yield* putPhas({
|
|
186
|
+
zoneId: output.zoneId,
|
|
187
|
+
rulesetPhase: olds.phase,
|
|
188
|
+
name: output.name,
|
|
189
|
+
description: output.description,
|
|
190
|
+
rules: [],
|
|
191
|
+
}).pipe(Effect.catchIf(isNotFoundError, () => Effect.void));
|
|
192
|
+
}),
|
|
193
|
+
read: Effect.fn(function* ({ olds, output }) {
|
|
194
|
+
const zoneId = output?.zoneId ?? zoneIdOf(olds.zone);
|
|
195
|
+
if (zoneId === undefined) return undefined;
|
|
196
|
+
return yield* getPhas({
|
|
197
|
+
zoneId,
|
|
198
|
+
rulesetPhase: output?.phase ?? olds.phase,
|
|
199
|
+
}).pipe(
|
|
200
|
+
Effect.map((ruleset) => toRulesetAttributes(zoneId, ruleset)),
|
|
201
|
+
Effect.catchIf(isNotFoundError, () => Effect.succeed(undefined)),
|
|
202
|
+
);
|
|
203
|
+
}),
|
|
204
|
+
};
|
|
205
|
+
}),
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
export const toRulesetAttributes = (
|
|
209
|
+
zoneId: string,
|
|
210
|
+
ruleset: rulesets.GetPhasResponse | rulesets.PutPhasResponse,
|
|
211
|
+
): Ruleset["Attributes"] => ({
|
|
212
|
+
rulesetId: ruleset.id,
|
|
213
|
+
zoneId,
|
|
214
|
+
kind: ruleset.kind,
|
|
215
|
+
name: ruleset.name,
|
|
216
|
+
phase: ruleset.phase,
|
|
217
|
+
description: ruleset.description ?? undefined,
|
|
218
|
+
rules: (ruleset.rules ?? []).map(
|
|
219
|
+
({ lastUpdated: _lastUpdated, version: _version, ...rule }) => rule,
|
|
220
|
+
),
|
|
221
|
+
lastUpdated: ruleset.lastUpdated,
|
|
222
|
+
version: ruleset.version,
|
|
223
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Ruleset.ts";
|
|
@@ -54,6 +54,10 @@ export type Secret = Resource<
|
|
|
54
54
|
Providers
|
|
55
55
|
>;
|
|
56
56
|
|
|
57
|
+
export const isSecret = (value: unknown): value is Secret =>
|
|
58
|
+
typeof value === "object" &&
|
|
59
|
+
(value as any)?.Type === "Cloudflare.SecretsStore.Secret";
|
|
60
|
+
|
|
57
61
|
export type SecretStatus = "pending" | "active" | "deleted";
|
|
58
62
|
|
|
59
63
|
// Distilled widened generated string enums to open unions (`string & {}`); the
|