alchemy 0.63.1 → 0.65.0
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 +7664 -5857
- package/bin/commands/init.ts +130 -9
- package/bin/constants.ts +4 -0
- package/bin/services/cdp-manager/cdp-proxy.ts +69 -0
- package/bin/services/cdp-manager/server.ts +173 -0
- package/bin/services/execute-alchemy.ts +83 -4
- package/bin/types.ts +1 -0
- package/lib/alchemy.d.ts +4 -0
- package/lib/alchemy.d.ts.map +1 -1
- package/lib/alchemy.js +10 -4
- package/lib/alchemy.js.map +1 -1
- package/lib/apply.d.ts +3 -0
- package/lib/apply.d.ts.map +1 -1
- package/lib/apply.js +11 -1
- package/lib/apply.js.map +1 -1
- package/lib/cloudflare/bindings.d.ts +3 -1
- package/lib/cloudflare/bindings.d.ts.map +1 -1
- package/lib/cloudflare/bucket.d.ts +2 -1
- package/lib/cloudflare/bucket.d.ts.map +1 -1
- package/lib/cloudflare/bucket.js.map +1 -1
- package/lib/cloudflare/bundle/cloudflare-internal.d.ts +6 -0
- package/lib/cloudflare/bundle/cloudflare-internal.d.ts.map +1 -0
- package/lib/cloudflare/bundle/cloudflare-internal.js +39 -0
- package/lib/cloudflare/bundle/cloudflare-internal.js.map +1 -0
- package/lib/cloudflare/bundle/nodejs-builtin-modules.d.ts +2 -0
- package/lib/cloudflare/bundle/nodejs-builtin-modules.d.ts.map +1 -0
- package/lib/cloudflare/bundle/nodejs-builtin-modules.js +9 -0
- package/lib/cloudflare/bundle/nodejs-builtin-modules.js.map +1 -0
- package/lib/cloudflare/bundle/plugin-als-external.d.ts +6 -0
- package/lib/cloudflare/bundle/plugin-als-external.d.ts.map +1 -0
- package/lib/cloudflare/bundle/plugin-als-external.js +12 -0
- package/lib/cloudflare/bundle/plugin-als-external.js.map +1 -0
- package/lib/cloudflare/bundle/plugin-hybrid-node-compat.d.ts +4 -1
- package/lib/cloudflare/bundle/plugin-hybrid-node-compat.d.ts.map +1 -1
- package/lib/cloudflare/bundle/plugin-hybrid-node-compat.js +23 -23
- package/lib/cloudflare/bundle/plugin-hybrid-node-compat.js.map +1 -1
- package/lib/cloudflare/bundle/plugin-node-compat.d.ts +11 -0
- package/lib/cloudflare/bundle/plugin-node-compat.d.ts.map +1 -0
- package/lib/cloudflare/bundle/plugin-node-compat.js +93 -0
- package/lib/cloudflare/bundle/plugin-node-compat.js.map +1 -0
- package/lib/cloudflare/bundle/plugin-wasm.d.ts.map +1 -1
- package/lib/cloudflare/bundle/plugin-wasm.js +20 -11
- package/lib/cloudflare/bundle/plugin-wasm.js.map +1 -1
- package/lib/cloudflare/compatibility-date.gen.d.ts +1 -1
- package/lib/cloudflare/compatibility-date.gen.js +1 -1
- package/lib/cloudflare/d1-local-migrations.js.map +1 -1
- package/lib/cloudflare/durable-object-namespace.d.ts +1 -0
- package/lib/cloudflare/durable-object-namespace.d.ts.map +1 -1
- package/lib/cloudflare/durable-object-namespace.js.map +1 -1
- package/lib/cloudflare/hyperdrive.d.ts +7 -2
- package/lib/cloudflare/hyperdrive.d.ts.map +1 -1
- package/lib/cloudflare/hyperdrive.js +39 -57
- package/lib/cloudflare/hyperdrive.js.map +1 -1
- package/lib/cloudflare/index.d.ts +1 -0
- package/lib/cloudflare/index.d.ts.map +1 -1
- package/lib/cloudflare/index.js +1 -0
- package/lib/cloudflare/index.js.map +1 -1
- package/lib/cloudflare/next.d.ts +13 -0
- package/lib/cloudflare/next.d.ts.map +1 -0
- package/lib/cloudflare/next.js +91 -0
- package/lib/cloudflare/next.js.map +1 -0
- package/lib/cloudflare/website.d.ts.map +1 -1
- package/lib/cloudflare/website.js +80 -82
- package/lib/cloudflare/website.js.map +1 -1
- package/lib/cloudflare/worker-assets.d.ts +3 -3
- package/lib/cloudflare/worker-assets.d.ts.map +1 -1
- package/lib/cloudflare/worker-assets.js +22 -47
- package/lib/cloudflare/worker-assets.js.map +1 -1
- package/lib/cloudflare/worker-bundle.d.ts +6 -0
- package/lib/cloudflare/worker-bundle.d.ts.map +1 -1
- package/lib/cloudflare/worker-bundle.js +34 -10
- package/lib/cloudflare/worker-bundle.js.map +1 -1
- package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
- package/lib/cloudflare/worker-metadata.js +1 -0
- package/lib/cloudflare/worker-metadata.js.map +1 -1
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +24 -6
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/cloudflare/wrangler.json.d.ts +4 -6
- package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
- package/lib/cloudflare/wrangler.json.js +20 -15
- package/lib/cloudflare/wrangler.json.js.map +1 -1
- package/lib/context.d.ts +3 -1
- package/lib/context.d.ts.map +1 -1
- package/lib/context.js +2 -2
- package/lib/context.js.map +1 -1
- package/lib/destroy.d.ts +8 -0
- package/lib/destroy.d.ts.map +1 -1
- package/lib/destroy.js +20 -4
- package/lib/destroy.js.map +1 -1
- package/lib/planetscale/api/client.gen.d.ts +1750 -0
- package/lib/planetscale/api/client.gen.d.ts.map +1 -0
- package/lib/planetscale/api/client.gen.js +2401 -0
- package/lib/planetscale/api/client.gen.js.map +1 -0
- package/lib/planetscale/api/index.d.ts +3 -0
- package/lib/planetscale/api/index.d.ts.map +1 -0
- package/lib/planetscale/api/index.js +4 -0
- package/lib/planetscale/api/index.js.map +1 -0
- package/lib/planetscale/api/types.gen.d.ts +12156 -0
- package/lib/planetscale/api/types.gen.d.ts.map +1 -0
- package/lib/planetscale/api/types.gen.js +2 -0
- package/lib/planetscale/api/types.gen.js.map +1 -0
- package/lib/planetscale/branch.d.ts +5 -8
- package/lib/planetscale/branch.d.ts.map +1 -1
- package/lib/planetscale/branch.js +122 -97
- package/lib/planetscale/branch.js.map +1 -1
- package/lib/planetscale/database.d.ts +24 -11
- package/lib/planetscale/database.d.ts.map +1 -1
- package/lib/planetscale/database.js +163 -118
- package/lib/planetscale/database.js.map +1 -1
- package/lib/planetscale/index.d.ts +2 -1
- package/lib/planetscale/index.d.ts.map +1 -1
- package/lib/planetscale/index.js +2 -1
- package/lib/planetscale/index.js.map +1 -1
- package/lib/planetscale/password.d.ts +7 -8
- package/lib/planetscale/password.d.ts.map +1 -1
- package/lib/planetscale/password.js +74 -57
- package/lib/planetscale/password.js.map +1 -1
- package/lib/planetscale/role.d.ts +126 -0
- package/lib/planetscale/role.d.ts.map +1 -0
- package/lib/planetscale/role.js +144 -0
- package/lib/planetscale/role.js.map +1 -0
- package/lib/planetscale/utils.d.ts +23 -7
- package/lib/planetscale/utils.d.ts.map +1 -1
- package/lib/planetscale/utils.js +169 -75
- package/lib/planetscale/utils.js.map +1 -1
- package/lib/scope.d.ts +5 -1
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +11 -3
- package/lib/scope.js.map +1 -1
- package/lib/secret.d.ts +0 -3
- package/lib/secret.d.ts.map +1 -1
- package/lib/secret.js +0 -2
- package/lib/secret.js.map +1 -1
- package/lib/state/cloudflare-state-store.js +3 -3
- package/lib/state/cloudflare-state-store.js.map +1 -1
- package/lib/test/bun.d.ts +2 -2
- package/lib/test/bun.d.ts.map +1 -1
- package/lib/test/vitest.d.ts +2 -2
- package/lib/test/vitest.d.ts.map +1 -1
- package/lib/test/vitest.js +4 -4
- package/lib/test/vitest.js.map +1 -1
- package/lib/util/content-type.js +2 -2
- package/lib/util/content-type.js.map +1 -1
- package/lib/util/dedent.d.ts +3 -14
- package/lib/util/dedent.d.ts.map +1 -1
- package/lib/util/dedent.js +33 -45
- package/lib/util/dedent.js.map +1 -1
- package/lib/util/memoize.d.ts.map +1 -1
- package/lib/util/memoize.js +11 -1
- package/lib/util/memoize.js.map +1 -1
- package/package.json +8 -3
- package/src/alchemy.ts +14 -6
- package/src/apply.ts +13 -1
- package/src/cloudflare/bindings.ts +3 -1
- package/src/cloudflare/bucket.ts +3 -1
- package/src/cloudflare/bundle/cloudflare-internal.ts +42 -0
- package/src/cloudflare/bundle/nodejs-builtin-modules.ts +14 -0
- package/src/cloudflare/bundle/plugin-als-external.ts +13 -0
- package/src/cloudflare/bundle/plugin-hybrid-node-compat.ts +29 -28
- package/src/cloudflare/bundle/plugin-node-compat.ts +114 -0
- package/src/cloudflare/bundle/plugin-wasm.ts +34 -14
- package/src/cloudflare/compatibility-date.gen.ts +1 -1
- package/src/cloudflare/d1-local-migrations.ts +2 -2
- package/src/cloudflare/durable-object-namespace.ts +1 -0
- package/src/cloudflare/hyperdrive.ts +136 -95
- package/src/cloudflare/index.ts +1 -0
- package/src/cloudflare/next.ts +123 -0
- package/src/cloudflare/website.ts +88 -89
- package/src/cloudflare/worker-assets.ts +43 -105
- package/src/cloudflare/worker-bundle.ts +46 -9
- package/src/cloudflare/worker-metadata.ts +2 -0
- package/src/cloudflare/worker.ts +35 -7
- package/src/cloudflare/wrangler.json.ts +114 -113
- package/src/context.ts +5 -3
- package/src/destroy.ts +26 -8
- package/src/planetscale/api/client.gen.ts +2882 -0
- package/src/planetscale/api/index.ts +4 -0
- package/src/planetscale/api/types.gen.ts +13041 -0
- package/src/planetscale/branch.ts +170 -162
- package/src/planetscale/database.ts +263 -243
- package/src/planetscale/index.ts +2 -1
- package/src/planetscale/password.ts +89 -86
- package/src/planetscale/role.ts +278 -0
- package/src/planetscale/utils.ts +289 -128
- package/src/scope.ts +12 -3
- package/src/secret.ts +0 -4
- package/src/state/cloudflare-state-store.ts +4 -4
- package/src/test/bun.ts +2 -2
- package/src/test/vitest.ts +6 -6
- package/src/util/content-type.ts +2 -2
- package/src/util/dedent.ts +34 -50
- package/src/util/memoize.ts +13 -1
- package/templates/astro/alchemy.run.ts +1 -3
- package/templates/hono/alchemy.run.ts +0 -1
- package/templates/nextjs/README.md +85 -0
- package/templates/nextjs/_env +1 -0
- package/templates/nextjs/_env.example +1 -0
- package/templates/nextjs/_gitignore +46 -0
- package/templates/nextjs/alchemy.run.ts +16 -0
- package/templates/nextjs/eslint.config.mjs +16 -0
- package/templates/nextjs/next-env.d.ts +5 -0
- package/templates/nextjs/next.config.ts +10 -0
- package/templates/nextjs/open-next.config.ts +5 -0
- package/templates/nextjs/package.json +31 -0
- package/templates/nextjs/src/app/api/hello/route.ts +19 -0
- package/templates/nextjs/src/app/favicon.ico +0 -0
- package/templates/nextjs/src/app/globals.css +72 -0
- package/templates/nextjs/src/app/layout.tsx +19 -0
- package/templates/nextjs/src/app/page.tsx +55 -0
- package/templates/nextjs/tsconfig.json +33 -0
- package/templates/nextjs/types/env.d.ts +14 -0
- package/templates/nuxt/alchemy.run.ts +1 -3
- package/templates/react-router/alchemy.run.ts +1 -3
- package/templates/rwsdk/alchemy.run.ts +0 -2
- package/templates/sveltekit/alchemy.run.ts +1 -3
- package/templates/tanstack-start/alchemy.run.ts +1 -3
- package/templates/typescript/alchemy.run.ts +0 -1
- package/templates/vite/alchemy.run.ts +0 -1
- package/workers/cloudflare-state-store.js +58 -58
- package/lib/cloudflare/bundle/externals.d.ts +0 -3
- package/lib/cloudflare/bundle/externals.d.ts.map +0 -1
- package/lib/cloudflare/bundle/externals.js +0 -35
- package/lib/cloudflare/bundle/externals.js.map +0 -1
- package/lib/cloudflare/bundle/plugin-compat-warning.d.ts +0 -10
- package/lib/cloudflare/bundle/plugin-compat-warning.d.ts.map +0 -1
- package/lib/cloudflare/bundle/plugin-compat-warning.js +0 -67
- package/lib/cloudflare/bundle/plugin-compat-warning.js.map +0 -1
- package/lib/planetscale/api.d.ts +0 -53
- package/lib/planetscale/api.d.ts.map +0 -1
- package/lib/planetscale/api.js +0 -84
- package/lib/planetscale/api.js.map +0 -1
- package/src/cloudflare/bundle/externals.ts +0 -36
- package/src/cloudflare/bundle/plugin-compat-warning.ts +0 -94
- package/src/planetscale/api.ts +0 -115
|
@@ -2,10 +2,10 @@ import crypto from "node:crypto";
|
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { AsyncQueue } from "../util/async-queue.ts";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { withExponentialBackoff } from "../util/retry.ts";
|
|
6
|
+
import { extractCloudflareResult } from "./api-response.ts";
|
|
7
7
|
import type { CloudflareApi } from "./api.ts";
|
|
8
|
-
import type { Assets } from "./assets.ts";
|
|
8
|
+
import type { AssetFile, Assets } from "./assets.ts";
|
|
9
9
|
import type { AssetsConfig, WorkerProps } from "./worker.ts";
|
|
10
10
|
|
|
11
11
|
export interface AssetUploadResult {
|
|
@@ -21,32 +21,6 @@ interface FileMetadata {
|
|
|
21
21
|
size: number;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/**
|
|
25
|
-
* Response from the assets upload session API
|
|
26
|
-
*/
|
|
27
|
-
interface UploadSessionResponse {
|
|
28
|
-
result: {
|
|
29
|
-
jwt: string;
|
|
30
|
-
buckets: string[][];
|
|
31
|
-
};
|
|
32
|
-
success: boolean;
|
|
33
|
-
errors: any[];
|
|
34
|
-
messages: any[];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Response from the file upload API
|
|
39
|
-
*/
|
|
40
|
-
interface UploadResponse {
|
|
41
|
-
result: {
|
|
42
|
-
jwt: string;
|
|
43
|
-
buckets?: string[][];
|
|
44
|
-
};
|
|
45
|
-
success: boolean;
|
|
46
|
-
errors: any[];
|
|
47
|
-
messages: any[];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
24
|
/**
|
|
51
25
|
* Uploads assets to Cloudflare and returns a completion token
|
|
52
26
|
*
|
|
@@ -73,64 +47,41 @@ export async function uploadAssets(
|
|
|
73
47
|
// Process the assets configuration once at the beginning
|
|
74
48
|
const processedConfig = createAssetConfig(assetConfig);
|
|
75
49
|
|
|
76
|
-
const { manifest,
|
|
50
|
+
const { manifest, filesByHash } = await prepareAssetManifest(assets);
|
|
77
51
|
|
|
78
52
|
// Start the upload session
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
53
|
+
const uploadSession = await extractCloudflareResult<{
|
|
54
|
+
jwt: string;
|
|
55
|
+
buckets: string[][];
|
|
56
|
+
}>(
|
|
57
|
+
`create assets upload session for worker "${workerName}"`,
|
|
58
|
+
api.post(
|
|
59
|
+
namespace
|
|
60
|
+
? `/accounts/${api.accountId}/workers/dispatch/namespaces/${namespace}/scripts/${workerName}/assets-upload-session`
|
|
61
|
+
: `/accounts/${api.accountId}/workers/scripts/${workerName}/assets-upload-session`,
|
|
62
|
+
{ manifest },
|
|
63
|
+
),
|
|
87
64
|
);
|
|
88
|
-
|
|
89
|
-
if (!uploadSessionResponse.ok) {
|
|
90
|
-
throw new Error(
|
|
91
|
-
`Failed to start assets upload session: ${uploadSessionResponse.status} ${uploadSessionResponse.statusText} - ${await uploadSessionResponse.text()}`,
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const sessionData =
|
|
96
|
-
(await uploadSessionResponse.json()) as UploadSessionResponse;
|
|
97
|
-
|
|
98
|
-
if (!sessionData?.success) {
|
|
99
|
-
if (sessionData?.errors) {
|
|
100
|
-
throw new CloudflareApiError(
|
|
101
|
-
`Failed to start assets upload session:\n${sessionData.errors
|
|
102
|
-
.map((error) => `- ${error.code}: ${error.message}`)
|
|
103
|
-
.join("\n")}`,
|
|
104
|
-
uploadSessionResponse,
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
throw new CloudflareApiError(
|
|
108
|
-
`Failed to start assets upload session: ${uploadSessionResponse.statusText}`,
|
|
109
|
-
uploadSessionResponse,
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
65
|
// If there are no buckets, assets are already uploaded or empty
|
|
114
|
-
if (!
|
|
66
|
+
if (!uploadSession.buckets || uploadSession.buckets.length === 0) {
|
|
115
67
|
return {
|
|
116
|
-
completionToken:
|
|
68
|
+
completionToken: uploadSession.jwt,
|
|
117
69
|
assetConfig: processedConfig,
|
|
118
70
|
};
|
|
119
71
|
}
|
|
120
72
|
|
|
121
73
|
// Upload the files in batches as specified by the API
|
|
122
|
-
let completionToken =
|
|
123
|
-
const buckets =
|
|
74
|
+
let completionToken = uploadSession.jwt;
|
|
75
|
+
const buckets = uploadSession.buckets;
|
|
124
76
|
|
|
125
77
|
const queue = new AsyncQueue(3);
|
|
126
78
|
await Promise.all(
|
|
127
79
|
buckets.map((bucket) =>
|
|
128
80
|
queue.add(async () => {
|
|
129
|
-
const jwt = await
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
filePathsByHash,
|
|
81
|
+
const jwt = await withExponentialBackoff(
|
|
82
|
+
async () =>
|
|
83
|
+
await uploadBucket(api, uploadSession.jwt, bucket, filesByHash),
|
|
84
|
+
() => true,
|
|
134
85
|
);
|
|
135
86
|
if (jwt) {
|
|
136
87
|
completionToken = jwt;
|
|
@@ -183,68 +134,55 @@ export function createAssetConfig(config?: AssetsConfig): AssetsConfig {
|
|
|
183
134
|
* Prepares the asset manifest for the assets upload session
|
|
184
135
|
*
|
|
185
136
|
* @param assets Assets resource containing files to upload
|
|
186
|
-
* @returns Asset manifest and
|
|
137
|
+
* @returns Asset manifest and files by hash
|
|
187
138
|
*/
|
|
188
139
|
export async function prepareAssetManifest(assets: Assets) {
|
|
189
140
|
const manifest: Record<string, FileMetadata> = {};
|
|
190
|
-
const
|
|
141
|
+
const filesByHash = new Map<string, AssetFile>();
|
|
191
142
|
await Promise.all(
|
|
192
143
|
assets.files.map(async (file) => {
|
|
193
144
|
const { hash, size } = await calculateFileMetadata(file.filePath);
|
|
194
145
|
const key = file.path.startsWith("/") ? file.path : `/${file.path}`;
|
|
195
146
|
manifest[key] = { hash, size };
|
|
196
|
-
|
|
147
|
+
filesByHash.set(hash, file);
|
|
197
148
|
}),
|
|
198
149
|
);
|
|
199
|
-
return { manifest,
|
|
150
|
+
return { manifest, filesByHash };
|
|
200
151
|
}
|
|
201
152
|
|
|
202
153
|
async function uploadBucket(
|
|
203
154
|
api: CloudflareApi,
|
|
204
155
|
jwt: string,
|
|
205
156
|
bucket: string[],
|
|
206
|
-
|
|
157
|
+
filesByHash: Map<string, AssetFile>,
|
|
207
158
|
) {
|
|
208
159
|
const formData = new FormData();
|
|
209
160
|
await Promise.all(
|
|
210
161
|
bucket.map(async (fileHash) => {
|
|
211
|
-
const
|
|
212
|
-
if (!
|
|
162
|
+
const file = filesByHash.get(fileHash);
|
|
163
|
+
if (!file) {
|
|
213
164
|
throw new Error(`Could not find file with hash ${fileHash}`);
|
|
214
165
|
}
|
|
215
|
-
const fileContent = await fs.readFile(filePath);
|
|
166
|
+
const fileContent = await fs.readFile(file.filePath);
|
|
216
167
|
const blob = new Blob([fileContent.toString("base64")], {
|
|
217
|
-
type:
|
|
168
|
+
type: file.contentType,
|
|
218
169
|
});
|
|
219
170
|
formData.append(fileHash, blob, fileHash);
|
|
220
171
|
}),
|
|
221
172
|
);
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
173
|
+
const uploadResult = await extractCloudflareResult<{ jwt?: string }>(
|
|
174
|
+
"upload asset files",
|
|
175
|
+
api.post(
|
|
176
|
+
`/accounts/${api.accountId}/workers/assets/upload?base64=true`,
|
|
177
|
+
formData,
|
|
178
|
+
{
|
|
179
|
+
headers: {
|
|
180
|
+
Authorization: `Bearer ${jwt}`,
|
|
181
|
+
},
|
|
229
182
|
},
|
|
230
|
-
|
|
183
|
+
),
|
|
231
184
|
);
|
|
232
|
-
|
|
233
|
-
if (!uploadResponse.ok) {
|
|
234
|
-
throw new Error(
|
|
235
|
-
`Failed to upload asset files: ${uploadResponse.status} ${uploadResponse.statusText}`,
|
|
236
|
-
);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const uploadData = (await uploadResponse.json()) as UploadResponse;
|
|
240
|
-
if (!uploadData.success) {
|
|
241
|
-
const error = uploadData.errors[0];
|
|
242
|
-
const message = error.message;
|
|
243
|
-
const code = error.code;
|
|
244
|
-
throw new Error(`Failed to upload asset files: ${message} (Code: ${code})`);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
return uploadData.result.jwt;
|
|
185
|
+
return uploadResult.jwt;
|
|
248
186
|
}
|
|
249
187
|
|
|
250
188
|
/**
|
|
@@ -4,11 +4,12 @@ import { err, ok, type Result } from "neverthrow";
|
|
|
4
4
|
import fs from "node:fs/promises";
|
|
5
5
|
import path from "pathe";
|
|
6
6
|
import { logger } from "../util/logger.ts";
|
|
7
|
-
import {
|
|
7
|
+
import { cloudflareInternalPlugin } from "./bundle/cloudflare-internal.ts";
|
|
8
8
|
import { esbuildPluginAlias } from "./bundle/plugin-alias.ts";
|
|
9
|
-
import {
|
|
9
|
+
import { esbuildPluginAsyncLocalStorage } from "./bundle/plugin-als-external.ts";
|
|
10
10
|
import { createHotReloadPlugin } from "./bundle/plugin-hot-reload.ts";
|
|
11
11
|
import { esbuildPluginHybridNodeCompat } from "./bundle/plugin-hybrid-node-compat.ts";
|
|
12
|
+
import { esbuildPluginNodeCompatImports } from "./bundle/plugin-node-compat.ts";
|
|
12
13
|
import { createWasmPlugin } from "./bundle/plugin-wasm.ts";
|
|
13
14
|
import { validateNodeCompat } from "./bundle/validate-node-compat.ts";
|
|
14
15
|
|
|
@@ -76,6 +77,8 @@ export function normalizeWorkerBundle(props: {
|
|
|
76
77
|
cwd: props.cwd,
|
|
77
78
|
outdir: props.outdir,
|
|
78
79
|
sourcemap: props.sourceMap !== false ? true : undefined,
|
|
80
|
+
compatibilityDate: props.compatibilityDate,
|
|
81
|
+
compatibilityFlags: props.compatibilityFlags,
|
|
79
82
|
...props.bundle,
|
|
80
83
|
}),
|
|
81
84
|
);
|
|
@@ -248,6 +251,8 @@ export namespace WorkerBundleSource {
|
|
|
248
251
|
entrypoint: string;
|
|
249
252
|
cwd: string;
|
|
250
253
|
outdir: string;
|
|
254
|
+
compatibilityDate: string;
|
|
255
|
+
compatibilityFlags: string[];
|
|
251
256
|
}
|
|
252
257
|
|
|
253
258
|
export class ESBuild implements WorkerBundleSource {
|
|
@@ -328,6 +333,8 @@ export namespace WorkerBundleSource {
|
|
|
328
333
|
nodeCompat,
|
|
329
334
|
cwd,
|
|
330
335
|
format,
|
|
336
|
+
compatibilityDate: _compatibilityDate,
|
|
337
|
+
compatibilityFlags: _compatibilityFlags,
|
|
331
338
|
...props
|
|
332
339
|
} = this.props;
|
|
333
340
|
return {
|
|
@@ -356,19 +363,49 @@ export namespace WorkerBundleSource {
|
|
|
356
363
|
conditions: props.conditions ?? ["workerd", "worker", "browser"],
|
|
357
364
|
plugins: [
|
|
358
365
|
esbuildPluginAlias(props.alias ?? {}, this.props.cwd),
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
:
|
|
366
|
+
cloudflareInternalPlugin,
|
|
367
|
+
...this.getNodeJSCompatPlugins({
|
|
368
|
+
mode: nodeCompat,
|
|
369
|
+
compatibilityDate: this.props.compatibilityDate,
|
|
370
|
+
compatibilityFlags: this.props.compatibilityFlags,
|
|
371
|
+
}),
|
|
362
372
|
...(props.plugins ?? []),
|
|
363
373
|
...additionalPlugins,
|
|
364
374
|
],
|
|
365
|
-
external: [
|
|
366
|
-
...(nodeCompat === "als" ? external_als : external),
|
|
367
|
-
...(props.external ?? []),
|
|
368
|
-
],
|
|
375
|
+
external: [...(props.external ?? [])],
|
|
369
376
|
} satisfies esbuild.BuildOptions;
|
|
370
377
|
}
|
|
371
378
|
|
|
379
|
+
/**
|
|
380
|
+
* Returns the list of ESBuild plugins to use for a given compat mode.
|
|
381
|
+
*/
|
|
382
|
+
private getNodeJSCompatPlugins({
|
|
383
|
+
mode,
|
|
384
|
+
compatibilityDate,
|
|
385
|
+
compatibilityFlags,
|
|
386
|
+
}: {
|
|
387
|
+
mode: "als" | "v2" | null;
|
|
388
|
+
compatibilityDate?: string;
|
|
389
|
+
compatibilityFlags?: string[];
|
|
390
|
+
}): esbuild.Plugin[] {
|
|
391
|
+
switch (mode) {
|
|
392
|
+
case "als":
|
|
393
|
+
return [
|
|
394
|
+
esbuildPluginAsyncLocalStorage,
|
|
395
|
+
esbuildPluginNodeCompatImports(mode),
|
|
396
|
+
];
|
|
397
|
+
case "v2":
|
|
398
|
+
return [
|
|
399
|
+
esbuildPluginHybridNodeCompat({
|
|
400
|
+
compatibilityDate,
|
|
401
|
+
compatibilityFlags,
|
|
402
|
+
}),
|
|
403
|
+
];
|
|
404
|
+
case null:
|
|
405
|
+
return [esbuildPluginNodeCompatImports(mode)];
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
372
409
|
private async formatBuildOutput(
|
|
373
410
|
metafile: esbuild.Metafile,
|
|
374
411
|
): Promise<WorkerBundle> {
|
|
@@ -442,6 +442,8 @@ export async function prepareWorkerMetadata(
|
|
|
442
442
|
type: "r2_bucket",
|
|
443
443
|
name: bindingName,
|
|
444
444
|
bucket_name: binding.name,
|
|
445
|
+
jurisdiction:
|
|
446
|
+
binding.jurisdiction === "default" ? undefined : binding.jurisdiction,
|
|
445
447
|
});
|
|
446
448
|
} else if (binding.type === "secrets_store_secret") {
|
|
447
449
|
meta.bindings.push({
|
package/src/cloudflare/worker.ts
CHANGED
|
@@ -709,14 +709,29 @@ const _Worker = Resource(
|
|
|
709
709
|
id: string,
|
|
710
710
|
props: WorkerProps<B>,
|
|
711
711
|
) {
|
|
712
|
-
|
|
712
|
+
let adopt = props.adopt ?? this.scope.adopt;
|
|
713
|
+
const workerName =
|
|
714
|
+
props.name ?? this.output?.name ?? this.scope.createPhysicalName(id);
|
|
715
|
+
if (this.phase === "create" && !props.adopt) {
|
|
716
|
+
// it is possible that this worker already exists and was created by the old Website wrapper with a nested scope
|
|
717
|
+
// we need to detect this and set adopt=true so that the previous version will be adopted seamlessly
|
|
718
|
+
|
|
719
|
+
// HEURISTIC: `this.scope` would previously be the nested outer scope alchemy.run
|
|
720
|
+
// so, if `this.scope` has a child of `wrangler.jsonc`, then it is likely that it was created by the old Website wrapper with a nested scope
|
|
721
|
+
if (await this.scope.has("wrangler.jsonc", "cloudflare::WranglerJson")) {
|
|
722
|
+
logger.warn(
|
|
723
|
+
`Migrating Worker '${workerName}' from the legacy Website wrapper.`,
|
|
724
|
+
);
|
|
725
|
+
props.adopt = true;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
|
|
713
729
|
const options = (() => {
|
|
714
730
|
if (props.projectRoot) {
|
|
715
731
|
logger.warn("projectRoot is deprecated, use cwd instead");
|
|
716
732
|
props.cwd = props.projectRoot;
|
|
717
733
|
}
|
|
718
|
-
|
|
719
|
-
props.name ?? this.output?.name ?? this.scope.createPhysicalName(id);
|
|
734
|
+
|
|
720
735
|
const cwd = path.resolve(props.cwd ?? process.cwd());
|
|
721
736
|
const compatibilityDate =
|
|
722
737
|
props.compatibilityDate ?? DEFAULT_COMPATIBILITY_DATE;
|
|
@@ -739,7 +754,8 @@ const _Worker = Resource(
|
|
|
739
754
|
cwd,
|
|
740
755
|
compatibilityDate,
|
|
741
756
|
compatibilityFlags,
|
|
742
|
-
outdir:
|
|
757
|
+
outdir:
|
|
758
|
+
props.bundle?.outdir ?? path.join(cwd, ".alchemy", "out", workerName),
|
|
743
759
|
sourceMap: "sourceMap" in props ? props.sourceMap : undefined,
|
|
744
760
|
});
|
|
745
761
|
|
|
@@ -756,19 +772,19 @@ const _Worker = Resource(
|
|
|
756
772
|
containers.push(binding);
|
|
757
773
|
} else if (
|
|
758
774
|
binding.type === "workflow" &&
|
|
759
|
-
(!binding.scriptName || binding.scriptName ===
|
|
775
|
+
(!binding.scriptName || binding.scriptName === workerName)
|
|
760
776
|
) {
|
|
761
777
|
workflows.push(binding);
|
|
762
778
|
} else if (
|
|
763
779
|
binding.type === "durable_object_namespace" &&
|
|
764
|
-
(!binding.scriptName || binding.scriptName ===
|
|
780
|
+
(!binding.scriptName || binding.scriptName === workerName)
|
|
765
781
|
) {
|
|
766
782
|
durableObjects.push(binding);
|
|
767
783
|
}
|
|
768
784
|
}
|
|
769
785
|
|
|
770
786
|
return {
|
|
771
|
-
name,
|
|
787
|
+
name: workerName,
|
|
772
788
|
cwd,
|
|
773
789
|
compatibilityDate,
|
|
774
790
|
compatibilityFlags,
|
|
@@ -780,7 +796,19 @@ const _Worker = Resource(
|
|
|
780
796
|
durableObjects,
|
|
781
797
|
};
|
|
782
798
|
})();
|
|
799
|
+
|
|
783
800
|
if (this.phase === "delete") {
|
|
801
|
+
// Heuristic: we must detect the case where this is the Worker wrapped in the old Website nested scope and not delete it
|
|
802
|
+
// we must not delete it because what we're actually doing is migrating to a flat worker
|
|
803
|
+
// we will achieve this by checking for a sibling resource with ID wrangler.jsonc and type cloudflare::WranglerJson
|
|
804
|
+
if (await this.scope.has("wrangler.jsonc", "cloudflare::WranglerJson")) {
|
|
805
|
+
// skip deletion
|
|
806
|
+
logger.warn(
|
|
807
|
+
`Migrating Worker '${options.name}' from the legacy Website wrapper.`,
|
|
808
|
+
);
|
|
809
|
+
return this.destroy(true);
|
|
810
|
+
}
|
|
811
|
+
|
|
784
812
|
if (options.bundle.isOk()) {
|
|
785
813
|
await options.bundle.value.delete?.();
|
|
786
814
|
}
|