alchemy 0.90.1 → 0.92.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/alchemy.js +3 -13
- package/bin/commands/util.ts +0 -3
- package/lib/cloudflare/astro/astro.d.ts +4 -4
- package/lib/cloudflare/astro/astro.d.ts.map +1 -1
- package/lib/cloudflare/astro/astro.js +2 -2
- package/lib/cloudflare/astro/astro.js.map +1 -1
- package/lib/cloudflare/auth.d.ts +0 -3
- package/lib/cloudflare/auth.d.ts.map +1 -1
- package/lib/cloudflare/auth.js +0 -3
- package/lib/cloudflare/auth.js.map +1 -1
- package/lib/cloudflare/bindings.d.ts +10 -2
- package/lib/cloudflare/bindings.d.ts.map +1 -1
- package/lib/cloudflare/bindings.js.map +1 -1
- package/lib/cloudflare/bound.d.ts +2 -1
- package/lib/cloudflare/bound.d.ts.map +1 -1
- package/lib/cloudflare/bucket.d.ts.map +1 -1
- package/lib/cloudflare/bucket.js +3 -1
- package/lib/cloudflare/bucket.js.map +1 -1
- package/lib/cloudflare/bun-spa/bun-spa.d.ts +3 -3
- package/lib/cloudflare/bun-spa/bun-spa.d.ts.map +1 -1
- package/lib/cloudflare/bun-spa/bun-spa.js.map +1 -1
- package/lib/cloudflare/bundle/plugin-wasm.d.ts.map +1 -1
- package/lib/cloudflare/bundle/plugin-wasm.js +20 -2
- package/lib/cloudflare/bundle/plugin-wasm.js.map +1 -1
- package/lib/cloudflare/container.d.ts +7 -0
- package/lib/cloudflare/container.d.ts.map +1 -1
- package/lib/cloudflare/container.js +1 -1
- package/lib/cloudflare/container.js.map +1 -1
- package/lib/cloudflare/custom-domain.d.ts +7 -0
- package/lib/cloudflare/custom-domain.d.ts.map +1 -1
- package/lib/cloudflare/custom-domain.js +3 -1
- package/lib/cloudflare/custom-domain.js.map +1 -1
- package/lib/cloudflare/email-address.d.ts +11 -2
- package/lib/cloudflare/email-address.d.ts.map +1 -1
- package/lib/cloudflare/email-address.js +20 -8
- package/lib/cloudflare/email-address.js.map +1 -1
- package/lib/cloudflare/email-catch-all.d.ts +13 -5
- package/lib/cloudflare/email-catch-all.d.ts.map +1 -1
- package/lib/cloudflare/email-catch-all.js +21 -4
- package/lib/cloudflare/email-catch-all.js.map +1 -1
- package/lib/cloudflare/email-common.d.ts +4 -0
- package/lib/cloudflare/email-common.d.ts.map +1 -0
- package/lib/cloudflare/email-common.js +7 -0
- package/lib/cloudflare/email-common.js.map +1 -0
- package/lib/cloudflare/email-routing.d.ts +1 -0
- package/lib/cloudflare/email-routing.d.ts.map +1 -1
- package/lib/cloudflare/email-routing.js +6 -2
- package/lib/cloudflare/email-routing.js.map +1 -1
- package/lib/cloudflare/email-rule.d.ts +4 -3
- package/lib/cloudflare/email-rule.d.ts.map +1 -1
- package/lib/cloudflare/email-rule.js +33 -4
- package/lib/cloudflare/email-rule.js.map +1 -1
- package/lib/cloudflare/email-sender.d.ts +38 -0
- package/lib/cloudflare/email-sender.d.ts.map +1 -0
- package/lib/cloudflare/email-sender.js +23 -0
- package/lib/cloudflare/email-sender.js.map +1 -0
- 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/cloudflare/miniflare/build-worker-options.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/build-worker-options.js +29 -0
- package/lib/cloudflare/miniflare/build-worker-options.js.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-controller.js +14 -1
- package/lib/cloudflare/miniflare/miniflare-controller.js.map +1 -1
- package/lib/cloudflare/nuxt/nuxt.d.ts +4 -4
- package/lib/cloudflare/nuxt/nuxt.d.ts.map +1 -1
- package/lib/cloudflare/nuxt/nuxt.js.map +1 -1
- package/lib/cloudflare/react-router/react-router.d.ts +4 -4
- package/lib/cloudflare/react-router/react-router.d.ts.map +1 -1
- package/lib/cloudflare/react-router/react-router.js.map +1 -1
- package/lib/cloudflare/redwood/redwood.d.ts +4 -4
- package/lib/cloudflare/redwood/redwood.d.ts.map +1 -1
- package/lib/cloudflare/redwood/redwood.js.map +1 -1
- package/lib/cloudflare/route.d.ts +7 -0
- package/lib/cloudflare/route.d.ts.map +1 -1
- package/lib/cloudflare/route.js +1 -1
- package/lib/cloudflare/route.js.map +1 -1
- package/lib/cloudflare/sveltekit/sveltekit.d.ts +4 -4
- package/lib/cloudflare/sveltekit/sveltekit.d.ts.map +1 -1
- package/lib/cloudflare/sveltekit/sveltekit.js.map +1 -1
- package/lib/cloudflare/tanstack-start/tanstack-start.d.ts +4 -4
- package/lib/cloudflare/tanstack-start/tanstack-start.d.ts.map +1 -1
- package/lib/cloudflare/tanstack-start/tanstack-start.js.map +1 -1
- package/lib/cloudflare/vite/vite.d.ts +4 -4
- package/lib/cloudflare/vite/vite.d.ts.map +1 -1
- package/lib/cloudflare/vite/vite.js.map +1 -1
- package/lib/cloudflare/website.d.ts +4 -4
- package/lib/cloudflare/website.d.ts.map +1 -1
- package/lib/cloudflare/website.js.map +1 -1
- package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
- package/lib/cloudflare/worker-metadata.js +9 -0
- package/lib/cloudflare/worker-metadata.js.map +1 -1
- package/lib/cloudflare/worker.d.ts +15 -0
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +14 -2
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/cloudflare/wrangler.json.js +13 -0
- package/lib/cloudflare/wrangler.json.js.map +1 -1
- package/package.json +4 -4
- package/src/cloudflare/astro/astro.ts +14 -13
- package/src/cloudflare/auth.ts +0 -3
- package/src/cloudflare/bindings.ts +11 -0
- package/src/cloudflare/bound.ts +56 -53
- package/src/cloudflare/bucket.ts +1 -0
- package/src/cloudflare/bun-spa/bun-spa.ts +15 -6
- package/src/cloudflare/bundle/plugin-wasm.ts +21 -2
- package/src/cloudflare/container.ts +9 -1
- package/src/cloudflare/custom-domain.ts +11 -1
- package/src/cloudflare/email-address.ts +39 -12
- package/src/cloudflare/email-catch-all.ts +41 -10
- package/src/cloudflare/email-common.ts +11 -0
- package/src/cloudflare/email-routing.ts +7 -2
- package/src/cloudflare/email-rule.ts +43 -7
- package/src/cloudflare/email-sender.ts +49 -0
- package/src/cloudflare/index.ts +1 -0
- package/src/cloudflare/miniflare/build-worker-options.ts +69 -1
- package/src/cloudflare/miniflare/miniflare-controller.ts +18 -1
- package/src/cloudflare/nuxt/nuxt.ts +12 -8
- package/src/cloudflare/react-router/react-router.ts +14 -7
- package/src/cloudflare/redwood/redwood.ts +12 -8
- package/src/cloudflare/route.ts +9 -1
- package/src/cloudflare/sveltekit/sveltekit.ts +14 -7
- package/src/cloudflare/tanstack-start/tanstack-start.ts +14 -7
- package/src/cloudflare/vite/vite.ts +12 -8
- package/src/cloudflare/website.ts +13 -12
- package/src/cloudflare/worker-metadata.ts +8 -0
- package/src/cloudflare/worker.ts +36 -2
- package/src/cloudflare/wrangler.json.ts +17 -0
- package/workers/cloudflare-state-store.js +57 -57
- package/workers/remote-binding-proxy.js +7 -3
- package/workers/remote-binding-proxy.ts +20 -3
- package/workers/tunnel-proxy.js +1 -1
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import type { Context } from "../context.ts";
|
|
2
|
-
import { Resource } from "../resource.ts";
|
|
2
|
+
import { Resource, ResourceKind } from "../resource.ts";
|
|
3
3
|
import { type CloudflareApiOptions, createCloudflareApi } from "./api.ts";
|
|
4
|
-
import
|
|
4
|
+
import { resolveEmailZoneId } from "./email-common.ts";
|
|
5
|
+
import type { EmailAction } from "./email-rule.ts";
|
|
5
6
|
import type { CloudflareResponse } from "./response.ts";
|
|
6
7
|
import type { Zone } from "./zone.ts";
|
|
7
8
|
|
|
9
|
+
export interface EmailCatchAllMatcher {
|
|
10
|
+
type: "all";
|
|
11
|
+
}
|
|
12
|
+
|
|
8
13
|
/**
|
|
9
14
|
* Cloudflare Email Catch All response format
|
|
10
15
|
*/
|
|
11
16
|
interface CloudflareEmailCatchAll {
|
|
17
|
+
id: string;
|
|
12
18
|
enabled: boolean;
|
|
13
19
|
name: string;
|
|
14
|
-
matchers:
|
|
20
|
+
matchers: EmailCatchAllMatcher[];
|
|
15
21
|
actions: EmailAction[];
|
|
16
22
|
tag: string;
|
|
17
23
|
}
|
|
@@ -43,7 +49,7 @@ export interface EmailCatchAllProps extends CloudflareApiOptions {
|
|
|
43
49
|
* Matchers for the catch-all rule (typically matches all emails)
|
|
44
50
|
* If not provided, defaults to matching all emails
|
|
45
51
|
*/
|
|
46
|
-
matchers?:
|
|
52
|
+
matchers?: EmailCatchAllMatcher[];
|
|
47
53
|
|
|
48
54
|
/**
|
|
49
55
|
* Actions to take for emails that don't match other rules
|
|
@@ -60,6 +66,11 @@ export interface EmailCatchAll {
|
|
|
60
66
|
*/
|
|
61
67
|
zoneId: string;
|
|
62
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Routing rule identifier.
|
|
71
|
+
*/
|
|
72
|
+
ruleId: string;
|
|
73
|
+
|
|
63
74
|
/**
|
|
64
75
|
* Whether the catch-all rule is enabled
|
|
65
76
|
*/
|
|
@@ -73,7 +84,7 @@ export interface EmailCatchAll {
|
|
|
73
84
|
/**
|
|
74
85
|
* Matchers for the catch-all rule
|
|
75
86
|
*/
|
|
76
|
-
matchers:
|
|
87
|
+
matchers: EmailCatchAllMatcher[];
|
|
77
88
|
|
|
78
89
|
/**
|
|
79
90
|
* Actions for the catch-all rule
|
|
@@ -81,9 +92,26 @@ export interface EmailCatchAll {
|
|
|
81
92
|
actions: EmailAction[];
|
|
82
93
|
|
|
83
94
|
/**
|
|
84
|
-
*
|
|
95
|
+
* Deprecated rule tag returned by the Cloudflare API.
|
|
85
96
|
*/
|
|
86
|
-
tag
|
|
97
|
+
tag?: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function isEmailCatchAll(resource: any): resource is EmailCatchAll {
|
|
101
|
+
return resource?.[ResourceKind] === "cloudflare::EmailCatchAll";
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function validateCatchAllActions(actions: EmailAction[]) {
|
|
105
|
+
for (const action of actions) {
|
|
106
|
+
if (action.type === "drop") {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (!action.value?.length) {
|
|
110
|
+
throw new Error(
|
|
111
|
+
`EmailCatchAll action "${action.type}" requires at least one value.`,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
87
115
|
}
|
|
88
116
|
|
|
89
117
|
/**
|
|
@@ -151,7 +179,8 @@ export const EmailCatchAll = Resource(
|
|
|
151
179
|
props: EmailCatchAllProps,
|
|
152
180
|
): Promise<EmailCatchAll> {
|
|
153
181
|
const api = await createCloudflareApi(props);
|
|
154
|
-
const zoneId =
|
|
182
|
+
const zoneId = await resolveEmailZoneId(api, props.zone);
|
|
183
|
+
validateCatchAllActions(props.actions);
|
|
155
184
|
|
|
156
185
|
if (this.phase === "delete") {
|
|
157
186
|
// Disable the catch-all rule by setting enabled to false
|
|
@@ -205,11 +234,12 @@ export const EmailCatchAll = Resource(
|
|
|
205
234
|
|
|
206
235
|
return {
|
|
207
236
|
zoneId,
|
|
237
|
+
ruleId: result.result.id,
|
|
208
238
|
enabled: result.result.enabled,
|
|
209
239
|
name: result.result.name,
|
|
210
240
|
matchers: result.result.matchers,
|
|
211
241
|
actions: result.result.actions,
|
|
212
|
-
tag: result.result.tag,
|
|
242
|
+
tag: result.result.tag || undefined,
|
|
213
243
|
};
|
|
214
244
|
}
|
|
215
245
|
|
|
@@ -238,11 +268,12 @@ export const EmailCatchAll = Resource(
|
|
|
238
268
|
|
|
239
269
|
return {
|
|
240
270
|
zoneId,
|
|
271
|
+
ruleId: result.result.id,
|
|
241
272
|
enabled: result.result.enabled,
|
|
242
273
|
name: result.result.name,
|
|
243
274
|
matchers: result.result.matchers,
|
|
244
275
|
actions: result.result.actions,
|
|
245
|
-
tag: result.result.tag,
|
|
276
|
+
tag: result.result.tag || undefined,
|
|
246
277
|
};
|
|
247
278
|
},
|
|
248
279
|
);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CloudflareApi } from "./api.ts";
|
|
2
|
+
import { findZoneForHostname, type Zone } from "./zone.ts";
|
|
3
|
+
|
|
4
|
+
export async function resolveEmailZoneId(
|
|
5
|
+
api: CloudflareApi,
|
|
6
|
+
zone: string | Zone,
|
|
7
|
+
): Promise<string> {
|
|
8
|
+
return typeof zone === "string"
|
|
9
|
+
? (await findZoneForHostname(api, zone)).zoneId
|
|
10
|
+
: zone.id;
|
|
11
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Context } from "../context.ts";
|
|
2
|
-
import { Resource } from "../resource.ts";
|
|
2
|
+
import { Resource, ResourceKind } from "../resource.ts";
|
|
3
3
|
import { handleApiError } from "./api-error.ts";
|
|
4
4
|
import { type CloudflareApiOptions, createCloudflareApi } from "./api.ts";
|
|
5
|
+
import { resolveEmailZoneId } from "./email-common.ts";
|
|
5
6
|
import type { CloudflareResponse } from "./response.ts";
|
|
6
7
|
import type { Zone } from "./zone.ts";
|
|
7
8
|
|
|
@@ -75,6 +76,10 @@ export interface EmailRouting {
|
|
|
75
76
|
tag: string;
|
|
76
77
|
}
|
|
77
78
|
|
|
79
|
+
export function isEmailRouting(resource: any): resource is EmailRouting {
|
|
80
|
+
return resource?.[ResourceKind] === "cloudflare::EmailRouting";
|
|
81
|
+
}
|
|
82
|
+
|
|
78
83
|
/**
|
|
79
84
|
* Configures email routing for a Cloudflare zone, allowing emails sent to the zone's domain
|
|
80
85
|
* to be routed according to defined rules.
|
|
@@ -116,7 +121,7 @@ export const EmailRouting = Resource(
|
|
|
116
121
|
props: EmailRoutingProps,
|
|
117
122
|
): Promise<EmailRouting> {
|
|
118
123
|
const api = await createCloudflareApi(props);
|
|
119
|
-
const zoneId =
|
|
124
|
+
const zoneId = await resolveEmailZoneId(api, props.zone);
|
|
120
125
|
|
|
121
126
|
if (this.phase === "delete") {
|
|
122
127
|
// Disable email routing DNS
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Context } from "../context.ts";
|
|
2
|
-
import { Resource } from "../resource.ts";
|
|
2
|
+
import { Resource, ResourceKind } from "../resource.ts";
|
|
3
3
|
import { handleApiError } from "./api-error.ts";
|
|
4
4
|
import { type CloudflareApiOptions, createCloudflareApi } from "./api.ts";
|
|
5
|
+
import { resolveEmailZoneId } from "./email-common.ts";
|
|
5
6
|
import type { CloudflareResponse } from "./response.ts";
|
|
6
7
|
import type { Zone } from "./zone.ts";
|
|
7
8
|
|
|
@@ -19,7 +20,7 @@ export interface EmailMatcher {
|
|
|
19
20
|
/**
|
|
20
21
|
* Field to match against (required for literal matchers)
|
|
21
22
|
*/
|
|
22
|
-
field?: "to"
|
|
23
|
+
field?: "to";
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* Value to match (required for literal matchers)
|
|
@@ -141,9 +142,42 @@ export interface EmailRule {
|
|
|
141
142
|
actions: EmailAction[];
|
|
142
143
|
|
|
143
144
|
/**
|
|
144
|
-
*
|
|
145
|
+
* Deprecated rule tag returned by the Cloudflare API.
|
|
145
146
|
*/
|
|
146
|
-
tag
|
|
147
|
+
tag?: string;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function isEmailRule(resource: any): resource is EmailRule {
|
|
151
|
+
return resource?.[ResourceKind] === "cloudflare::EmailRule";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function validateMatchers(matchers: EmailMatcher[]) {
|
|
155
|
+
for (const matcher of matchers) {
|
|
156
|
+
if (matcher.type === "all") {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (matcher.field !== "to") {
|
|
160
|
+
throw new Error(
|
|
161
|
+
'EmailRule literal matchers currently only support field: "to".',
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
if (!matcher.value) {
|
|
165
|
+
throw new Error("EmailRule literal matchers require a value.");
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function validateActions(actions: EmailAction[]) {
|
|
171
|
+
for (const action of actions) {
|
|
172
|
+
if (action.type === "drop") {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (!action.value?.length) {
|
|
176
|
+
throw new Error(
|
|
177
|
+
`EmailRule action "${action.type}" requires at least one value.`,
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
147
181
|
}
|
|
148
182
|
|
|
149
183
|
/**
|
|
@@ -235,7 +269,9 @@ export const EmailRule = Resource(
|
|
|
235
269
|
props: EmailRuleProps,
|
|
236
270
|
): Promise<EmailRule> {
|
|
237
271
|
const api = await createCloudflareApi(props);
|
|
238
|
-
const zoneId =
|
|
272
|
+
const zoneId = await resolveEmailZoneId(api, props.zone);
|
|
273
|
+
validateMatchers(props.matchers);
|
|
274
|
+
validateActions(props.actions);
|
|
239
275
|
|
|
240
276
|
if (this.phase === "delete") {
|
|
241
277
|
if (this.output?.ruleId) {
|
|
@@ -282,7 +318,7 @@ export const EmailRule = Resource(
|
|
|
282
318
|
priority: result.result.priority,
|
|
283
319
|
matchers: result.result.matchers,
|
|
284
320
|
actions: result.result.actions,
|
|
285
|
-
tag: result.result.tag,
|
|
321
|
+
tag: result.result.tag || undefined,
|
|
286
322
|
};
|
|
287
323
|
}
|
|
288
324
|
}
|
|
@@ -316,7 +352,7 @@ export const EmailRule = Resource(
|
|
|
316
352
|
priority: result.result.priority,
|
|
317
353
|
matchers: result.result.matchers,
|
|
318
354
|
actions: result.result.actions,
|
|
319
|
-
tag: result.result.tag,
|
|
355
|
+
tag: result.result.tag || undefined,
|
|
320
356
|
};
|
|
321
357
|
},
|
|
322
358
|
);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export interface BaseEmailSenderProps {
|
|
2
|
+
allowedSenderAddresses?: string[];
|
|
3
|
+
dev?: {
|
|
4
|
+
remote?: boolean;
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type EmailSenderProps = BaseEmailSenderProps &
|
|
9
|
+
(
|
|
10
|
+
| {
|
|
11
|
+
destinationAddress?: string;
|
|
12
|
+
allowedDestinationAddresses?: never;
|
|
13
|
+
}
|
|
14
|
+
| {
|
|
15
|
+
destinationAddress?: never;
|
|
16
|
+
allowedDestinationAddresses?: string[];
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Type representing a Cloudflare Email Service send binding.
|
|
22
|
+
* @see https://developers.cloudflare.com/email-service/api/send-emails/workers-api/
|
|
23
|
+
*/
|
|
24
|
+
export type EmailSender = EmailSenderProps & {
|
|
25
|
+
type: "send_email";
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Creates a Cloudflare Email Service binding for sending emails from Workers.
|
|
30
|
+
*
|
|
31
|
+
* Set `dev.remote` to `true` to use the real Cloudflare email binding while
|
|
32
|
+
* running the Worker locally.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* const email = EmailSender({
|
|
37
|
+
* allowedSenderAddresses: ["noreply@example.com"],
|
|
38
|
+
* dev: { remote: true },
|
|
39
|
+
* });
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @see https://developers.cloudflare.com/email-service/api/send-emails/workers-api/
|
|
43
|
+
*/
|
|
44
|
+
export function EmailSender(props: EmailSenderProps = {}): EmailSender {
|
|
45
|
+
return {
|
|
46
|
+
type: "send_email",
|
|
47
|
+
...props,
|
|
48
|
+
};
|
|
49
|
+
}
|
package/src/cloudflare/index.ts
CHANGED
|
@@ -38,6 +38,7 @@ export * from "./email-address.ts";
|
|
|
38
38
|
export * from "./email-catch-all.ts";
|
|
39
39
|
export * from "./email-routing.ts";
|
|
40
40
|
export * from "./email-rule.ts";
|
|
41
|
+
export * from "./email-sender.ts";
|
|
41
42
|
export * from "./health-check.ts";
|
|
42
43
|
export * from "./hyperdrive-ref.ts";
|
|
43
44
|
export * from "./hyperdrive.ts";
|
|
@@ -50,7 +50,10 @@ type RemoteBinding =
|
|
|
50
50
|
}
|
|
51
51
|
> & { raw: true })
|
|
52
52
|
// Fetcher type bindings do not require the `raw` flag and will throw an error if it is present.
|
|
53
|
-
| Extract<
|
|
53
|
+
| Extract<
|
|
54
|
+
WorkerBindingSpec,
|
|
55
|
+
{ type: "send_email" | "service" | "vpc_service" }
|
|
56
|
+
>;
|
|
54
57
|
|
|
55
58
|
type BaseWorkerOptions = {
|
|
56
59
|
[K in keyof miniflare.WorkerOptions]: K extends
|
|
@@ -261,6 +264,36 @@ export const buildWorkerOptions = async (
|
|
|
261
264
|
(options.bindings ??= {})[key] = binding.unencrypted;
|
|
262
265
|
break;
|
|
263
266
|
}
|
|
267
|
+
case "send_email": {
|
|
268
|
+
const config = {
|
|
269
|
+
name: key,
|
|
270
|
+
destination_address: binding.destinationAddress,
|
|
271
|
+
allowed_destination_addresses: binding.allowedDestinationAddresses,
|
|
272
|
+
allowed_sender_addresses: binding.allowedSenderAddresses,
|
|
273
|
+
};
|
|
274
|
+
if (isRemoteBinding(binding)) {
|
|
275
|
+
remoteBindings.push({
|
|
276
|
+
type: "send_email",
|
|
277
|
+
...config,
|
|
278
|
+
});
|
|
279
|
+
} else {
|
|
280
|
+
((
|
|
281
|
+
options as BaseWorkerOptions & {
|
|
282
|
+
email?: {
|
|
283
|
+
send_email?: Array<typeof config>;
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
).email ??= {}).send_email ??= [];
|
|
287
|
+
(
|
|
288
|
+
options as BaseWorkerOptions & {
|
|
289
|
+
email: {
|
|
290
|
+
send_email: Array<typeof config>;
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
).email.send_email.push(config);
|
|
294
|
+
}
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
264
297
|
case "secret_key": {
|
|
265
298
|
throw new Error("Secret keys are not supported in local mode");
|
|
266
299
|
}
|
|
@@ -441,6 +474,41 @@ export const buildWorkerOptions = async (
|
|
|
441
474
|
remoteProxyConnectionString: remoteProxy.connectionString,
|
|
442
475
|
};
|
|
443
476
|
break;
|
|
477
|
+
case "send_email":
|
|
478
|
+
((
|
|
479
|
+
options as BaseWorkerOptions & {
|
|
480
|
+
email?: {
|
|
481
|
+
send_email?: Array<{
|
|
482
|
+
name: string;
|
|
483
|
+
destination_address?: string;
|
|
484
|
+
allowed_destination_addresses?: string[];
|
|
485
|
+
allowed_sender_addresses?: string[];
|
|
486
|
+
remoteProxyConnectionString: typeof remoteProxy.connectionString;
|
|
487
|
+
}>;
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
).email ??= {}).send_email ??= [];
|
|
491
|
+
(
|
|
492
|
+
options as BaseWorkerOptions & {
|
|
493
|
+
email: {
|
|
494
|
+
send_email: Array<{
|
|
495
|
+
name: string;
|
|
496
|
+
destination_address?: string;
|
|
497
|
+
allowed_destination_addresses?: string[];
|
|
498
|
+
allowed_sender_addresses?: string[];
|
|
499
|
+
remoteProxyConnectionString: typeof remoteProxy.connectionString;
|
|
500
|
+
}>;
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
).email.send_email.push({
|
|
504
|
+
name: binding.name,
|
|
505
|
+
destination_address: binding.destination_address,
|
|
506
|
+
allowed_destination_addresses:
|
|
507
|
+
binding.allowed_destination_addresses,
|
|
508
|
+
allowed_sender_addresses: binding.allowed_sender_addresses,
|
|
509
|
+
remoteProxyConnectionString: remoteProxy.connectionString,
|
|
510
|
+
});
|
|
511
|
+
break;
|
|
444
512
|
case "service":
|
|
445
513
|
(options.serviceBindings ??= {})[binding.name] = {
|
|
446
514
|
name: binding.name,
|
|
@@ -101,7 +101,7 @@ export class MiniflareController {
|
|
|
101
101
|
unsafeDevRegistryPath: miniflare.getDefaultDevRegistryPath(),
|
|
102
102
|
log: process.env.DEBUG
|
|
103
103
|
? new miniflare.Log(miniflare.LogLevel.DEBUG)
|
|
104
|
-
:
|
|
104
|
+
: new DefaultLogger(),
|
|
105
105
|
// This is required to allow websites and other separate processes
|
|
106
106
|
// to detect Alchemy-managed Durable Objects via the Wrangler dev registry.
|
|
107
107
|
unsafeDevRegistryDurableObjectProxy: true,
|
|
@@ -170,3 +170,20 @@ export class MiniflareController {
|
|
|
170
170
|
]);
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
|
+
|
|
174
|
+
class DefaultLogger extends miniflare.Log {
|
|
175
|
+
constructor() {
|
|
176
|
+
// Miniflare emits send_email activity at info level.
|
|
177
|
+
super(miniflare.LogLevel.INFO);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
override info(message: string) {
|
|
181
|
+
if (
|
|
182
|
+
message.startsWith("Ready on") ||
|
|
183
|
+
message.startsWith("Updated and ready on")
|
|
184
|
+
) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
super.info(message);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -14,16 +14,20 @@ import type { Worker } from "../worker.ts";
|
|
|
14
14
|
* Properties for creating a Nuxt resource.
|
|
15
15
|
* Extends WebsiteProps, allowing customization of the underlying Website.
|
|
16
16
|
*/
|
|
17
|
-
export interface NuxtProps<
|
|
17
|
+
export interface NuxtProps<
|
|
18
|
+
B extends Bindings,
|
|
19
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
20
|
+
> extends WebsiteProps<B, RPC> {}
|
|
18
21
|
|
|
19
22
|
/**
|
|
20
23
|
* Represents the output of a Nuxt resource deployment.
|
|
21
24
|
* It resolves to the underlying Cloudflare Worker type, ensuring type safety.
|
|
22
25
|
* Prevents overriding the internal ASSETS binding.
|
|
23
26
|
*/
|
|
24
|
-
export type Nuxt<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
export type Nuxt<
|
|
28
|
+
B extends Bindings,
|
|
29
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
30
|
+
> = B extends { ASSETS: any } ? never : Worker<B & { ASSETS: Assets }, RPC>;
|
|
27
31
|
|
|
28
32
|
/**
|
|
29
33
|
* Creates and deploys a Nuxt application using the Cloudflare Workers preset.
|
|
@@ -52,10 +56,10 @@ export type Nuxt<B extends Bindings> = B extends { ASSETS: any }
|
|
|
52
56
|
* },
|
|
53
57
|
* });
|
|
54
58
|
*/
|
|
55
|
-
export async function Nuxt<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
): Promise<Nuxt<B>> {
|
|
59
|
+
export async function Nuxt<
|
|
60
|
+
B extends Bindings,
|
|
61
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
62
|
+
>(id: string, props?: Partial<NuxtProps<B, RPC>>): Promise<Nuxt<B, RPC>> {
|
|
59
63
|
const runner = await getPackageManagerRunner();
|
|
60
64
|
return await Website(id, {
|
|
61
65
|
...props,
|
|
@@ -5,7 +5,10 @@ import type { Bindings } from "../bindings.ts";
|
|
|
5
5
|
import { Vite, type ViteProps } from "../vite/vite.ts";
|
|
6
6
|
import type { Worker } from "../worker.ts";
|
|
7
7
|
|
|
8
|
-
export interface ReactRouterProps<
|
|
8
|
+
export interface ReactRouterProps<
|
|
9
|
+
B extends Bindings,
|
|
10
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
11
|
+
> extends ViteProps<B, RPC> {
|
|
9
12
|
/**
|
|
10
13
|
* @default workers/app.ts
|
|
11
14
|
*/
|
|
@@ -13,14 +16,18 @@ export interface ReactRouterProps<B extends Bindings> extends ViteProps<B> {
|
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
// don't allow the ASSETS to be overriden
|
|
16
|
-
export type ReactRouter<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
export type ReactRouter<
|
|
20
|
+
B extends Bindings,
|
|
21
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
22
|
+
> = B extends { ASSETS: any } ? never : Worker<B & { ASSETS: Assets }, RPC>;
|
|
19
23
|
|
|
20
|
-
export async function ReactRouter<
|
|
24
|
+
export async function ReactRouter<
|
|
25
|
+
B extends Bindings,
|
|
26
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
27
|
+
>(
|
|
21
28
|
id: string,
|
|
22
|
-
props: ReactRouterProps<B> = {},
|
|
23
|
-
): Promise<ReactRouter<B>> {
|
|
29
|
+
props: ReactRouterProps<B, RPC> = {},
|
|
30
|
+
): Promise<ReactRouter<B, RPC>> {
|
|
24
31
|
const runner = await getPackageManagerRunner();
|
|
25
32
|
const cwd = path.resolve(props.cwd ?? process.cwd());
|
|
26
33
|
const ssr = await detectSSREnabled(cwd);
|
|
@@ -4,12 +4,16 @@ import type { Bindings } from "../bindings.ts";
|
|
|
4
4
|
import { Vite, type ViteProps } from "../vite/vite.ts";
|
|
5
5
|
import type { Worker } from "../worker.ts";
|
|
6
6
|
|
|
7
|
-
export interface RedwoodProps<
|
|
7
|
+
export interface RedwoodProps<
|
|
8
|
+
B extends Bindings,
|
|
9
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
10
|
+
> extends ViteProps<B, RPC> {}
|
|
8
11
|
|
|
9
12
|
// don't allow the ASSETS to be overridden
|
|
10
|
-
export type Redwood<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
export type Redwood<
|
|
14
|
+
B extends Bindings,
|
|
15
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
16
|
+
> = B extends { ASSETS: any } ? never : Worker<B & { ASSETS: Assets }, RPC>;
|
|
13
17
|
|
|
14
18
|
/**
|
|
15
19
|
* Deploy a RedwoodJS application to Cloudflare Workers with automatically configured defaults.
|
|
@@ -37,10 +41,10 @@ export type Redwood<B extends Bindings> = B extends { ASSETS: any }
|
|
|
37
41
|
* @param props - Configuration properties for the RedwoodJS deployment
|
|
38
42
|
* @returns A Cloudflare Worker resource representing the deployed RedwoodJS application
|
|
39
43
|
*/
|
|
40
|
-
export async function Redwood<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
): Promise<Redwood<B>> {
|
|
44
|
+
export async function Redwood<
|
|
45
|
+
B extends Bindings,
|
|
46
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
47
|
+
>(id: string, props?: Partial<RedwoodProps<B, RPC>>): Promise<Redwood<B, RPC>> {
|
|
44
48
|
return await Vite(id, {
|
|
45
49
|
...props,
|
|
46
50
|
build: props?.build ?? {
|
package/src/cloudflare/route.ts
CHANGED
|
@@ -49,6 +49,14 @@ export interface RouteProps extends CloudflareApiOptions {
|
|
|
49
49
|
*/
|
|
50
50
|
adopt?: boolean;
|
|
51
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Whether to delete the route when removed from Alchemy.
|
|
54
|
+
* If set to false, the route will remain but the resource will be removed from state.
|
|
55
|
+
*
|
|
56
|
+
* @default true
|
|
57
|
+
*/
|
|
58
|
+
delete?: boolean;
|
|
59
|
+
|
|
52
60
|
/**
|
|
53
61
|
* If true, the route will not be created, but will be retained if it already exists.
|
|
54
62
|
* This is used for local development.
|
|
@@ -151,7 +159,7 @@ export const Route = Resource(
|
|
|
151
159
|
|
|
152
160
|
// Only delete if we have complete output data (both ID and zoneId)
|
|
153
161
|
// If creation failed, we won't have proper output, so just skip deletion
|
|
154
|
-
if (this.output?.id && this.output?.zoneId) {
|
|
162
|
+
if (props.delete !== false && this.output?.id && this.output?.zoneId) {
|
|
155
163
|
await deleteRoute(api, this.output.zoneId, this.output.id);
|
|
156
164
|
}
|
|
157
165
|
|
|
@@ -4,12 +4,16 @@ import type { Bindings } from "../bindings.ts";
|
|
|
4
4
|
import { Vite, type ViteProps } from "../vite/vite.ts";
|
|
5
5
|
import type { Worker } from "../worker.ts";
|
|
6
6
|
|
|
7
|
-
export interface SvelteKitProps<
|
|
7
|
+
export interface SvelteKitProps<
|
|
8
|
+
B extends Bindings,
|
|
9
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
10
|
+
> extends ViteProps<B, RPC> {}
|
|
8
11
|
|
|
9
12
|
// don't allow the ASSETS to be overriden
|
|
10
|
-
export type SvelteKit<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
export type SvelteKit<
|
|
14
|
+
B extends Bindings,
|
|
15
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
16
|
+
> = B extends { ASSETS: any } ? never : Worker<B & { ASSETS: Assets }, RPC>;
|
|
13
17
|
|
|
14
18
|
/**
|
|
15
19
|
* Deploy a SvelteKit application to Cloudflare Workers with automatically configured defaults.
|
|
@@ -47,10 +51,13 @@ export type SvelteKit<B extends Bindings> = B extends { ASSETS: any }
|
|
|
47
51
|
* @param props - Configuration properties for the SvelteKit deployment
|
|
48
52
|
* @returns A Cloudflare Worker resource representing the deployed SvelteKit application
|
|
49
53
|
*/
|
|
50
|
-
export async function SvelteKit<
|
|
54
|
+
export async function SvelteKit<
|
|
55
|
+
B extends Bindings,
|
|
56
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
57
|
+
>(
|
|
51
58
|
id: string,
|
|
52
|
-
props?: Partial<SvelteKitProps<B>>,
|
|
53
|
-
): Promise<SvelteKit<B>> {
|
|
59
|
+
props?: Partial<SvelteKitProps<B, RPC>>,
|
|
60
|
+
): Promise<SvelteKit<B, RPC>> {
|
|
54
61
|
if (props?.compatibilityDate) {
|
|
55
62
|
const providedDate = new Date(props.compatibilityDate);
|
|
56
63
|
const minDate = new Date("2024-09-23");
|
|
@@ -5,17 +5,24 @@ import type { Bindings } from "../bindings.ts";
|
|
|
5
5
|
import { Vite, type ViteProps } from "../vite/vite.ts";
|
|
6
6
|
import type { Worker } from "../worker.ts";
|
|
7
7
|
|
|
8
|
-
export interface TanStackStartProps<
|
|
8
|
+
export interface TanStackStartProps<
|
|
9
|
+
B extends Bindings,
|
|
10
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
11
|
+
> extends ViteProps<B, RPC> {}
|
|
9
12
|
|
|
10
13
|
// don't allow the ASSETS to be overriden
|
|
11
|
-
export type TanStackStart<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
export type TanStackStart<
|
|
15
|
+
B extends Bindings,
|
|
16
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
17
|
+
> = B extends { ASSETS: any } ? never : Worker<B & { ASSETS: Assets }, RPC>;
|
|
14
18
|
|
|
15
|
-
export async function TanStackStart<
|
|
19
|
+
export async function TanStackStart<
|
|
20
|
+
B extends Bindings,
|
|
21
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
22
|
+
>(
|
|
16
23
|
id: string,
|
|
17
|
-
props?: Partial<TanStackStartProps<B>>,
|
|
18
|
-
): Promise<TanStackStart<B>> {
|
|
24
|
+
props?: Partial<TanStackStartProps<B, RPC>>,
|
|
25
|
+
): Promise<TanStackStart<B, RPC>> {
|
|
19
26
|
const main =
|
|
20
27
|
props?.wrangler?.main ??
|
|
21
28
|
((await exists(path.resolve(props?.cwd ?? process.cwd(), "src/server.ts")))
|
|
@@ -11,16 +11,20 @@ import {
|
|
|
11
11
|
} from "../website.ts";
|
|
12
12
|
import type { Worker } from "../worker.ts";
|
|
13
13
|
|
|
14
|
-
export interface ViteProps<
|
|
14
|
+
export interface ViteProps<
|
|
15
|
+
B extends Bindings,
|
|
16
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
17
|
+
> extends WebsiteProps<B, RPC> {}
|
|
15
18
|
|
|
16
|
-
export type Vite<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
export type Vite<
|
|
20
|
+
B extends Bindings,
|
|
21
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
22
|
+
> = B extends { ASSETS: any } ? never : Worker<B & { ASSETS: Assets }, RPC>;
|
|
19
23
|
|
|
20
|
-
export async function Vite<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
): Promise<Vite<B>> {
|
|
24
|
+
export async function Vite<
|
|
25
|
+
B extends Bindings,
|
|
26
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
27
|
+
>(id: string, props: ViteProps<B, RPC>): Promise<Vite<B, RPC>> {
|
|
24
28
|
const runner = await getPackageManagerRunner();
|
|
25
29
|
let dev = spreadDevProps(props, `${runner} vite dev`);
|
|
26
30
|
let domain = typeof dev === "object" ? dev.domain : undefined;
|