alchemy 0.90.0 → 0.91.2
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 +1 -1
- 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/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/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.d.ts +15 -0
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +37 -22
- package/lib/cloudflare/worker.js.map +1 -1
- package/package.json +1 -1
- package/src/cloudflare/astro/astro.ts +14 -13
- 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/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.ts +71 -33
- package/workers/tunnel-proxy.js +1 -1
|
@@ -14,7 +14,10 @@ import {
|
|
|
14
14
|
type WebsiteProps,
|
|
15
15
|
} from "../website.ts";
|
|
16
16
|
|
|
17
|
-
export interface BunSPAProps<
|
|
17
|
+
export interface BunSPAProps<
|
|
18
|
+
B extends Bindings,
|
|
19
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
20
|
+
> extends WebsiteProps<B, RPC> {
|
|
18
21
|
/**
|
|
19
22
|
* The path to the frontend entrypoints that bun should bundle for deployment & serve in dev mode.
|
|
20
23
|
* These are usually html files. Glob patterns are supported.
|
|
@@ -24,12 +27,18 @@ export interface BunSPAProps<B extends Bindings> extends WebsiteProps<B> {
|
|
|
24
27
|
outDir?: string;
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
export type BunSPA<
|
|
30
|
+
export type BunSPA<
|
|
31
|
+
B extends Bindings,
|
|
32
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
33
|
+
> = Website<B, RPC> & { apiUrl: string };
|
|
28
34
|
|
|
29
|
-
export async function BunSPA<
|
|
35
|
+
export async function BunSPA<
|
|
36
|
+
B extends Bindings,
|
|
37
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
38
|
+
>(
|
|
30
39
|
id: string,
|
|
31
|
-
props: BunSPAProps<B>,
|
|
32
|
-
): Promise<BunSPA<B> & { apiUrl: string }> {
|
|
40
|
+
props: BunSPAProps<B, RPC>,
|
|
41
|
+
): Promise<BunSPA<B, RPC> & { apiUrl: string }> {
|
|
33
42
|
const frontendPaths = Array.isArray(props.frontend)
|
|
34
43
|
? props.frontend.map((p) => path.resolve(p))
|
|
35
44
|
: [path.resolve(props.frontend)];
|
|
@@ -132,7 +141,7 @@ export async function BunSPA<B extends Bindings>(
|
|
|
132
141
|
},
|
|
133
142
|
});
|
|
134
143
|
}
|
|
135
|
-
return { ...website, apiUrl } as BunSPA<B>;
|
|
144
|
+
return { ...website, apiUrl } as BunSPA<B, RPC>;
|
|
136
145
|
}
|
|
137
146
|
|
|
138
147
|
async function validateBunfigToml(cwd: string): Promise<void> {
|
|
@@ -2,6 +2,7 @@ import type esbuild from "esbuild";
|
|
|
2
2
|
import assert from "node:assert";
|
|
3
3
|
import crypto from "node:crypto";
|
|
4
4
|
import fs from "node:fs/promises";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
5
6
|
import path from "pathe";
|
|
6
7
|
import type { WorkerBundle } from "../worker-bundle.ts";
|
|
7
8
|
|
|
@@ -22,9 +23,27 @@ export function createWasmPlugin() {
|
|
|
22
23
|
return { path: resolved.path, external: true };
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
// Resolve path to source file, excluding the `?module` suffix
|
|
26
|
+
// Resolve path to source file, excluding the `?module` suffix
|
|
26
27
|
const normalizedPath = path.normalize(args.path).replace(/\?.*$/, "");
|
|
27
|
-
|
|
28
|
+
|
|
29
|
+
// Determine the source file: use Node module resolution for bare specifiers (npm packages),
|
|
30
|
+
// otherwise resolve relative to the importing file's directory
|
|
31
|
+
let copyFrom: string;
|
|
32
|
+
if (/^[./]/.test(normalizedPath)) {
|
|
33
|
+
copyFrom = path.resolve(args.resolveDir, normalizedPath);
|
|
34
|
+
} else {
|
|
35
|
+
try {
|
|
36
|
+
// createRequire needs a file path to anchor node_modules resolution from.
|
|
37
|
+
// The filename is a dummy — only the directory matters.
|
|
38
|
+
const esmRequire = createRequire(
|
|
39
|
+
path.join(args.resolveDir, "noop.js"),
|
|
40
|
+
);
|
|
41
|
+
copyFrom = esmRequire.resolve(normalizedPath);
|
|
42
|
+
} catch {
|
|
43
|
+
// Fall back to the original behavior if require.resolve fails
|
|
44
|
+
copyFrom = path.resolve(args.resolveDir, normalizedPath);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
28
47
|
|
|
29
48
|
// Resolve path to outdir (required for monorepos if the workdir is not the same as process.cwd())
|
|
30
49
|
assert(
|
|
@@ -410,6 +410,14 @@ export interface ContainerApplicationProps extends CloudflareApiOptions {
|
|
|
410
410
|
*/
|
|
411
411
|
adopt?: boolean;
|
|
412
412
|
|
|
413
|
+
/**
|
|
414
|
+
* Whether to delete the container application when removed from Alchemy.
|
|
415
|
+
* If set to false, the container application will remain but the resource will be removed from state.
|
|
416
|
+
*
|
|
417
|
+
* @default true
|
|
418
|
+
*/
|
|
419
|
+
delete?: boolean;
|
|
420
|
+
|
|
413
421
|
/**
|
|
414
422
|
* If true, the container application will not be created, but will be retained if it already exists.
|
|
415
423
|
* This is used for local development.
|
|
@@ -557,7 +565,7 @@ export const ContainerApplication = Resource(
|
|
|
557
565
|
|
|
558
566
|
const api = await createCloudflareApi(props);
|
|
559
567
|
if (this.phase === "delete") {
|
|
560
|
-
if (this.output?.id) {
|
|
568
|
+
if (props.delete !== false && this.output?.id) {
|
|
561
569
|
// Delete the container application
|
|
562
570
|
await deleteContainerApplication(api, this.output.id);
|
|
563
571
|
}
|
|
@@ -44,6 +44,14 @@ export interface CustomDomainProps extends CloudflareApiOptions {
|
|
|
44
44
|
*/
|
|
45
45
|
adopt?: boolean;
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Whether to delete the custom domain when removed from Alchemy.
|
|
49
|
+
* If set to false, the custom domain will remain but the resource will be removed from state.
|
|
50
|
+
*
|
|
51
|
+
* @default true
|
|
52
|
+
*/
|
|
53
|
+
delete?: boolean;
|
|
54
|
+
|
|
47
55
|
/**
|
|
48
56
|
* If true, the custom domain will not be created, but will be retained if it already exists.
|
|
49
57
|
* This is used for local development.
|
|
@@ -137,7 +145,9 @@ export const CustomDomain = Resource(
|
|
|
137
145
|
const api = await createCloudflareApi(props);
|
|
138
146
|
|
|
139
147
|
if (this.phase === "delete") {
|
|
140
|
-
|
|
148
|
+
if (props.delete !== false) {
|
|
149
|
+
await deleteCustomDomain(this, api, logicalId, props);
|
|
150
|
+
}
|
|
141
151
|
return this.destroy();
|
|
142
152
|
}
|
|
143
153
|
|
|
@@ -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;
|
|
@@ -18,10 +18,10 @@ import { computeWorkerDevDomain } from "./worker-subdomain.ts";
|
|
|
18
18
|
import { type AssetsConfig, Worker, type WorkerProps } from "./worker.ts";
|
|
19
19
|
import { WranglerJson, type WranglerJsonSpec } from "./wrangler.json.ts";
|
|
20
20
|
|
|
21
|
-
export interface WebsiteProps<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
> {
|
|
21
|
+
export interface WebsiteProps<
|
|
22
|
+
B extends Bindings,
|
|
23
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
24
|
+
> extends Omit<WorkerProps<B, RPC>, "assets" | "dev"> {
|
|
25
25
|
/**
|
|
26
26
|
* Configuration for the build command
|
|
27
27
|
*
|
|
@@ -149,14 +149,15 @@ export interface WebsiteProps<B extends Bindings> extends Omit<
|
|
|
149
149
|
memoize?: boolean | { patterns: string[] };
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
export type Website<
|
|
153
|
-
|
|
154
|
-
|
|
152
|
+
export type Website<
|
|
153
|
+
B extends Bindings,
|
|
154
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
155
|
+
> = B extends { ASSETS: any } ? never : Worker<B & { ASSETS: Assets }, RPC>;
|
|
155
156
|
|
|
156
|
-
export async function Website<
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
) {
|
|
157
|
+
export async function Website<
|
|
158
|
+
B extends Bindings,
|
|
159
|
+
RPC extends Rpc.WorkerEntrypointBranded = Rpc.WorkerEntrypointBranded,
|
|
160
|
+
>(id: string, props: WebsiteProps<B, RPC>) {
|
|
160
161
|
const {
|
|
161
162
|
name = Scope.current.createPhysicalName(id).toLowerCase(),
|
|
162
163
|
build: buildProps,
|
|
@@ -377,7 +378,7 @@ export async function Website<B extends Bindings>(
|
|
|
377
378
|
: {}),
|
|
378
379
|
},
|
|
379
380
|
dev: url ? { url } : undefined,
|
|
380
|
-
})) as Website<B>;
|
|
381
|
+
})) as Website<B, RPC>;
|
|
381
382
|
}
|
|
382
383
|
|
|
383
384
|
export const spreadBuildProps = (
|
package/src/cloudflare/worker.ts
CHANGED
|
@@ -6,7 +6,11 @@ import type { type } from "../type.ts";
|
|
|
6
6
|
import { DeferredPromise } from "../util/deferred-promise.ts";
|
|
7
7
|
import { logger } from "../util/logger.ts";
|
|
8
8
|
import { withExponentialBackoff } from "../util/retry.ts";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
CloudflareApiError,
|
|
11
|
+
handleApiError,
|
|
12
|
+
isCloudflareApiError,
|
|
13
|
+
} from "./api-error.ts";
|
|
10
14
|
import {
|
|
11
15
|
type CloudflareApi,
|
|
12
16
|
type CloudflareApiOptions,
|
|
@@ -207,6 +211,14 @@ export interface BaseWorkerProps<
|
|
|
207
211
|
*/
|
|
208
212
|
logpush?: boolean;
|
|
209
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Whether to delete the worker when removed from Alchemy.
|
|
216
|
+
* If set to false, the worker will remain but the resource will be removed from state.
|
|
217
|
+
*
|
|
218
|
+
* @default true
|
|
219
|
+
*/
|
|
220
|
+
delete?: boolean;
|
|
221
|
+
|
|
210
222
|
/**
|
|
211
223
|
* Whether to adopt the Worker if it already exists when creating
|
|
212
224
|
*/
|
|
@@ -939,6 +951,14 @@ export type Worker<
|
|
|
939
951
|
* // The worker will have a preview URL for testing:
|
|
940
952
|
* console.log(`Preview URL: ${previewWorker.url}`);
|
|
941
953
|
* // Output: Preview URL: https://pr-123-my-worker.subdomain.workers.dev
|
|
954
|
+
*
|
|
955
|
+
* @example
|
|
956
|
+
* // Prevent deletion of the worker when removed from Alchemy:
|
|
957
|
+
* const worker = await Worker("critical-api", {
|
|
958
|
+
* name: "critical-api",
|
|
959
|
+
* entrypoint: "./src/api.ts",
|
|
960
|
+
* delete: false
|
|
961
|
+
* });
|
|
942
962
|
*/
|
|
943
963
|
export function Worker<
|
|
944
964
|
const B extends Bindings,
|
|
@@ -1104,7 +1124,7 @@ const _Worker = Resource(
|
|
|
1104
1124
|
durableObjects: options.durableObjects,
|
|
1105
1125
|
workflows: options.workflows,
|
|
1106
1126
|
});
|
|
1107
|
-
if (this.output?.dev?.hasRemote !== false) {
|
|
1127
|
+
if (props.delete !== false && this.output?.dev?.hasRemote !== false) {
|
|
1108
1128
|
const api = await createCloudflareApi(props);
|
|
1109
1129
|
if (props.version) {
|
|
1110
1130
|
//* if the worker exists we deploy an empty version so we can destroy
|
|
@@ -1250,45 +1270,49 @@ const _Worker = Resource(
|
|
|
1250
1270
|
|
|
1251
1271
|
let result: PutWorkerResult;
|
|
1252
1272
|
|
|
1273
|
+
// cloudflare has awkward sequencing requirements for modifying subdomains
|
|
1274
|
+
// because conflicts with Durable Objects and preview_enabled is stateful
|
|
1275
|
+
// to solve this, we try and do both in parallel and push them through
|
|
1276
|
+
const bruteForce = <T>(operation: () => Promise<T>) =>
|
|
1277
|
+
withExponentialBackoff(
|
|
1278
|
+
operation,
|
|
1279
|
+
(error) => {
|
|
1280
|
+
operation;
|
|
1281
|
+
return (
|
|
1282
|
+
error instanceof CloudflareApiError &&
|
|
1283
|
+
error.status === 400 &&
|
|
1284
|
+
error.message.includes(
|
|
1285
|
+
"Cannot use Durable Objects with Preview URLs",
|
|
1286
|
+
)
|
|
1287
|
+
);
|
|
1288
|
+
},
|
|
1289
|
+
10,
|
|
1290
|
+
100,
|
|
1291
|
+
1000,
|
|
1292
|
+
);
|
|
1293
|
+
|
|
1253
1294
|
if (this.scope.watch) {
|
|
1254
1295
|
const controller = new AbortController();
|
|
1255
|
-
result = await
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1296
|
+
[result] = await Promise.all([
|
|
1297
|
+
watchWorker(api, props, {
|
|
1298
|
+
id,
|
|
1299
|
+
name: options.name,
|
|
1300
|
+
dispatchNamespace: options.dispatchNamespace,
|
|
1301
|
+
bundle,
|
|
1302
|
+
compatibilityDate: options.compatibilityDate,
|
|
1303
|
+
compatibilityFlags: options.compatibilityFlags,
|
|
1304
|
+
version: props.version,
|
|
1305
|
+
assets,
|
|
1306
|
+
controller,
|
|
1307
|
+
}),
|
|
1308
|
+
bruteForce(updateSubdomain),
|
|
1309
|
+
]);
|
|
1266
1310
|
this.onCleanup(() => controller.abort());
|
|
1267
1311
|
const tail = await createTail(api, id, options.name).catch((error) => {
|
|
1268
1312
|
logger.error(`Failed to create tail for ${options.name}`, error);
|
|
1269
1313
|
});
|
|
1270
1314
|
this.onCleanup(() => tail?.close());
|
|
1271
1315
|
} else {
|
|
1272
|
-
// cloudflare has awkward sequencing requirements for modifying subdomains
|
|
1273
|
-
// because conflicts with Durable Objects and preview_enabled is stateful
|
|
1274
|
-
// to solve this, we try and do both in parallel and push them through
|
|
1275
|
-
const bruteForce = <T>(operation: () => Promise<T>) =>
|
|
1276
|
-
withExponentialBackoff(
|
|
1277
|
-
operation,
|
|
1278
|
-
(error) => {
|
|
1279
|
-
operation;
|
|
1280
|
-
return (
|
|
1281
|
-
error instanceof CloudflareApiError &&
|
|
1282
|
-
error.status === 400 &&
|
|
1283
|
-
error.message.includes(
|
|
1284
|
-
"Cannot use Durable Objects with Preview URLs",
|
|
1285
|
-
)
|
|
1286
|
-
);
|
|
1287
|
-
},
|
|
1288
|
-
10,
|
|
1289
|
-
100,
|
|
1290
|
-
1000,
|
|
1291
|
-
);
|
|
1292
1316
|
const scriptBundle = await bundle.create();
|
|
1293
1317
|
const [_, _result] = await Promise.all([
|
|
1294
1318
|
bruteForce(updateSubdomain),
|
|
@@ -1540,6 +1564,7 @@ async function provisionResources<B extends Bindings>(
|
|
|
1540
1564
|
durableObjects: {
|
|
1541
1565
|
namespaceId: await getContainerNamespaceId(container),
|
|
1542
1566
|
},
|
|
1567
|
+
delete: props.delete,
|
|
1543
1568
|
dev: options.local,
|
|
1544
1569
|
...input.api,
|
|
1545
1570
|
});
|
|
@@ -1553,6 +1578,7 @@ async function provisionResources<B extends Bindings>(
|
|
|
1553
1578
|
name: domain.name,
|
|
1554
1579
|
zoneId: domain.zoneId,
|
|
1555
1580
|
adopt: domain.adopt,
|
|
1581
|
+
delete: props.delete,
|
|
1556
1582
|
workerName: options.name,
|
|
1557
1583
|
dev: options.local,
|
|
1558
1584
|
...input.api,
|
|
@@ -1575,6 +1601,7 @@ async function provisionResources<B extends Bindings>(
|
|
|
1575
1601
|
scriptName: options.name,
|
|
1576
1602
|
settings: eventSource.settings,
|
|
1577
1603
|
adopt: props.adopt,
|
|
1604
|
+
delete: props.delete,
|
|
1578
1605
|
dev: options.local,
|
|
1579
1606
|
...input.api,
|
|
1580
1607
|
});
|
|
@@ -1589,6 +1616,7 @@ async function provisionResources<B extends Bindings>(
|
|
|
1589
1616
|
script: options.name,
|
|
1590
1617
|
zoneId: route.zoneId,
|
|
1591
1618
|
adopt: route.adopt,
|
|
1619
|
+
delete: props.delete,
|
|
1592
1620
|
dev: options.local,
|
|
1593
1621
|
...input.api,
|
|
1594
1622
|
});
|
|
@@ -1839,6 +1867,16 @@ export async function putWorker(
|
|
|
1839
1867
|
});
|
|
1840
1868
|
}
|
|
1841
1869
|
}
|
|
1870
|
+
if (
|
|
1871
|
+
isCloudflareApiError(error, { code: 11001 }) &&
|
|
1872
|
+
!props.eventSources?.length
|
|
1873
|
+
) {
|
|
1874
|
+
// Error code 11001 means that the worker has event sources, but no `queue` handler is defined.
|
|
1875
|
+
// Normally, queue consumers are removed automatically since we're using the `QueueConsumer` resource,
|
|
1876
|
+
// but if no `queue` handler is defined, we need to remove them for Cloudflare to let us deploy.
|
|
1877
|
+
await deleteQueueConsumers(api, workerName);
|
|
1878
|
+
return await putWorker(api, props);
|
|
1879
|
+
}
|
|
1842
1880
|
throw error;
|
|
1843
1881
|
}
|
|
1844
1882
|
},
|
package/workers/tunnel-proxy.js
CHANGED
|
@@ -83,7 +83,7 @@ const renderErrorHtml = (props) => `
|
|
|
83
83
|
Alchemy</a>.</p>
|
|
84
84
|
</div>
|
|
85
85
|
<div class="bg-slate-200 px-5 py-3 flex flex-col w-full max-w-lg">
|
|
86
|
-
<p class="text-sm text-slate-500">Alchemy 0.
|
|
86
|
+
<p class="text-sm text-slate-500">Alchemy 0.91.2</p>
|
|
87
87
|
</div>
|
|
88
88
|
</div>
|
|
89
89
|
</body>
|