alchemy 0.44.4 → 0.45.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/lib/alchemy.d.ts +3 -3
- package/lib/alchemy.d.ts.map +1 -1
- package/lib/alchemy.js +5 -2
- package/lib/alchemy.js.map +1 -1
- package/lib/build-date.d.ts +1 -1
- package/lib/build-date.js +1 -1
- package/lib/cloudflare/auth.js +1 -1
- package/lib/cloudflare/auth.js.map +1 -1
- package/lib/cloudflare/bundle/esbuild.d.ts +16 -0
- package/lib/cloudflare/bundle/esbuild.d.ts.map +1 -0
- package/lib/cloudflare/bundle/esbuild.js +159 -0
- package/lib/cloudflare/bundle/esbuild.js.map +1 -0
- package/lib/cloudflare/bundle/fs.d.ts +18 -0
- package/lib/cloudflare/bundle/fs.d.ts.map +1 -0
- package/lib/cloudflare/bundle/fs.js +75 -0
- package/lib/cloudflare/bundle/fs.js.map +1 -0
- package/lib/cloudflare/bundle/index.d.ts +3 -0
- package/lib/cloudflare/bundle/index.d.ts.map +1 -0
- package/lib/cloudflare/bundle/index.js +2 -0
- package/lib/cloudflare/bundle/index.js.map +1 -0
- package/lib/cloudflare/bundle/inline.d.ts +12 -0
- package/lib/cloudflare/bundle/inline.d.ts.map +1 -0
- package/lib/cloudflare/bundle/inline.js +32 -0
- package/lib/cloudflare/bundle/inline.js.map +1 -0
- package/lib/cloudflare/bundle/normalize.d.ts +21 -0
- package/lib/cloudflare/bundle/normalize.d.ts.map +1 -0
- package/lib/cloudflare/bundle/normalize.js +49 -0
- package/lib/cloudflare/bundle/normalize.js.map +1 -0
- package/lib/cloudflare/bundle/{nodejs-import-warning-plugin.d.ts → plugin-compat-warning.d.ts} +2 -2
- package/lib/cloudflare/bundle/plugin-compat-warning.d.ts.map +1 -0
- package/lib/cloudflare/bundle/{nodejs-import-warning-plugin.js → plugin-compat-warning.js} +3 -3
- package/lib/cloudflare/bundle/plugin-compat-warning.js.map +1 -0
- package/lib/cloudflare/bundle/plugin-hot-reload.d.ts +8 -0
- package/lib/cloudflare/bundle/plugin-hot-reload.d.ts.map +1 -0
- package/lib/cloudflare/bundle/plugin-hot-reload.js +19 -0
- package/lib/cloudflare/bundle/plugin-hot-reload.js.map +1 -0
- package/lib/cloudflare/bundle/{nodejs-compat.d.ts → plugin-hybrid-node-compat.d.ts} +2 -2
- package/lib/cloudflare/bundle/plugin-hybrid-node-compat.d.ts.map +1 -0
- package/lib/cloudflare/bundle/{nodejs-compat.js → plugin-hybrid-node-compat.js} +10 -10
- package/lib/cloudflare/bundle/plugin-hybrid-node-compat.js.map +1 -0
- package/lib/cloudflare/bundle/plugin-wasm.d.ts +3 -0
- package/lib/cloudflare/bundle/plugin-wasm.d.ts.map +1 -0
- package/lib/cloudflare/bundle/plugin-wasm.js +55 -0
- package/lib/cloudflare/bundle/plugin-wasm.js.map +1 -0
- package/lib/cloudflare/bundle/shared.d.ts +30 -0
- package/lib/cloudflare/bundle/shared.d.ts.map +1 -0
- package/lib/cloudflare/bundle/shared.js +34 -0
- package/lib/cloudflare/bundle/shared.js.map +1 -0
- package/lib/cloudflare/bundle/{nodejs-compat-mode.d.ts → validate-node-compat.d.ts} +8 -4
- package/lib/cloudflare/bundle/validate-node-compat.d.ts.map +1 -0
- package/lib/cloudflare/bundle/{nodejs-compat-mode.js → validate-node-compat.js} +27 -7
- package/lib/cloudflare/bundle/validate-node-compat.js.map +1 -0
- package/lib/cloudflare/container.d.ts +231 -0
- package/lib/cloudflare/container.d.ts.map +1 -1
- package/lib/cloudflare/container.js +7 -0
- package/lib/cloudflare/container.js.map +1 -1
- package/lib/cloudflare/d1-migrations.d.ts +1 -0
- package/lib/cloudflare/d1-migrations.d.ts.map +1 -1
- package/lib/cloudflare/d1-migrations.js +18 -6
- package/lib/cloudflare/d1-migrations.js.map +1 -1
- package/lib/cloudflare/d1-state-store.d.ts +10 -0
- package/lib/cloudflare/d1-state-store.d.ts.map +1 -0
- package/lib/cloudflare/d1-state-store.js +70 -0
- package/lib/cloudflare/d1-state-store.js.map +1 -0
- package/lib/cloudflare/do-state-store/internal.js +1 -1
- package/lib/cloudflare/do-state-store/internal.js.map +1 -1
- package/lib/cloudflare/do-state-store/store.js +1 -1
- package/lib/cloudflare/do-state-store/store.js.map +1 -1
- package/lib/cloudflare/index.d.ts +3 -2
- package/lib/cloudflare/index.d.ts.map +1 -1
- package/lib/cloudflare/index.js +3 -2
- package/lib/cloudflare/index.js.map +1 -1
- package/lib/cloudflare/local-dev-cloudflare-shim.d.ts.map +1 -0
- package/lib/cloudflare/{bundle/local-dev-cloudflare-shim.js → local-dev-cloudflare-shim.js} +1 -1
- package/lib/cloudflare/local-dev-cloudflare-shim.js.map +1 -0
- package/lib/cloudflare/miniflare/http-server.d.ts.map +1 -0
- package/lib/cloudflare/miniflare/http-server.js.map +1 -0
- package/lib/cloudflare/{worker → miniflare}/miniflare-worker-options.d.ts +4 -3
- package/lib/cloudflare/miniflare/miniflare-worker-options.d.ts.map +1 -0
- package/lib/cloudflare/{worker → miniflare}/miniflare-worker-options.js +6 -3
- package/lib/cloudflare/miniflare/miniflare-worker-options.js.map +1 -0
- package/lib/cloudflare/miniflare/miniflare.d.ts.map +1 -0
- package/lib/cloudflare/{worker → miniflare}/miniflare.js +1 -1
- package/lib/cloudflare/miniflare/miniflare.js.map +1 -0
- package/lib/cloudflare/miniflare/mixed-mode.d.ts.map +1 -0
- package/lib/cloudflare/{worker → miniflare}/mixed-mode.js +1 -2
- package/lib/cloudflare/miniflare/mixed-mode.js.map +1 -0
- package/lib/cloudflare/user.js +1 -1
- package/lib/cloudflare/user.js.map +1 -1
- package/lib/cloudflare/worker/shared.d.ts +4 -0
- package/lib/cloudflare/worker/shared.d.ts.map +1 -0
- package/lib/cloudflare/worker/{get-worker-template.js → shared.js} +10 -1
- package/lib/cloudflare/worker/shared.js.map +1 -0
- package/lib/cloudflare/worker/tail.d.ts +18 -0
- package/lib/cloudflare/worker/tail.d.ts.map +1 -0
- package/lib/cloudflare/worker/tail.js +140 -0
- package/lib/cloudflare/worker/tail.js.map +1 -0
- package/lib/cloudflare/worker-metadata.d.ts +6 -2
- package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
- package/lib/cloudflare/worker-metadata.js +7 -23
- package/lib/cloudflare/worker-metadata.js.map +1 -1
- package/lib/cloudflare/worker-stub.d.ts.map +1 -1
- package/lib/cloudflare/worker-stub.js +8 -7
- package/lib/cloudflare/worker-stub.js.map +1 -1
- package/lib/cloudflare/worker-subdomain.d.ts +31 -0
- package/lib/cloudflare/worker-subdomain.d.ts.map +1 -0
- package/lib/cloudflare/worker-subdomain.js +55 -0
- package/lib/cloudflare/worker-subdomain.js.map +1 -0
- package/lib/cloudflare/worker.d.ts +30 -36
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +641 -569
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/fs/file-system-state-store.js +1 -1
- package/lib/fs/file-system-state-store.js.map +1 -1
- package/lib/scope.d.ts +2 -2
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +23 -8
- package/lib/scope.js.map +1 -1
- package/lib/serde.d.ts +1 -1
- package/lib/serde.d.ts.map +1 -1
- package/lib/serde.js +4 -4
- package/lib/serde.js.map +1 -1
- package/lib/sqlite/base-sqlite-state-store.d.ts +31 -0
- package/lib/sqlite/base-sqlite-state-store.d.ts.map +1 -0
- package/lib/sqlite/base-sqlite-state-store.js +124 -0
- package/lib/sqlite/base-sqlite-state-store.js.map +1 -0
- package/lib/sqlite/index.d.ts +2 -0
- package/lib/sqlite/index.d.ts.map +1 -0
- package/lib/sqlite/index.js +2 -0
- package/lib/sqlite/index.js.map +1 -0
- package/lib/sqlite/schema.d.ts +198 -0
- package/lib/sqlite/schema.d.ts.map +1 -0
- package/lib/sqlite/schema.js +23 -0
- package/lib/sqlite/schema.js.map +1 -0
- package/lib/sqlite/sqlite-state-store.d.ts +60 -0
- package/lib/sqlite/sqlite-state-store.d.ts.map +1 -0
- package/lib/sqlite/sqlite-state-store.js +83 -0
- package/lib/sqlite/sqlite-state-store.js.map +1 -0
- package/lib/test/bun.d.ts.map +1 -1
- package/lib/test/bun.js +0 -6
- package/lib/test/bun.js.map +1 -1
- package/lib/test/vitest.d.ts.map +1 -1
- package/lib/test/vitest.js +19 -5
- package/lib/test/vitest.js.map +1 -1
- package/lib/util/memoize.d.ts +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 +12 -3
- package/src/alchemy.ts +8 -6
- package/src/build-date.ts +1 -1
- package/src/cloudflare/auth.ts +1 -1
- package/src/cloudflare/bundle/esbuild.ts +194 -0
- package/src/cloudflare/bundle/fs.ts +98 -0
- package/src/cloudflare/bundle/index.ts +6 -0
- package/src/cloudflare/bundle/inline.ts +42 -0
- package/src/cloudflare/bundle/normalize.ts +76 -0
- package/src/cloudflare/bundle/{nodejs-import-warning-plugin.ts → plugin-compat-warning.ts} +4 -2
- package/src/cloudflare/bundle/plugin-hot-reload.ts +27 -0
- package/src/cloudflare/bundle/{nodejs-compat.ts → plugin-hybrid-node-compat.ts} +10 -10
- package/src/cloudflare/bundle/plugin-wasm.ts +62 -0
- package/src/cloudflare/bundle/shared.ts +73 -0
- package/src/cloudflare/bundle/{nodejs-compat-mode.ts → validate-node-compat.ts} +41 -16
- package/src/cloudflare/container.ts +296 -0
- package/src/cloudflare/d1-migrations.ts +29 -16
- package/src/cloudflare/d1-state-store.ts +105 -0
- package/src/cloudflare/do-state-store/internal.ts +1 -1
- package/src/cloudflare/do-state-store/store.ts +1 -1
- package/src/cloudflare/index.ts +3 -2
- package/src/cloudflare/{bundle/local-dev-cloudflare-shim.ts → local-dev-cloudflare-shim.ts} +1 -1
- package/src/cloudflare/{worker → miniflare}/miniflare-worker-options.ts +14 -6
- package/src/cloudflare/{worker → miniflare}/miniflare.ts +1 -1
- package/src/cloudflare/{worker → miniflare}/mixed-mode.ts +1 -2
- package/src/cloudflare/user.ts +1 -1
- package/src/cloudflare/worker/{subdomain.ts → shared.ts} +14 -0
- package/src/cloudflare/worker/tail.ts +287 -0
- package/src/cloudflare/worker-metadata.ts +18 -26
- package/src/cloudflare/worker-stub.ts +9 -7
- package/src/cloudflare/worker-subdomain.ts +123 -0
- package/src/cloudflare/worker.ts +863 -760
- package/src/fs/file-system-state-store.ts +1 -1
- package/src/scope.ts +30 -11
- package/src/serde.ts +4 -4
- package/src/sqlite/base-sqlite-state-store.ts +199 -0
- package/src/sqlite/index.ts +1 -0
- package/src/sqlite/schema.ts +37 -0
- package/src/sqlite/sqlite-state-store.ts +174 -0
- package/src/test/bun.ts +0 -8
- package/src/test/vitest.ts +19 -8
- package/src/util/memoize.ts +13 -1
- package/templates/astro/types/env.d.ts +1 -1
- package/templates/nuxt/types/env.d.ts +1 -1
- package/templates/react-router/types/env.d.ts +1 -1
- package/templates/rwsdk/types/env.d.ts +1 -1
- package/templates/sveltekit/types/env.d.ts +1 -1
- package/templates/tanstack-start/types/env.d.ts +1 -1
- package/templates/typescript/types/env.d.ts +1 -1
- package/templates/vite/types/env.d.ts +1 -1
- package/lib/cloudflare/bundle/alias-plugin.d.ts +0 -6
- package/lib/cloudflare/bundle/alias-plugin.d.ts.map +0 -1
- package/lib/cloudflare/bundle/alias-plugin.js +0 -36
- package/lib/cloudflare/bundle/alias-plugin.js.map +0 -1
- package/lib/cloudflare/bundle/build-failures.d.ts +0 -12
- package/lib/cloudflare/bundle/build-failures.d.ts.map +0 -1
- package/lib/cloudflare/bundle/build-failures.js +0 -45
- package/lib/cloudflare/bundle/build-failures.js.map +0 -1
- package/lib/cloudflare/bundle/bundle-worker-dev.d.ts +0 -26
- package/lib/cloudflare/bundle/bundle-worker-dev.d.ts.map +0 -1
- package/lib/cloudflare/bundle/bundle-worker-dev.js +0 -88
- package/lib/cloudflare/bundle/bundle-worker-dev.js.map +0 -1
- package/lib/cloudflare/bundle/bundle-worker.d.ts +0 -13
- package/lib/cloudflare/bundle/bundle-worker.d.ts.map +0 -1
- package/lib/cloudflare/bundle/bundle-worker.js +0 -98
- package/lib/cloudflare/bundle/bundle-worker.js.map +0 -1
- package/lib/cloudflare/bundle/external.d.ts +0 -4
- package/lib/cloudflare/bundle/external.d.ts.map +0 -1
- package/lib/cloudflare/bundle/external.js +0 -40
- package/lib/cloudflare/bundle/external.js.map +0 -1
- package/lib/cloudflare/bundle/local-dev-cloudflare-shim.d.ts.map +0 -1
- package/lib/cloudflare/bundle/local-dev-cloudflare-shim.js.map +0 -1
- package/lib/cloudflare/bundle/nodejs-compat-mode.d.ts.map +0 -1
- package/lib/cloudflare/bundle/nodejs-compat-mode.js.map +0 -1
- package/lib/cloudflare/bundle/nodejs-compat.d.ts.map +0 -1
- package/lib/cloudflare/bundle/nodejs-compat.js.map +0 -1
- package/lib/cloudflare/bundle/nodejs-import-warning-plugin.d.ts.map +0 -1
- package/lib/cloudflare/bundle/nodejs-import-warning-plugin.js.map +0 -1
- package/lib/cloudflare/bundle/wasm-plugin.d.ts +0 -3
- package/lib/cloudflare/bundle/wasm-plugin.d.ts.map +0 -1
- package/lib/cloudflare/bundle/wasm-plugin.js +0 -53
- package/lib/cloudflare/bundle/wasm-plugin.js.map +0 -1
- package/lib/cloudflare/worker/get-worker-template.d.ts +0 -2
- package/lib/cloudflare/worker/get-worker-template.d.ts.map +0 -1
- package/lib/cloudflare/worker/get-worker-template.js.map +0 -1
- package/lib/cloudflare/worker/http-server.d.ts.map +0 -1
- package/lib/cloudflare/worker/http-server.js.map +0 -1
- package/lib/cloudflare/worker/miniflare-worker-options.d.ts.map +0 -1
- package/lib/cloudflare/worker/miniflare-worker-options.js.map +0 -1
- package/lib/cloudflare/worker/miniflare.d.ts.map +0 -1
- package/lib/cloudflare/worker/miniflare.js.map +0 -1
- package/lib/cloudflare/worker/mixed-mode.d.ts.map +0 -1
- package/lib/cloudflare/worker/mixed-mode.js.map +0 -1
- package/lib/cloudflare/worker/subdomain.d.ts +0 -3
- package/lib/cloudflare/worker/subdomain.d.ts.map +0 -1
- package/lib/cloudflare/worker/subdomain.js +0 -10
- package/lib/cloudflare/worker/subdomain.js.map +0 -1
- package/src/cloudflare/bundle/alias-plugin.ts +0 -48
- package/src/cloudflare/bundle/build-failures.ts +0 -55
- package/src/cloudflare/bundle/bundle-worker-dev.ts +0 -129
- package/src/cloudflare/bundle/bundle-worker.ts +0 -150
- package/src/cloudflare/bundle/external.ts +0 -41
- package/src/cloudflare/bundle/wasm-plugin.ts +0 -57
- package/src/cloudflare/worker/get-worker-template.ts +0 -14
- /package/lib/cloudflare/{bundle/local-dev-cloudflare-shim.d.ts → local-dev-cloudflare-shim.d.ts} +0 -0
- /package/lib/cloudflare/{worker → miniflare}/http-server.d.ts +0 -0
- /package/lib/cloudflare/{worker → miniflare}/http-server.js +0 -0
- /package/lib/cloudflare/{worker → miniflare}/miniflare.d.ts +0 -0
- /package/lib/cloudflare/{worker → miniflare}/mixed-mode.d.ts +0 -0
- /package/src/cloudflare/{worker → miniflare}/http-server.ts +0 -0
package/lib/cloudflare/worker.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import kleur from "kleur";
|
|
1
2
|
import { spawn } from "node:child_process";
|
|
2
3
|
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
3
|
-
import
|
|
4
|
+
import { isDeepStrictEqual } from "node:util";
|
|
5
|
+
import path from "pathe";
|
|
4
6
|
import { BUILD_DATE } from "../build-date.js";
|
|
5
7
|
import { InnerResourceScope, Resource, ResourceKind } from "../resource.js";
|
|
6
8
|
import { getBindKey, tryGetBinding } from "../runtime/bind.js";
|
|
@@ -9,7 +11,6 @@ import { bootstrapPlugin } from "../runtime/plugin.js";
|
|
|
9
11
|
import { Scope } from "../scope.js";
|
|
10
12
|
import { Secret, secret } from "../secret.js";
|
|
11
13
|
import { serializeScope } from "../serde.js";
|
|
12
|
-
import { getContentType } from "../util/content-type.js";
|
|
13
14
|
import { DeferredPromise } from "../util/deferred-promise.js";
|
|
14
15
|
import { logger } from "../util/logger.js";
|
|
15
16
|
import { withExponentialBackoff } from "../util/retry.js";
|
|
@@ -17,14 +18,15 @@ import { CloudflareApiError, handleApiError } from "./api-error.js";
|
|
|
17
18
|
import { createCloudflareApi, } from "./api.js";
|
|
18
19
|
import { Json, } from "./bindings.js";
|
|
19
20
|
import { isBucket } from "./bucket.js";
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
21
|
+
import { normalizeWorkerBundle, } from "./bundle/index.js";
|
|
22
|
+
import { wrap } from "./bundle/normalize.js";
|
|
22
23
|
import { ContainerApplication } from "./container.js";
|
|
23
24
|
import { CustomDomain } from "./custom-domain.js";
|
|
24
25
|
import { isD1Database } from "./d1-database.js";
|
|
25
26
|
import { DurableObjectNamespace, isDurableObjectNamespace, } from "./durable-object-namespace.js";
|
|
26
27
|
import { isQueueEventSource, } from "./event-source.js";
|
|
27
28
|
import { isKVNamespace } from "./kv-namespace.js";
|
|
29
|
+
import { miniflareServer } from "./miniflare/miniflare.js";
|
|
28
30
|
import { isPipeline } from "./pipeline.js";
|
|
29
31
|
import { QueueConsumer, deleteQueueConsumer, listQueueConsumersForWorker, } from "./queue-consumer.js";
|
|
30
32
|
import { isQueue } from "./queue.js";
|
|
@@ -33,8 +35,8 @@ import { isVectorizeIndex } from "./vectorize-index.js";
|
|
|
33
35
|
import { uploadAssets } from "./worker-assets.js";
|
|
34
36
|
import { bumpMigrationTagVersion, prepareWorkerMetadata, } from "./worker-metadata.js";
|
|
35
37
|
import { WorkerStub, isWorkerStub } from "./worker-stub.js";
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
+
import { WorkerSubdomain, disableWorkerSubdomain } from "./worker-subdomain.js";
|
|
39
|
+
import { createTail } from "./worker/tail.js";
|
|
38
40
|
import { Workflow, isWorkflow, upsertWorkflow } from "./workflow.js";
|
|
39
41
|
export function isWorker(resource) {
|
|
40
42
|
return resource[ResourceKind] === "cloudflare::Worker";
|
|
@@ -224,174 +226,60 @@ export const DEFAULT_COMPATIBILITY_DATE = BUILD_DATE;
|
|
|
224
226
|
export const _Worker = Resource("cloudflare::Worker", {
|
|
225
227
|
alwaysUpdate: true,
|
|
226
228
|
}, async function (id, props) {
|
|
227
|
-
if (props.noBundle && !props.entrypoint) {
|
|
228
|
-
throw new Error("entrypoint must be provided when noBundle is true");
|
|
229
|
-
}
|
|
230
|
-
// Use the provided name
|
|
231
|
-
const workerName = props.name ?? id;
|
|
232
229
|
if (props.projectRoot) {
|
|
233
230
|
logger.warn("projectRoot is deprecated, use cwd instead");
|
|
234
231
|
props.cwd = props.projectRoot;
|
|
235
232
|
}
|
|
236
|
-
const cwd =
|
|
233
|
+
const cwd = path.resolve(props.cwd ?? process.cwd());
|
|
237
234
|
const relativeCwd = cwd === process.cwd() ? undefined : path.relative(process.cwd(), cwd);
|
|
235
|
+
const workerName = props.name ?? id;
|
|
238
236
|
const compatibilityDate = props.compatibilityDate ?? DEFAULT_COMPATIBILITY_DATE;
|
|
239
237
|
const compatibilityFlags = props.compatibilityFlags ?? [];
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
bindings: props.bindings ?? {},
|
|
260
|
-
env: props.env,
|
|
261
|
-
observability: props.observability,
|
|
262
|
-
createdAt: now,
|
|
263
|
-
updatedAt: now,
|
|
264
|
-
eventSources: props.eventSources,
|
|
265
|
-
url: props.dev.url,
|
|
266
|
-
dev: props.dev,
|
|
267
|
-
// Include assets configuration in the output
|
|
268
|
-
assets: props.assets,
|
|
269
|
-
// Include cron triggers in the output
|
|
270
|
-
crons: props.crons,
|
|
271
|
-
// phantom property
|
|
272
|
-
Env: undefined,
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
const sharedOptions = {
|
|
276
|
-
name: workerName,
|
|
277
|
-
compatibilityDate,
|
|
278
|
-
compatibilityFlags,
|
|
279
|
-
bindings: props.bindings ?? {},
|
|
280
|
-
port: typeof props.dev === "object" ? props.dev.port : undefined,
|
|
281
|
-
};
|
|
238
|
+
const dispatchNamespace = typeof props.namespace === "string"
|
|
239
|
+
? props.namespace
|
|
240
|
+
: props.namespace?.namespaceName;
|
|
241
|
+
const dev = normalizeDev(this, props.dev);
|
|
242
|
+
const [bundle, error] = wrap(() => normalizeWorkerBundle({
|
|
243
|
+
entrypoint: props.entrypoint,
|
|
244
|
+
script: props.script,
|
|
245
|
+
format: props.format,
|
|
246
|
+
noBundle: props.noBundle,
|
|
247
|
+
rules: "rules" in props ? props.rules : undefined,
|
|
248
|
+
bundle: props.bundle,
|
|
249
|
+
cwd,
|
|
250
|
+
compatibilityDate,
|
|
251
|
+
compatibilityFlags,
|
|
252
|
+
outdir: props.bundle?.outdir ??
|
|
253
|
+
path.join(process.cwd(), ".alchemy", ...this.scope.chain, id),
|
|
254
|
+
sourceMap: "sourceMap" in props ? props.sourceMap : undefined,
|
|
255
|
+
}));
|
|
256
|
+
if (dev.local) {
|
|
282
257
|
let url;
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
const startPromise = new DeferredPromise();
|
|
286
|
-
await createWorkerDevContext(workerName, {
|
|
287
|
-
...props,
|
|
288
|
-
entrypoint: props.entrypoint,
|
|
289
|
-
cwd,
|
|
290
|
-
compatibilityDate,
|
|
291
|
-
compatibilityFlags,
|
|
292
|
-
}, {
|
|
293
|
-
onBuildStart: () => {
|
|
294
|
-
logger.task("miniflare-server", {
|
|
295
|
-
message: `${startPromise.status === "pending" ? "Building" : "Rebuilding"}`,
|
|
296
|
-
status: "pending",
|
|
297
|
-
resource: id,
|
|
298
|
-
prefix: "build",
|
|
299
|
-
prefixColor: "cyanBright",
|
|
300
|
-
});
|
|
301
|
-
},
|
|
302
|
-
onBuildEnd: async (newScript) => {
|
|
303
|
-
try {
|
|
304
|
-
// Hot reload callback - update the miniflare worker
|
|
305
|
-
const server = await miniflareServer.push({
|
|
306
|
-
...sharedOptions,
|
|
307
|
-
script: newScript,
|
|
308
|
-
});
|
|
309
|
-
if (startPromise.status === "pending") {
|
|
310
|
-
logger.task("miniflare-server", {
|
|
311
|
-
message: `Started Miniflare server at ${server.url}`,
|
|
312
|
-
status: "success",
|
|
313
|
-
resource: id,
|
|
314
|
-
prefix: "ready",
|
|
315
|
-
prefixColor: "cyanBright",
|
|
316
|
-
});
|
|
317
|
-
startPromise.resolve(server.url);
|
|
318
|
-
}
|
|
319
|
-
else {
|
|
320
|
-
logger.task("miniflare-server", {
|
|
321
|
-
message: `Updated Miniflare server at ${server.url}`,
|
|
322
|
-
status: "success",
|
|
323
|
-
resource: id,
|
|
324
|
-
prefix: "reload",
|
|
325
|
-
prefixColor: "cyanBright",
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
catch (error) {
|
|
330
|
-
if (startPromise.status === "pending") {
|
|
331
|
-
logger.error(error);
|
|
332
|
-
logger.task("miniflare-server", {
|
|
333
|
-
message: "Failed to start Miniflare server",
|
|
334
|
-
status: "failure",
|
|
335
|
-
resource: id,
|
|
336
|
-
prefix: "error",
|
|
337
|
-
prefixColor: "redBright",
|
|
338
|
-
});
|
|
339
|
-
startPromise.reject(new Error(`Failed to start Miniflare server for worker "${workerName}"`, { cause: error }));
|
|
340
|
-
}
|
|
341
|
-
else {
|
|
342
|
-
logger.task("miniflare-server", {
|
|
343
|
-
message: "Failed to update Miniflare server",
|
|
344
|
-
status: "failure",
|
|
345
|
-
resource: id,
|
|
346
|
-
prefix: "error",
|
|
347
|
-
prefixColor: "redBright",
|
|
348
|
-
});
|
|
349
|
-
logger.error(error);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
},
|
|
353
|
-
onBuildError: (errors) => {
|
|
354
|
-
if (startPromise.status === "pending") {
|
|
355
|
-
logger.task("miniflare-server", {
|
|
356
|
-
message: "Failed to build worker",
|
|
357
|
-
status: "failure",
|
|
358
|
-
resource: id,
|
|
359
|
-
prefix: "error",
|
|
360
|
-
prefixColor: "redBright",
|
|
361
|
-
});
|
|
362
|
-
startPromise.reject(errors);
|
|
363
|
-
}
|
|
364
|
-
else {
|
|
365
|
-
logger.task("miniflare-server", {
|
|
366
|
-
message: "Failed to rebuild worker",
|
|
367
|
-
status: "failure",
|
|
368
|
-
resource: id,
|
|
369
|
-
prefix: "error",
|
|
370
|
-
prefixColor: "redBright",
|
|
371
|
-
});
|
|
372
|
-
logger.error(errors);
|
|
373
|
-
}
|
|
374
|
-
},
|
|
375
|
-
});
|
|
376
|
-
url = await startPromise.value;
|
|
258
|
+
if (error) {
|
|
259
|
+
throw error;
|
|
377
260
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
261
|
+
switch (dev.type) {
|
|
262
|
+
case "command":
|
|
263
|
+
createDevCommand({
|
|
264
|
+
id,
|
|
265
|
+
command: dev.command,
|
|
266
|
+
cwd: dev.cwd ?? process.cwd(),
|
|
267
|
+
env: props.env ?? {},
|
|
268
|
+
});
|
|
269
|
+
url = dev.url;
|
|
270
|
+
break;
|
|
271
|
+
case "miniflare": {
|
|
272
|
+
url = await createMiniflare({
|
|
273
|
+
id,
|
|
274
|
+
workerName,
|
|
385
275
|
compatibilityDate,
|
|
386
276
|
compatibilityFlags,
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
});
|
|
394
|
-
url = server.url;
|
|
277
|
+
bindings: props.bindings,
|
|
278
|
+
bundle,
|
|
279
|
+
port: dev.port,
|
|
280
|
+
});
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
395
283
|
}
|
|
396
284
|
return this({
|
|
397
285
|
type: "service",
|
|
@@ -402,11 +290,11 @@ export const _Worker = Resource("cloudflare::Worker", {
|
|
|
402
290
|
compatibilityDate,
|
|
403
291
|
compatibilityFlags,
|
|
404
292
|
format: props.format || "esm", // Include format in the output
|
|
405
|
-
bindings: props.bindings
|
|
293
|
+
bindings: normalizeExportBindings(workerName, props.bindings),
|
|
406
294
|
env: props.env,
|
|
407
295
|
observability: props.observability,
|
|
408
|
-
createdAt: now,
|
|
409
|
-
updatedAt: now,
|
|
296
|
+
createdAt: this.output?.createdAt ?? Date.now(),
|
|
297
|
+
updatedAt: Date.now(),
|
|
410
298
|
eventSources: props.eventSources,
|
|
411
299
|
url,
|
|
412
300
|
dev: props.dev,
|
|
@@ -418,59 +306,48 @@ export const _Worker = Resource("cloudflare::Worker", {
|
|
|
418
306
|
Env: undefined,
|
|
419
307
|
});
|
|
420
308
|
}
|
|
421
|
-
// Create Cloudflare API client with automatic account discovery
|
|
422
309
|
const api = await createCloudflareApi(props);
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
310
|
+
if (this.phase === "delete") {
|
|
311
|
+
await bundle?.delete?.();
|
|
312
|
+
if (!props.version) {
|
|
313
|
+
await deleteQueueConsumers(api, workerName);
|
|
314
|
+
await deleteWorker(api, {
|
|
315
|
+
scriptName: workerName,
|
|
316
|
+
dispatchNamespace,
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
return this.destroy();
|
|
320
|
+
}
|
|
321
|
+
else if (error) {
|
|
322
|
+
throw error;
|
|
323
|
+
}
|
|
324
|
+
let assetsBinding;
|
|
325
|
+
const workflowsBindings = [];
|
|
326
|
+
const containersBindings = [];
|
|
327
|
+
for (const binding of Object.values(props.bindings ?? {})) {
|
|
328
|
+
if (typeof binding === "object") {
|
|
329
|
+
if (binding.type === "assets") {
|
|
330
|
+
assetsBinding = binding;
|
|
331
|
+
}
|
|
332
|
+
else if (binding.type === "workflow") {
|
|
333
|
+
workflowsBindings.push(binding);
|
|
334
|
+
}
|
|
335
|
+
else if (binding.type === "container") {
|
|
336
|
+
containersBindings.push(binding);
|
|
450
337
|
}
|
|
451
338
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
: props.namespace.namespace
|
|
457
|
-
: undefined;
|
|
458
|
-
// Upload any assets and get completion tokens
|
|
459
|
-
let assetUploadResult;
|
|
460
|
-
if (assetsBindings.length > 0) {
|
|
461
|
-
// We'll use the first asset binding for now
|
|
462
|
-
// In the future, we might want to support multiple asset bindings
|
|
463
|
-
const assetBinding = assetsBindings[0];
|
|
464
|
-
// Upload the assets and get the completion token
|
|
465
|
-
assetUploadResult = await uploadAssets(api, {
|
|
339
|
+
}
|
|
340
|
+
const putWorkerWithAssets = async (props, scriptBundle) => {
|
|
341
|
+
const assetUploadResult = assetsBinding
|
|
342
|
+
? await uploadAssets(api, {
|
|
466
343
|
workerName,
|
|
467
|
-
assets:
|
|
344
|
+
assets: assetsBinding,
|
|
468
345
|
assetConfig: props.assets,
|
|
469
346
|
namespace: dispatchNamespace,
|
|
470
|
-
})
|
|
471
|
-
|
|
347
|
+
})
|
|
348
|
+
: undefined;
|
|
472
349
|
// Deploy worker (either as version or live worker)
|
|
473
|
-
|
|
350
|
+
return await putWorker(api, {
|
|
474
351
|
...props,
|
|
475
352
|
workerName,
|
|
476
353
|
scriptBundle,
|
|
@@ -480,115 +357,14 @@ export const _Worker = Resource("cloudflare::Worker", {
|
|
|
480
357
|
compatibilityFlags,
|
|
481
358
|
assetUploadResult,
|
|
482
359
|
});
|
|
483
|
-
versionResult.versionId;
|
|
484
|
-
for (const workflow of workflowsBindings) {
|
|
485
|
-
if (workflow.scriptName === undefined ||
|
|
486
|
-
workflow.scriptName === workerName) {
|
|
487
|
-
await upsertWorkflow(api, {
|
|
488
|
-
workflowName: workflow.workflowName,
|
|
489
|
-
className: workflow.className,
|
|
490
|
-
scriptName: workflow.scriptName ?? workerName,
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
for (const container of containersBindings) {
|
|
495
|
-
async function findNamespaceId() {
|
|
496
|
-
const response = await api.get(`/accounts/${api.accountId}/workers/scripts/${workerName}/versions/${versionResult.deploymentId}`);
|
|
497
|
-
const result = (await response.json());
|
|
498
|
-
const namespaceId = result.result.resources.bindings.find((binding) => binding.type === "durable_object_namespace" &&
|
|
499
|
-
binding.class_name === container.className)?.namespace_id;
|
|
500
|
-
if (!namespaceId) {
|
|
501
|
-
throw new Error(`Namespace ID not found for container ${container.id}`);
|
|
502
|
-
}
|
|
503
|
-
return namespaceId;
|
|
504
|
-
}
|
|
505
|
-
await ContainerApplication(container.id, {
|
|
506
|
-
accountId: props.accountId,
|
|
507
|
-
apiKey: props.apiKey,
|
|
508
|
-
apiToken: props.apiToken,
|
|
509
|
-
baseUrl: props.baseUrl,
|
|
510
|
-
email: props.email,
|
|
511
|
-
image: container.image,
|
|
512
|
-
name: container.id,
|
|
513
|
-
instanceType: container.instanceType,
|
|
514
|
-
observability: container.observability,
|
|
515
|
-
durableObjects: {
|
|
516
|
-
namespaceId: await findNamespaceId(),
|
|
517
|
-
},
|
|
518
|
-
schedulingPolicy: container.schedulingPolicy,
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
await Promise.all(props.eventSources?.map((eventSource) => {
|
|
522
|
-
if (isQueue(eventSource) || isQueueEventSource(eventSource)) {
|
|
523
|
-
const queue = isQueue(eventSource)
|
|
524
|
-
? eventSource
|
|
525
|
-
: eventSource.queue;
|
|
526
|
-
return QueueConsumer(`${queue.id}-consumer`, {
|
|
527
|
-
queue,
|
|
528
|
-
scriptName: workerName,
|
|
529
|
-
accountId: api.accountId,
|
|
530
|
-
adopt: props.adopt,
|
|
531
|
-
settings: isQueueEventSource(eventSource)
|
|
532
|
-
? eventSource.settings
|
|
533
|
-
: queue.dlq
|
|
534
|
-
? { deadLetterQueue: queue.dlq }
|
|
535
|
-
: undefined,
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
throw new Error(`Unsupported event source type: ${eventSource}`);
|
|
539
|
-
}) ?? []);
|
|
540
|
-
// Handle worker URL if requested
|
|
541
|
-
let workerUrl;
|
|
542
|
-
if (props.version) {
|
|
543
|
-
// For versions, use the preview URL if available
|
|
544
|
-
workerUrl = versionResult?.previewUrl;
|
|
545
|
-
}
|
|
546
|
-
else if (!props.namespace) {
|
|
547
|
-
// namespaces don't support URLs
|
|
548
|
-
// For regular workers, use the normal URL configuration
|
|
549
|
-
workerUrl = await configureURL(this, api, {
|
|
550
|
-
...props,
|
|
551
|
-
workerName,
|
|
552
|
-
url: props.url ?? true,
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
// Get current timestamp
|
|
556
|
-
const now = Date.now();
|
|
557
|
-
// Update cron triggers
|
|
558
|
-
if (props.crons) {
|
|
559
|
-
const res = await api.put(`/accounts/${api.accountId}/workers/scripts/${workerName}/schedules`, props.crons.map((cron) => ({ cron })));
|
|
560
|
-
if (!res.ok) {
|
|
561
|
-
await handleApiError(res, "updating cron triggers", "worker", workerName);
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
return { scriptBundle, workerUrl, now, versionResult };
|
|
565
360
|
};
|
|
566
|
-
if (this.phase === "delete") {
|
|
567
|
-
// only delete the worker if it's not a version
|
|
568
|
-
if (!props.version) {
|
|
569
|
-
// Delete any queue consumers attached to this worker first
|
|
570
|
-
await deleteQueueConsumers(api, workerName);
|
|
571
|
-
await withExponentialBackoff(() => deleteWorker(api, {
|
|
572
|
-
workerName,
|
|
573
|
-
namespace: typeof props.namespace === "string"
|
|
574
|
-
? props.namespace
|
|
575
|
-
: props.namespace?.namespaceId,
|
|
576
|
-
url: this.output.url,
|
|
577
|
-
}), (err) => (err.status === 400 &&
|
|
578
|
-
err.message.includes("is still referenced by service bindings in Workers")) ||
|
|
579
|
-
err.status === 500 ||
|
|
580
|
-
err.status === 503, 10, 100);
|
|
581
|
-
}
|
|
582
|
-
return this.destroy();
|
|
583
|
-
}
|
|
584
361
|
if (this.phase === "create") {
|
|
585
362
|
if (props.version) {
|
|
586
363
|
// When version is specified, we adopt existing workers or create them if they don't exist
|
|
587
|
-
|
|
588
|
-
if (!workerExists) {
|
|
364
|
+
if (!(await workerExists(api, workerName))) {
|
|
589
365
|
// Create the base worker first if it doesn't exist
|
|
590
366
|
const baseWorkerProps = { ...props, version: undefined };
|
|
591
|
-
await
|
|
367
|
+
await putWorkerWithAssets(baseWorkerProps, await bundle.create());
|
|
592
368
|
}
|
|
593
369
|
// We always "adopt" when publishing versions
|
|
594
370
|
}
|
|
@@ -596,73 +372,136 @@ export const _Worker = Resource("cloudflare::Worker", {
|
|
|
596
372
|
await assertWorkerDoesNotExist(api, workerName);
|
|
597
373
|
}
|
|
598
374
|
}
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
:
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
375
|
+
let putWorkerResult;
|
|
376
|
+
if (dev.type === "remote") {
|
|
377
|
+
// todo(john): clean this up and add log tail
|
|
378
|
+
const controller = new AbortController();
|
|
379
|
+
cleanups.push(() => controller.abort());
|
|
380
|
+
const watcher = await bundle.watch(controller.signal);
|
|
381
|
+
const promise = new DeferredPromise();
|
|
382
|
+
void watcher.pipeTo(new WritableStream({
|
|
383
|
+
async write(chunk) {
|
|
384
|
+
switch (chunk.type) {
|
|
385
|
+
case "start":
|
|
386
|
+
logger.task("", {
|
|
387
|
+
message: "start",
|
|
388
|
+
status: "pending",
|
|
389
|
+
resource: id,
|
|
390
|
+
prefix: "build",
|
|
391
|
+
prefixColor: "cyanBright",
|
|
392
|
+
});
|
|
393
|
+
break;
|
|
394
|
+
case "end": {
|
|
395
|
+
if (promise.status === "pending") {
|
|
396
|
+
await putWorkerWithAssets(props, chunk.result)
|
|
397
|
+
.then((result) => promise.resolve(result))
|
|
398
|
+
.catch((error) => {
|
|
399
|
+
controller.abort();
|
|
400
|
+
promise.reject(error);
|
|
401
|
+
});
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
logger.task("", {
|
|
405
|
+
message: "reload",
|
|
406
|
+
status: "success",
|
|
407
|
+
resource: id,
|
|
408
|
+
prefix: "build",
|
|
409
|
+
prefixColor: "cyanBright",
|
|
410
|
+
});
|
|
411
|
+
await putWorker(api, {
|
|
412
|
+
...props,
|
|
413
|
+
workerName,
|
|
414
|
+
scriptBundle: chunk.result,
|
|
415
|
+
dispatchNamespace,
|
|
416
|
+
version: props.version,
|
|
417
|
+
compatibilityDate,
|
|
418
|
+
compatibilityFlags,
|
|
419
|
+
assetUploadResult: assetsBinding
|
|
420
|
+
? {
|
|
421
|
+
keepAssets: true,
|
|
422
|
+
assetConfig: props.assets,
|
|
423
|
+
}
|
|
424
|
+
: undefined,
|
|
425
|
+
unstable_cacheWorkerSettings: true,
|
|
426
|
+
});
|
|
427
|
+
logger.task("", {
|
|
428
|
+
message: "updated",
|
|
429
|
+
status: "success",
|
|
430
|
+
resource: id,
|
|
431
|
+
prefix: "build",
|
|
432
|
+
prefixColor: "greenBright",
|
|
433
|
+
});
|
|
434
|
+
break;
|
|
435
|
+
}
|
|
436
|
+
case "error":
|
|
437
|
+
logger.task("", {
|
|
438
|
+
message: "error",
|
|
439
|
+
status: "failure",
|
|
440
|
+
resource: id,
|
|
441
|
+
prefix: "build",
|
|
442
|
+
prefixColor: "redBright",
|
|
443
|
+
});
|
|
444
|
+
logger.error(chunk.errors);
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
},
|
|
623
448
|
}));
|
|
449
|
+
putWorkerResult = await promise.value;
|
|
450
|
+
const tail = await createTail(api, id, workerName);
|
|
451
|
+
cleanups.push(() => tail.close());
|
|
624
452
|
}
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
if (props.routes && props.routes.length > 0) {
|
|
628
|
-
ensureNoDuplicates("Route", props.routes.map((route) => typeof route === "string" ? route : route.pattern));
|
|
629
|
-
// Create Route resources for each route and capture their outputs
|
|
630
|
-
createdRoutes = await Promise.all(props.routes.map(async (routeConfig) => {
|
|
631
|
-
const pattern = typeof routeConfig === "string" ? routeConfig : routeConfig.pattern;
|
|
632
|
-
return await Route(pattern, {
|
|
633
|
-
pattern,
|
|
634
|
-
script: workerName,
|
|
635
|
-
zoneId: typeof routeConfig === "string" ? undefined : routeConfig.zoneId, // Route resource will handle inference if not provided
|
|
636
|
-
adopt: typeof routeConfig === "string"
|
|
637
|
-
? (props.adopt ?? false)
|
|
638
|
-
: (routeConfig.adopt ?? props.adopt),
|
|
639
|
-
accountId: props.accountId,
|
|
640
|
-
apiKey: props.apiKey,
|
|
641
|
-
apiToken: props.apiToken,
|
|
642
|
-
baseUrl: props.baseUrl,
|
|
643
|
-
email: props.email,
|
|
644
|
-
});
|
|
645
|
-
}));
|
|
453
|
+
else {
|
|
454
|
+
putWorkerResult = await putWorkerWithAssets(props, await bundle.create());
|
|
646
455
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
456
|
+
const tasks = [];
|
|
457
|
+
for (const workflow of workflowsBindings) {
|
|
458
|
+
if (workflow.scriptName === undefined ||
|
|
459
|
+
workflow.scriptName === workerName) {
|
|
460
|
+
tasks.push(upsertWorkflow(api, {
|
|
461
|
+
workflowName: workflow.workflowName,
|
|
462
|
+
className: workflow.className,
|
|
463
|
+
scriptName: workflow.scriptName ?? workerName,
|
|
464
|
+
}));
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
if (containersBindings.length > 0) {
|
|
468
|
+
tasks.push(getVersionMetadata(api, workerName, putWorkerResult.deployment_id).then((versionMetadata) => provisionContainers(api, {
|
|
469
|
+
scriptName: workerName,
|
|
470
|
+
containers: containersBindings,
|
|
471
|
+
bindings: versionMetadata.resources.bindings,
|
|
472
|
+
})));
|
|
473
|
+
}
|
|
474
|
+
if (!isDeepStrictEqual(props.crons, this.output?.crons)) {
|
|
475
|
+
tasks.push(api.put(`/accounts/${api.accountId}/workers/scripts/${workerName}/schedules`, props.crons?.map((cron) => ({ cron })) ?? []));
|
|
665
476
|
}
|
|
477
|
+
tasks.push(provisionEventSources(api, {
|
|
478
|
+
scriptName: workerName,
|
|
479
|
+
eventSources: props.eventSources,
|
|
480
|
+
}));
|
|
481
|
+
const [domains, routes, subdomain] = await Promise.all([
|
|
482
|
+
// TODO: can you provision domains and routes in parallel, or is there a dependency?
|
|
483
|
+
provisionDomains(api, {
|
|
484
|
+
scriptName: workerName,
|
|
485
|
+
adopt: props.adopt,
|
|
486
|
+
domains: props.domains,
|
|
487
|
+
}),
|
|
488
|
+
provisionRoutes(api, {
|
|
489
|
+
scriptName: workerName,
|
|
490
|
+
adopt: props.adopt,
|
|
491
|
+
routes: props.routes,
|
|
492
|
+
}),
|
|
493
|
+
provisionSubdomain(api, {
|
|
494
|
+
scriptName: workerName,
|
|
495
|
+
enable: props.url ?? dispatchNamespace === undefined,
|
|
496
|
+
previewVersionId: props.version && putWorkerResult.metadata.has_preview
|
|
497
|
+
? putWorkerResult.id
|
|
498
|
+
: undefined,
|
|
499
|
+
retain: !!props.version,
|
|
500
|
+
forceDelete: this.phase === "create" && !!props.adopt && props.url === false,
|
|
501
|
+
}),
|
|
502
|
+
...tasks,
|
|
503
|
+
]);
|
|
504
|
+
const now = Date.now();
|
|
666
505
|
// Construct the output
|
|
667
506
|
return this({
|
|
668
507
|
...props,
|
|
@@ -674,22 +513,22 @@ export const _Worker = Resource("cloudflare::Worker", {
|
|
|
674
513
|
compatibilityDate,
|
|
675
514
|
compatibilityFlags,
|
|
676
515
|
format: props.format || "esm", // Include format in the output
|
|
677
|
-
bindings:
|
|
516
|
+
bindings: normalizeExportBindings(workerName, props.bindings),
|
|
678
517
|
env: props.env,
|
|
679
518
|
observability: props.observability,
|
|
680
|
-
createdAt: now,
|
|
519
|
+
createdAt: this.output?.createdAt ?? now,
|
|
681
520
|
updatedAt: now,
|
|
682
521
|
eventSources: props.eventSources,
|
|
683
|
-
url:
|
|
522
|
+
url: subdomain?.url,
|
|
684
523
|
dev: props.dev,
|
|
685
524
|
// Include assets configuration in the output
|
|
686
525
|
assets: props.assets,
|
|
687
526
|
// Include cron triggers in the output
|
|
688
527
|
crons: props.crons,
|
|
689
528
|
// Include the created routes in the output
|
|
690
|
-
routes
|
|
529
|
+
routes,
|
|
691
530
|
// Include the created domains in the output
|
|
692
|
-
domains
|
|
531
|
+
domains,
|
|
693
532
|
// Include the dispatch namespace in the output
|
|
694
533
|
namespace: props.namespace,
|
|
695
534
|
// Include version information in the output
|
|
@@ -698,31 +537,324 @@ export const _Worker = Resource("cloudflare::Worker", {
|
|
|
698
537
|
Env: undefined,
|
|
699
538
|
});
|
|
700
539
|
});
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
540
|
+
const cleanups = [];
|
|
541
|
+
let exiting = false;
|
|
542
|
+
process.on("SIGINT", async () => {
|
|
543
|
+
if (cleanups.length > 0) {
|
|
544
|
+
if (!exiting) {
|
|
545
|
+
exiting = true;
|
|
546
|
+
logger.log(`\n${kleur.gray("Exiting...")}`);
|
|
547
|
+
}
|
|
548
|
+
// TODO: for some reason this runs twice...
|
|
549
|
+
// and this whole thing feels hacky anyway
|
|
550
|
+
await Promise.allSettled(cleanups.map((cleanup) => cleanup()));
|
|
551
|
+
}
|
|
552
|
+
process.exit(0);
|
|
553
|
+
});
|
|
554
|
+
const normalizeDev = (ctx, dev) => {
|
|
555
|
+
if (!ctx.scope.dev || ctx.phase === "delete" || dev === false) {
|
|
556
|
+
return {
|
|
557
|
+
type: "none",
|
|
558
|
+
local: false,
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
const devObj = dev === true ? {} : (dev ?? {});
|
|
562
|
+
if ("command" in devObj) {
|
|
563
|
+
// Commands are always local
|
|
564
|
+
return {
|
|
565
|
+
type: "command",
|
|
566
|
+
...devObj,
|
|
567
|
+
local: true,
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
if (devObj.remote === false || ctx.scope.dev === "prefer-local") {
|
|
571
|
+
return {
|
|
572
|
+
type: "miniflare",
|
|
573
|
+
port: devObj.port,
|
|
574
|
+
local: true,
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
return {
|
|
578
|
+
type: "remote",
|
|
579
|
+
local: false,
|
|
580
|
+
};
|
|
581
|
+
};
|
|
582
|
+
const assertUnique = (inputs, key, message) => {
|
|
583
|
+
const ids = inputs.map((input) => input[key]);
|
|
584
|
+
const duplicates = ids.filter((id, index) => ids.indexOf(id) !== index);
|
|
585
|
+
if (duplicates.length > 0) {
|
|
586
|
+
throw new Error(`Duplicate ${message} found: ${duplicates.join(", ")}`);
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
const normalizeExportBindings = (scriptName, bindings = {}) => {
|
|
590
|
+
return Object.fromEntries(Object.entries(bindings).map(([bindingName, binding]) => [
|
|
591
|
+
bindingName,
|
|
592
|
+
isDurableObjectNamespace(binding) && binding.scriptName === undefined
|
|
593
|
+
? new DurableObjectNamespace(binding.id, {
|
|
594
|
+
...binding,
|
|
595
|
+
// re-export this binding mapping to the host worker (this worker)
|
|
596
|
+
scriptName,
|
|
597
|
+
})
|
|
598
|
+
: isWorkflow(binding) && binding.scriptName === undefined
|
|
599
|
+
? new Workflow(binding.id, {
|
|
600
|
+
...binding,
|
|
601
|
+
// re-export this binding mapping to the host worker (this worker)
|
|
602
|
+
scriptName,
|
|
603
|
+
})
|
|
604
|
+
: binding,
|
|
605
|
+
]));
|
|
606
|
+
};
|
|
607
|
+
const normalizeApiOptions = (api) => ({
|
|
608
|
+
accountId: api.accountId,
|
|
609
|
+
apiKey: api.apiKey,
|
|
610
|
+
apiToken: api.apiToken,
|
|
611
|
+
email: api.email,
|
|
612
|
+
baseUrl: api.baseUrl,
|
|
613
|
+
});
|
|
614
|
+
async function provisionContainers(api, props) {
|
|
615
|
+
if (!props.containers?.length) {
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
return await Promise.all(props.containers.map((container) => {
|
|
619
|
+
const namespaceId = props.bindings.find((binding) => binding.type === "durable_object_namespace" &&
|
|
620
|
+
binding.class_name === container.className)?.namespace_id;
|
|
621
|
+
if (!namespaceId) {
|
|
622
|
+
throw new Error(`Namespace ID not found for container ${container.id}`);
|
|
623
|
+
}
|
|
624
|
+
return ContainerApplication(container.id, {
|
|
625
|
+
image: container.image,
|
|
626
|
+
name: container.id,
|
|
627
|
+
instanceType: container.instanceType,
|
|
628
|
+
observability: container.observability,
|
|
629
|
+
durableObjects: {
|
|
630
|
+
namespaceId,
|
|
631
|
+
},
|
|
632
|
+
schedulingPolicy: container.schedulingPolicy,
|
|
633
|
+
adopt: container.adopt,
|
|
634
|
+
...normalizeApiOptions(api),
|
|
635
|
+
});
|
|
636
|
+
}));
|
|
637
|
+
}
|
|
638
|
+
async function provisionEventSources(api, props) {
|
|
639
|
+
if (!props.eventSources?.length) {
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
return await Promise.all(props.eventSources.map((eventSource) => {
|
|
643
|
+
if (isQueue(eventSource)) {
|
|
644
|
+
return QueueConsumer(`${eventSource.id}-consumer`, {
|
|
645
|
+
queue: eventSource,
|
|
646
|
+
scriptName: props.scriptName,
|
|
647
|
+
settings: eventSource.dlq
|
|
648
|
+
? { deadLetterQueue: eventSource.dlq }
|
|
649
|
+
: undefined,
|
|
650
|
+
...normalizeApiOptions(api),
|
|
716
651
|
});
|
|
717
652
|
}
|
|
718
|
-
|
|
719
|
-
|
|
653
|
+
if (isQueueEventSource(eventSource)) {
|
|
654
|
+
return QueueConsumer(`${eventSource.queue.id}-consumer`, {
|
|
655
|
+
queue: eventSource.queue,
|
|
656
|
+
scriptName: props.scriptName,
|
|
657
|
+
settings: eventSource.settings,
|
|
658
|
+
...normalizeApiOptions(api),
|
|
659
|
+
});
|
|
720
660
|
}
|
|
661
|
+
throw new Error(`Unsupported event source: ${eventSource}`);
|
|
662
|
+
}));
|
|
663
|
+
}
|
|
664
|
+
async function provisionDomains(api, props) {
|
|
665
|
+
if (!props.domains?.length) {
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
const domains = props.domains.map((domain) => {
|
|
669
|
+
if (typeof domain === "string") {
|
|
670
|
+
return {
|
|
671
|
+
name: domain,
|
|
672
|
+
zoneId: undefined,
|
|
673
|
+
adopt: props.adopt,
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
return {
|
|
677
|
+
name: domain.domainName,
|
|
678
|
+
zoneId: domain.zoneId,
|
|
679
|
+
adopt: domain.adopt ?? props.adopt,
|
|
680
|
+
};
|
|
681
|
+
});
|
|
682
|
+
assertUnique(domains, "name", "Custom Domain");
|
|
683
|
+
return await Promise.all(domains.map(async (domain) => {
|
|
684
|
+
return await CustomDomain(domain.name, {
|
|
685
|
+
workerName: props.scriptName,
|
|
686
|
+
name: domain.name,
|
|
687
|
+
zoneId: domain.zoneId,
|
|
688
|
+
adopt: domain.adopt,
|
|
689
|
+
...normalizeApiOptions(api),
|
|
690
|
+
});
|
|
691
|
+
}));
|
|
692
|
+
}
|
|
693
|
+
async function provisionRoutes(api, props) {
|
|
694
|
+
if (!props.routes?.length) {
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
const routes = props.routes.map((route) => {
|
|
698
|
+
if (typeof route === "string") {
|
|
699
|
+
return {
|
|
700
|
+
pattern: route,
|
|
701
|
+
adopt: props.adopt,
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
return {
|
|
705
|
+
pattern: route.pattern,
|
|
706
|
+
zoneId: route.zoneId,
|
|
707
|
+
adopt: route.adopt ?? props.adopt,
|
|
708
|
+
};
|
|
709
|
+
});
|
|
710
|
+
assertUnique(routes, "pattern", "Route");
|
|
711
|
+
return await Promise.all(routes.map(async (route) => {
|
|
712
|
+
return await Route(route.pattern, {
|
|
713
|
+
pattern: route.pattern,
|
|
714
|
+
script: props.scriptName,
|
|
715
|
+
zoneId: route.zoneId,
|
|
716
|
+
adopt: route.adopt,
|
|
717
|
+
...normalizeApiOptions(api),
|
|
718
|
+
});
|
|
719
|
+
}));
|
|
720
|
+
}
|
|
721
|
+
async function provisionSubdomain(api, props) {
|
|
722
|
+
if (props.enable) {
|
|
723
|
+
return await WorkerSubdomain("url", {
|
|
724
|
+
scriptName: props.scriptName,
|
|
725
|
+
previewVersionId: props.previewVersionId,
|
|
726
|
+
retain: props.retain,
|
|
727
|
+
...normalizeApiOptions(api),
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
if (props.forceDelete) {
|
|
731
|
+
await disableWorkerSubdomain(api, props.scriptName);
|
|
721
732
|
}
|
|
722
|
-
// Return minimal output for deleted state
|
|
723
|
-
return;
|
|
724
733
|
}
|
|
725
|
-
function
|
|
734
|
+
async function createMiniflare(props) {
|
|
735
|
+
const sharedOptions = {
|
|
736
|
+
name: props.workerName,
|
|
737
|
+
compatibilityDate: props.compatibilityDate,
|
|
738
|
+
compatibilityFlags: props.compatibilityFlags,
|
|
739
|
+
bindings: props.bindings,
|
|
740
|
+
port: props.port,
|
|
741
|
+
};
|
|
742
|
+
const startPromise = new DeferredPromise();
|
|
743
|
+
const controller = new AbortController();
|
|
744
|
+
cleanups.push(() => controller.abort());
|
|
745
|
+
(await props.bundle.watch(controller.signal))
|
|
746
|
+
.pipeThrough(new TransformStream({
|
|
747
|
+
async transform(chunk, controller) {
|
|
748
|
+
switch (chunk.type) {
|
|
749
|
+
case "start": {
|
|
750
|
+
controller.enqueue({ type: "build-start" });
|
|
751
|
+
break;
|
|
752
|
+
}
|
|
753
|
+
case "end": {
|
|
754
|
+
controller.enqueue({ type: "build-end" });
|
|
755
|
+
try {
|
|
756
|
+
const server = await miniflareServer.push({
|
|
757
|
+
...sharedOptions,
|
|
758
|
+
bundle: chunk.result,
|
|
759
|
+
});
|
|
760
|
+
controller.enqueue({
|
|
761
|
+
type: "miniflare-ready",
|
|
762
|
+
url: server.url,
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
catch (error) {
|
|
766
|
+
controller.enqueue({
|
|
767
|
+
type: "miniflare-error",
|
|
768
|
+
error: error,
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
break;
|
|
772
|
+
}
|
|
773
|
+
case "error": {
|
|
774
|
+
controller.enqueue({
|
|
775
|
+
type: "build-error",
|
|
776
|
+
errors: chunk.errors,
|
|
777
|
+
});
|
|
778
|
+
break;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
},
|
|
782
|
+
}))
|
|
783
|
+
.pipeTo(new WritableStream({
|
|
784
|
+
write: async (chunk) => {
|
|
785
|
+
switch (chunk.type) {
|
|
786
|
+
case "build-start": {
|
|
787
|
+
logger.task("", {
|
|
788
|
+
message: "start",
|
|
789
|
+
status: "pending",
|
|
790
|
+
resource: props.id,
|
|
791
|
+
prefix: "build",
|
|
792
|
+
prefixColor: "cyanBright",
|
|
793
|
+
});
|
|
794
|
+
break;
|
|
795
|
+
}
|
|
796
|
+
case "build-end": {
|
|
797
|
+
logger.task("", {
|
|
798
|
+
message: startPromise.status === "pending" ? "load" : "reload",
|
|
799
|
+
status: "success",
|
|
800
|
+
resource: props.id,
|
|
801
|
+
prefix: "build",
|
|
802
|
+
prefixColor: "greenBright",
|
|
803
|
+
});
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
case "build-error": {
|
|
807
|
+
logger.task("", {
|
|
808
|
+
message: "error",
|
|
809
|
+
status: "failure",
|
|
810
|
+
resource: props.id,
|
|
811
|
+
prefix: "build",
|
|
812
|
+
prefixColor: "redBright",
|
|
813
|
+
});
|
|
814
|
+
if (startPromise.status === "pending") {
|
|
815
|
+
controller.abort();
|
|
816
|
+
startPromise.reject(chunk.errors);
|
|
817
|
+
}
|
|
818
|
+
else {
|
|
819
|
+
logger.error(chunk.errors);
|
|
820
|
+
}
|
|
821
|
+
break;
|
|
822
|
+
}
|
|
823
|
+
case "miniflare-ready": {
|
|
824
|
+
logger.task("", {
|
|
825
|
+
message: `ready at ${chunk.url}`,
|
|
826
|
+
status: "success",
|
|
827
|
+
resource: props.id,
|
|
828
|
+
prefix: "miniflare",
|
|
829
|
+
prefixColor: "greenBright",
|
|
830
|
+
});
|
|
831
|
+
if (startPromise.status === "pending") {
|
|
832
|
+
startPromise.resolve(chunk.url);
|
|
833
|
+
}
|
|
834
|
+
break;
|
|
835
|
+
}
|
|
836
|
+
case "miniflare-error": {
|
|
837
|
+
logger.task("", {
|
|
838
|
+
message: "error",
|
|
839
|
+
status: "failure",
|
|
840
|
+
resource: props.id,
|
|
841
|
+
prefix: "miniflare",
|
|
842
|
+
prefixColor: "redBright",
|
|
843
|
+
});
|
|
844
|
+
if (startPromise.status === "pending") {
|
|
845
|
+
startPromise.reject(chunk.error);
|
|
846
|
+
}
|
|
847
|
+
else {
|
|
848
|
+
logger.error(chunk.error);
|
|
849
|
+
}
|
|
850
|
+
break;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
},
|
|
854
|
+
}));
|
|
855
|
+
return await startPromise.value;
|
|
856
|
+
}
|
|
857
|
+
function createDevCommand(props) {
|
|
726
858
|
const persistFile = path.join(process.cwd(), ".alchemy", `${props.id}.pid`);
|
|
727
859
|
if (existsSync(persistFile)) {
|
|
728
860
|
const pid = Number.parseInt(readFileSync(persistFile, "utf8"));
|
|
@@ -749,104 +881,92 @@ function upsertDevCommand(props) {
|
|
|
749
881
|
},
|
|
750
882
|
stdio: ["inherit", "inherit", "inherit"],
|
|
751
883
|
});
|
|
752
|
-
|
|
884
|
+
cleanups.push(() => {
|
|
753
885
|
try {
|
|
754
886
|
unlinkSync(persistFile);
|
|
755
887
|
}
|
|
756
888
|
catch {
|
|
757
889
|
// ignore
|
|
758
890
|
}
|
|
759
|
-
proc.kill(
|
|
760
|
-
process.exit(0);
|
|
891
|
+
proc.kill();
|
|
761
892
|
});
|
|
762
893
|
if (proc.pid) {
|
|
763
894
|
mkdirSync(path.dirname(persistFile), { recursive: true });
|
|
764
895
|
writeFileSync(persistFile, proc.pid.toString());
|
|
765
896
|
}
|
|
766
897
|
}
|
|
898
|
+
async function prepareWorkerUpload(api, props) {
|
|
899
|
+
const scriptMetadata = await prepareWorkerMetadata(api, props);
|
|
900
|
+
if (props.format === "cjs") {
|
|
901
|
+
scriptMetadata.body_part = props.scriptBundle.entrypoint;
|
|
902
|
+
}
|
|
903
|
+
else {
|
|
904
|
+
scriptMetadata.main_module = props.scriptBundle.entrypoint;
|
|
905
|
+
}
|
|
906
|
+
const body = new FormData();
|
|
907
|
+
for await (const file of props.scriptBundle.files) {
|
|
908
|
+
body.append(file.name, file);
|
|
909
|
+
}
|
|
910
|
+
// Prepare metadata - add version annotations if this is a version
|
|
911
|
+
const finalMetadata = props.version
|
|
912
|
+
? {
|
|
913
|
+
...scriptMetadata,
|
|
914
|
+
// Exclude migrations for worker versions - they're not allowed
|
|
915
|
+
migrations: undefined,
|
|
916
|
+
annotations: {
|
|
917
|
+
"workers/tag": props.version,
|
|
918
|
+
"workers/message": `Version ${props.version}`,
|
|
919
|
+
},
|
|
920
|
+
}
|
|
921
|
+
: {
|
|
922
|
+
...scriptMetadata,
|
|
923
|
+
migrations: scriptMetadata.migrations
|
|
924
|
+
? {
|
|
925
|
+
...scriptMetadata.migrations,
|
|
926
|
+
old_tag: props.migrationTag,
|
|
927
|
+
new_tag: bumpMigrationTagVersion(props.migrationTag),
|
|
928
|
+
}
|
|
929
|
+
: undefined,
|
|
930
|
+
};
|
|
931
|
+
body.append("metadata", new Blob([JSON.stringify(finalMetadata)], {
|
|
932
|
+
type: "application/json",
|
|
933
|
+
}));
|
|
934
|
+
let endpoint;
|
|
935
|
+
let method;
|
|
936
|
+
if (props.version) {
|
|
937
|
+
if (props.dispatchNamespace) {
|
|
938
|
+
throw new Error("Worker Preview Versions are not supported in Workers for Platforms");
|
|
939
|
+
}
|
|
940
|
+
// Upload worker version using the versions API
|
|
941
|
+
endpoint = `/accounts/${api.accountId}/workers/scripts/${props.workerName}/versions`;
|
|
942
|
+
method = "POST";
|
|
943
|
+
}
|
|
944
|
+
else {
|
|
945
|
+
// Upload worker script with bindings
|
|
946
|
+
endpoint = props.dispatchNamespace
|
|
947
|
+
? `/accounts/${api.accountId}/workers/dispatch/namespaces/${props.dispatchNamespace}/scripts/${props.workerName}`
|
|
948
|
+
: `/accounts/${api.accountId}/workers/scripts/${props.workerName}`;
|
|
949
|
+
method = "PUT";
|
|
950
|
+
}
|
|
951
|
+
return {
|
|
952
|
+
body,
|
|
953
|
+
endpoint,
|
|
954
|
+
method,
|
|
955
|
+
};
|
|
956
|
+
}
|
|
767
957
|
export async function putWorker(api, props) {
|
|
768
958
|
const {
|
|
769
959
|
//
|
|
770
|
-
|
|
771
|
-
const scriptMetadata = await prepareWorkerMetadata(api, props);
|
|
960
|
+
workerName, version, } = props;
|
|
772
961
|
return withExponentialBackoff(async () => {
|
|
773
|
-
const
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
? "application/javascript+module"
|
|
782
|
-
: contentType,
|
|
783
|
-
}), fileName);
|
|
784
|
-
}
|
|
785
|
-
if (typeof scriptBundle === "string") {
|
|
786
|
-
addFile(scriptName, scriptBundle);
|
|
787
|
-
}
|
|
788
|
-
else {
|
|
789
|
-
for (const [fileName, content] of Object.entries(scriptBundle)) {
|
|
790
|
-
addFile(fileName, content);
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
// Prepare metadata - add version annotations if this is a version
|
|
794
|
-
const finalMetadata = version
|
|
795
|
-
? {
|
|
796
|
-
...scriptMetadata,
|
|
797
|
-
// Exclude migrations for worker versions - they're not allowed
|
|
798
|
-
migrations: undefined,
|
|
799
|
-
annotations: {
|
|
800
|
-
"workers/tag": version,
|
|
801
|
-
"workers/message": `Version ${version}`,
|
|
802
|
-
},
|
|
803
|
-
}
|
|
804
|
-
: {
|
|
805
|
-
...scriptMetadata,
|
|
806
|
-
migrations: scriptMetadata.migrations
|
|
807
|
-
? {
|
|
808
|
-
...scriptMetadata.migrations,
|
|
809
|
-
old_tag: migrationTag,
|
|
810
|
-
new_tag: bumpMigrationTagVersion(migrationTag),
|
|
811
|
-
}
|
|
812
|
-
: undefined,
|
|
813
|
-
};
|
|
814
|
-
if (process.env.DEBUG) {
|
|
815
|
-
console.log(`metadata(${scriptName}):`, finalMetadata);
|
|
816
|
-
}
|
|
817
|
-
// Add metadata as JSON
|
|
818
|
-
formData.append("metadata", new Blob([JSON.stringify(finalMetadata)], {
|
|
819
|
-
type: "application/json",
|
|
820
|
-
}));
|
|
821
|
-
// Determine endpoint and HTTP method
|
|
822
|
-
let endpoint;
|
|
823
|
-
let method;
|
|
824
|
-
if (version) {
|
|
825
|
-
if (dispatchNamespace) {
|
|
826
|
-
throw new Error("Worker Preview Versions are not supported in Workers for Platforms");
|
|
827
|
-
}
|
|
828
|
-
// Upload worker version using the versions API
|
|
829
|
-
endpoint = `/accounts/${api.accountId}/workers/scripts/${workerName}/versions`;
|
|
830
|
-
method = "POST";
|
|
831
|
-
}
|
|
832
|
-
else {
|
|
833
|
-
// Upload worker script with bindings
|
|
834
|
-
endpoint = dispatchNamespace
|
|
835
|
-
? `/accounts/${api.accountId}/workers/dispatch/namespaces/${dispatchNamespace}/scripts/${workerName}`
|
|
836
|
-
: `/accounts/${api.accountId}/workers/scripts/${workerName}`;
|
|
837
|
-
method = "PUT";
|
|
838
|
-
}
|
|
839
|
-
const uploadResponse = method === "PUT"
|
|
840
|
-
? await api.put(endpoint, formData, {
|
|
841
|
-
headers: {
|
|
842
|
-
"Content-Type": "multipart/form-data",
|
|
843
|
-
},
|
|
844
|
-
})
|
|
845
|
-
: await api.post(endpoint, formData, {
|
|
846
|
-
headers: {
|
|
847
|
-
"Content-Type": "multipart/form-data",
|
|
848
|
-
},
|
|
849
|
-
});
|
|
962
|
+
const { body, endpoint, method } = await prepareWorkerUpload(api, props);
|
|
963
|
+
const uploadResponse = await api.fetch(endpoint, {
|
|
964
|
+
method,
|
|
965
|
+
headers: {
|
|
966
|
+
"Content-Type": "multipart/form-data",
|
|
967
|
+
},
|
|
968
|
+
body,
|
|
969
|
+
});
|
|
850
970
|
// Check if the upload was successful
|
|
851
971
|
if (!uploadResponse.ok) {
|
|
852
972
|
try {
|
|
@@ -880,33 +1000,7 @@ export async function putWorker(api, props) {
|
|
|
880
1000
|
}
|
|
881
1001
|
}
|
|
882
1002
|
const responseData = (await uploadResponse.json());
|
|
883
|
-
|
|
884
|
-
// Handle version response
|
|
885
|
-
if (props.version) {
|
|
886
|
-
// Get the account's workers.dev subdomain to construct preview URL
|
|
887
|
-
let previewUrl;
|
|
888
|
-
if (result.metadata?.has_preview) {
|
|
889
|
-
// Need to get the subdomain
|
|
890
|
-
const subdomainResponse = await api.get(`/accounts/${api.accountId}/workers/subdomain`);
|
|
891
|
-
if (subdomainResponse.ok) {
|
|
892
|
-
const subdomainData = await subdomainResponse.json();
|
|
893
|
-
const subdomain = subdomainData.result?.subdomain;
|
|
894
|
-
if (subdomain) {
|
|
895
|
-
// Preview URL format: <FIRST_8_CHARS_OF_VERSION_ID>-<WORKER_NAME>.<SUBDOMAIN>.workers.dev
|
|
896
|
-
const versionPrefix = result.id.substring(0, 8);
|
|
897
|
-
previewUrl = `https://${versionPrefix}-${workerName}.${subdomain}.workers.dev`;
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
return {
|
|
902
|
-
versionId: result.id,
|
|
903
|
-
previewUrl,
|
|
904
|
-
deploymentId: result.deployment_id,
|
|
905
|
-
};
|
|
906
|
-
}
|
|
907
|
-
return {
|
|
908
|
-
deploymentId: result.deployment_id,
|
|
909
|
-
};
|
|
1003
|
+
return responseData.result;
|
|
910
1004
|
}, (err) => err.status === 404 ||
|
|
911
1005
|
err.status === 500 ||
|
|
912
1006
|
err.status === 503 ||
|
|
@@ -915,79 +1009,57 @@ export async function putWorker(api, props) {
|
|
|
915
1009
|
err.status === 400 &&
|
|
916
1010
|
err.message.match(/binding.*failed to generate/)), 10, 100);
|
|
917
1011
|
}
|
|
918
|
-
|
|
919
|
-
const
|
|
920
|
-
return
|
|
1012
|
+
async function workerExists(api, scriptName) {
|
|
1013
|
+
const res = await api.get(`/accounts/${api.accountId}/workers/scripts/${scriptName}`);
|
|
1014
|
+
return res.status === 200;
|
|
921
1015
|
}
|
|
922
|
-
|
|
923
|
-
const response = await api.get(`/accounts/${api.accountId}/workers/scripts/${
|
|
1016
|
+
async function assertWorkerDoesNotExist(api, scriptName) {
|
|
1017
|
+
const response = await api.get(`/accounts/${api.accountId}/workers/scripts/${scriptName}`);
|
|
924
1018
|
if (response.status === 404) {
|
|
925
1019
|
return true;
|
|
926
1020
|
}
|
|
927
1021
|
if (response.status === 200) {
|
|
928
|
-
const metadata = await
|
|
1022
|
+
const metadata = await getScriptMetadata(api, scriptName);
|
|
929
1023
|
if (!metadata) {
|
|
930
1024
|
throw new Error(`Worker exists but failed to fetch metadata: ${response.status} ${response.statusText}`);
|
|
931
1025
|
}
|
|
932
|
-
throw new Error(`Worker with name '${
|
|
1026
|
+
throw new Error(`Worker with name '${scriptName}' already exists. Please use a unique name.`);
|
|
933
1027
|
}
|
|
934
1028
|
throw new Error(`Error checking if worker exists: ${response.status} ${response.statusText} ${await response.text()}`);
|
|
935
1029
|
}
|
|
936
|
-
|
|
937
|
-
const
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
// Enable the workers.dev subdomain for this worker
|
|
941
|
-
await api.post(`/accounts/${api.accountId}/workers/scripts/${workerName}/subdomain`, { enabled: true, previews_enabled: true }, {
|
|
942
|
-
headers: { "Content-Type": "application/json" },
|
|
943
|
-
});
|
|
944
|
-
// Get the account's workers.dev subdomain
|
|
945
|
-
const subdomain = await getAccountSubdomain(api);
|
|
946
|
-
if (subdomain) {
|
|
947
|
-
workerUrl = `https://${workerName}.${subdomain}.workers.dev`;
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
else if (url === false &&
|
|
951
|
-
(ctx.output?.url || (ctx.phase === "create" && props.adopt))) {
|
|
952
|
-
// Explicitly disable URL if it was previously enabled
|
|
953
|
-
const response = await api.post(`/accounts/${api.accountId}/workers/scripts/${workerName}/subdomain`, JSON.stringify({ enabled: false }), {
|
|
954
|
-
headers: { "Content-Type": "application/json" },
|
|
955
|
-
});
|
|
956
|
-
if (!response.ok) {
|
|
957
|
-
throw new Error(`Failed to disable worker URL: ${response.status} ${response.statusText}`);
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
return workerUrl;
|
|
961
|
-
}
|
|
962
|
-
export async function getWorkerSubdomainConfig(api, workerName) {
|
|
963
|
-
// Query Cloudflare API to verify subdomain is disabled
|
|
964
|
-
const subdomainResponse = await api.get(`/accounts/${api.accountId}/workers/scripts/${workerName}/subdomain`);
|
|
965
|
-
if (subdomainResponse.status === 404) {
|
|
966
|
-
return undefined;
|
|
967
|
-
}
|
|
968
|
-
const subdomainData = await subdomainResponse.json();
|
|
969
|
-
return subdomainData.result;
|
|
970
|
-
}
|
|
971
|
-
export async function getWorkerScriptMetadata(api, workerName) {
|
|
972
|
-
const response = await api.get(`/accounts/${api.accountId}/workers/services/${workerName}`);
|
|
973
|
-
if (response.status === 404) {
|
|
974
|
-
return undefined;
|
|
1030
|
+
async function getScriptMetadata(api, scriptName) {
|
|
1031
|
+
const res = await api.get(`/accounts/${api.accountId}/workers/services/${scriptName}`);
|
|
1032
|
+
if (res.status === 404) {
|
|
1033
|
+
return;
|
|
975
1034
|
}
|
|
976
|
-
if (!
|
|
977
|
-
throw new Error(`Error getting worker script metadata: ${
|
|
1035
|
+
if (!res.ok) {
|
|
1036
|
+
throw new Error(`Error getting worker script metadata: ${res.status} ${res.statusText}`);
|
|
978
1037
|
}
|
|
979
|
-
|
|
1038
|
+
const json = (await res.json());
|
|
1039
|
+
return json.result;
|
|
980
1040
|
}
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
* @param ctx Worker context containing eventSources
|
|
984
|
-
* @param api CloudflareApi instance
|
|
985
|
-
* @param workerName Name of the worker script
|
|
986
|
-
*/
|
|
987
|
-
async function deleteQueueConsumers(api, workerName) {
|
|
988
|
-
const consumers = await listQueueConsumersForWorker(api, workerName);
|
|
1041
|
+
async function deleteQueueConsumers(api, scriptName) {
|
|
1042
|
+
const consumers = await listQueueConsumersForWorker(api, scriptName);
|
|
989
1043
|
await Promise.all(consumers.map(async (consumer) => {
|
|
990
1044
|
await deleteQueueConsumer(api, consumer.queueId, consumer.consumerId);
|
|
991
1045
|
}));
|
|
992
1046
|
}
|
|
1047
|
+
export async function deleteWorker(api, props) {
|
|
1048
|
+
await withExponentialBackoff(async () => {
|
|
1049
|
+
const deleteResponse = await api.delete(props.dispatchNamespace
|
|
1050
|
+
? `/accounts/${api.accountId}/workers/dispatch/namespaces/${props.dispatchNamespace}/scripts/${props.scriptName}?force=true`
|
|
1051
|
+
: `/accounts/${api.accountId}/workers/scripts/${props.scriptName}?force=true`);
|
|
1052
|
+
if (!deleteResponse.ok && deleteResponse.status !== 404) {
|
|
1053
|
+
await handleApiError(deleteResponse, "delete", "worker", props.scriptName);
|
|
1054
|
+
}
|
|
1055
|
+
}, (err) => (err.status === 400 &&
|
|
1056
|
+
err.message.includes("is still referenced by service bindings in Workers")) ||
|
|
1057
|
+
err.status === 500 ||
|
|
1058
|
+
err.status === 503, 10, 100);
|
|
1059
|
+
}
|
|
1060
|
+
async function getVersionMetadata(api, scriptName, deploymentId) {
|
|
1061
|
+
const response = await api.get(`/accounts/${api.accountId}/workers/scripts/${scriptName}/versions/${deploymentId}`);
|
|
1062
|
+
const result = (await response.json());
|
|
1063
|
+
return result.result;
|
|
1064
|
+
}
|
|
993
1065
|
//# sourceMappingURL=worker.js.map
|