alchemy 0.44.3 → 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/bin/alchemy.mjs +0 -13
- package/bin/commands/create.ts +1 -10
- package/bin/services/vibe-rules.ts +0 -14
- 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 -4
- 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 -4
- 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 -28
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +641 -554
- 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 -3
- 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 -4
- package/src/cloudflare/worker-subdomain.ts +123 -0
- package/src/cloudflare/worker.ts +863 -734
- 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/src/cloudflare/worker.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type esbuild from "esbuild";
|
|
2
|
+
import kleur from "kleur";
|
|
1
3
|
import { spawn } from "node:child_process";
|
|
2
4
|
import {
|
|
3
5
|
existsSync,
|
|
@@ -6,7 +8,8 @@ import {
|
|
|
6
8
|
unlinkSync,
|
|
7
9
|
writeFileSync,
|
|
8
10
|
} from "node:fs";
|
|
9
|
-
import
|
|
11
|
+
import { isDeepStrictEqual } from "node:util";
|
|
12
|
+
import path from "pathe";
|
|
10
13
|
import { BUILD_DATE } from "../build-date.ts";
|
|
11
14
|
import type { Context } from "../context.ts";
|
|
12
15
|
import type { BundleProps } from "../esbuild/bundle.ts";
|
|
@@ -18,7 +21,6 @@ import { Scope } from "../scope.ts";
|
|
|
18
21
|
import { Secret, secret } from "../secret.ts";
|
|
19
22
|
import { serializeScope } from "../serde.ts";
|
|
20
23
|
import type { type } from "../type.ts";
|
|
21
|
-
import { getContentType } from "../util/content-type.ts";
|
|
22
24
|
import { DeferredPromise } from "../util/deferred-promise.ts";
|
|
23
25
|
import { logger } from "../util/logger.ts";
|
|
24
26
|
import { withExponentialBackoff } from "../util/retry.ts";
|
|
@@ -39,11 +41,13 @@ import {
|
|
|
39
41
|
} from "./bindings.ts";
|
|
40
42
|
import type { Bound } from "./bound.ts";
|
|
41
43
|
import { isBucket } from "./bucket.ts";
|
|
42
|
-
import { createWorkerDevContext } from "./bundle/bundle-worker-dev.ts";
|
|
43
44
|
import {
|
|
44
|
-
type
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
type WorkerBundle,
|
|
46
|
+
type WorkerBundleChunk,
|
|
47
|
+
type WorkerBundleProvider,
|
|
48
|
+
normalizeWorkerBundle,
|
|
49
|
+
} from "./bundle/index.ts";
|
|
50
|
+
import { wrap } from "./bundle/normalize.ts";
|
|
47
51
|
import { type Container, ContainerApplication } from "./container.ts";
|
|
48
52
|
import { CustomDomain } from "./custom-domain.ts";
|
|
49
53
|
import { isD1Database } from "./d1-database.ts";
|
|
@@ -58,6 +62,8 @@ import {
|
|
|
58
62
|
isQueueEventSource,
|
|
59
63
|
} from "./event-source.ts";
|
|
60
64
|
import { isKVNamespace } from "./kv-namespace.ts";
|
|
65
|
+
import type { MiniflareWorkerOptions } from "./miniflare/miniflare-worker-options.ts";
|
|
66
|
+
import { miniflareServer } from "./miniflare/miniflare.ts";
|
|
61
67
|
import { isPipeline } from "./pipeline.ts";
|
|
62
68
|
import {
|
|
63
69
|
QueueConsumer,
|
|
@@ -67,16 +73,15 @@ import {
|
|
|
67
73
|
import { type QueueResource, isQueue } from "./queue.ts";
|
|
68
74
|
import { Route } from "./route.ts";
|
|
69
75
|
import { isVectorizeIndex } from "./vectorize-index.ts";
|
|
70
|
-
import {
|
|
76
|
+
import { uploadAssets } from "./worker-assets.ts";
|
|
71
77
|
import {
|
|
72
78
|
type WorkerScriptMetadata,
|
|
73
79
|
bumpMigrationTagVersion,
|
|
74
80
|
prepareWorkerMetadata,
|
|
75
81
|
} from "./worker-metadata.ts";
|
|
76
82
|
import { WorkerStub, isWorkerStub } from "./worker-stub.ts";
|
|
77
|
-
import
|
|
78
|
-
import {
|
|
79
|
-
import { getAccountSubdomain } from "./worker/subdomain.ts";
|
|
83
|
+
import { WorkerSubdomain, disableWorkerSubdomain } from "./worker-subdomain.ts";
|
|
84
|
+
import { createTail } from "./worker/tail.ts";
|
|
80
85
|
import { Workflow, isWorkflow, upsertWorkflow } from "./workflow.ts";
|
|
81
86
|
|
|
82
87
|
/**
|
|
@@ -246,7 +251,7 @@ export interface BaseWorkerProps<
|
|
|
246
251
|
* ],
|
|
247
252
|
* });
|
|
248
253
|
*/
|
|
249
|
-
routes?:
|
|
254
|
+
routes?: (
|
|
250
255
|
| string
|
|
251
256
|
| {
|
|
252
257
|
/**
|
|
@@ -264,7 +269,7 @@ export interface BaseWorkerProps<
|
|
|
264
269
|
*/
|
|
265
270
|
adopt?: boolean;
|
|
266
271
|
}
|
|
267
|
-
|
|
272
|
+
)[];
|
|
268
273
|
|
|
269
274
|
/**
|
|
270
275
|
* Custom domains to bind to the worker
|
|
@@ -335,9 +340,7 @@ export interface BaseWorkerProps<
|
|
|
335
340
|
*/
|
|
336
341
|
port?: number;
|
|
337
342
|
/**
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
* When this is enabled, hot reloading will not work.
|
|
343
|
+
* Whether to run the worker remotely instead of locally.
|
|
341
344
|
*
|
|
342
345
|
* @default false
|
|
343
346
|
*/
|
|
@@ -381,9 +384,9 @@ export interface EntrypointWorkerProps<
|
|
|
381
384
|
/**
|
|
382
385
|
* Whether to upload source maps for the worker script.
|
|
383
386
|
*
|
|
384
|
-
* @default
|
|
387
|
+
* @default true
|
|
385
388
|
*/
|
|
386
|
-
|
|
389
|
+
sourceMap?: boolean;
|
|
387
390
|
|
|
388
391
|
/**
|
|
389
392
|
* Rules for adding additional files to the bundle.
|
|
@@ -972,193 +975,72 @@ export const _Worker = Resource(
|
|
|
972
975
|
id: string,
|
|
973
976
|
props: WorkerProps<B>,
|
|
974
977
|
): Promise<Worker<B>> {
|
|
975
|
-
if (props.noBundle && !props.entrypoint) {
|
|
976
|
-
throw new Error("entrypoint must be provided when noBundle is true");
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
// Use the provided name
|
|
980
|
-
const workerName = props.name ?? id;
|
|
981
|
-
|
|
982
978
|
if (props.projectRoot) {
|
|
983
979
|
logger.warn("projectRoot is deprecated, use cwd instead");
|
|
984
980
|
props.cwd = props.projectRoot;
|
|
985
981
|
}
|
|
986
982
|
|
|
987
|
-
const cwd =
|
|
983
|
+
const cwd = path.resolve(props.cwd ?? process.cwd());
|
|
988
984
|
const relativeCwd =
|
|
989
985
|
cwd === process.cwd() ? undefined : path.relative(process.cwd(), cwd);
|
|
990
986
|
|
|
987
|
+
const workerName = props.name ?? id;
|
|
991
988
|
const compatibilityDate =
|
|
992
989
|
props.compatibilityDate ?? DEFAULT_COMPATIBILITY_DATE;
|
|
993
990
|
const compatibilityFlags = props.compatibilityFlags ?? [];
|
|
991
|
+
const dispatchNamespace =
|
|
992
|
+
typeof props.namespace === "string"
|
|
993
|
+
? props.namespace
|
|
994
|
+
: props.namespace?.namespaceName;
|
|
994
995
|
|
|
995
|
-
|
|
996
|
-
// Get current timestamp
|
|
997
|
-
const now = Date.now();
|
|
998
|
-
|
|
999
|
-
if (typeof props.dev === "object" && "command" in props.dev) {
|
|
1000
|
-
upsertDevCommand({
|
|
1001
|
-
id,
|
|
1002
|
-
command: props.dev.command,
|
|
1003
|
-
cwd: props.dev.cwd ?? cwd,
|
|
1004
|
-
env: props.env ?? {},
|
|
1005
|
-
});
|
|
1006
|
-
return this({
|
|
1007
|
-
type: "service",
|
|
1008
|
-
id,
|
|
1009
|
-
entrypoint: props.entrypoint,
|
|
1010
|
-
name: workerName,
|
|
1011
|
-
cwd: relativeCwd,
|
|
1012
|
-
compatibilityDate,
|
|
1013
|
-
compatibilityFlags,
|
|
1014
|
-
format: props.format || "esm", // Include format in the output
|
|
1015
|
-
bindings: props.bindings ?? ({} as B),
|
|
1016
|
-
env: props.env,
|
|
1017
|
-
observability: props.observability,
|
|
1018
|
-
createdAt: now,
|
|
1019
|
-
updatedAt: now,
|
|
1020
|
-
eventSources: props.eventSources,
|
|
1021
|
-
url: props.dev.url,
|
|
1022
|
-
dev: props.dev,
|
|
1023
|
-
// Include assets configuration in the output
|
|
1024
|
-
assets: props.assets,
|
|
1025
|
-
// Include cron triggers in the output
|
|
1026
|
-
crons: props.crons,
|
|
1027
|
-
// phantom property
|
|
1028
|
-
Env: undefined!,
|
|
1029
|
-
} as unknown as Worker<B>);
|
|
1030
|
-
}
|
|
996
|
+
const dev = normalizeDev(this, props.dev);
|
|
1031
997
|
|
|
1032
|
-
|
|
1033
|
-
|
|
998
|
+
const [bundle, error] = wrap(() =>
|
|
999
|
+
normalizeWorkerBundle({
|
|
1000
|
+
entrypoint: props.entrypoint,
|
|
1001
|
+
script: props.script,
|
|
1002
|
+
format: props.format,
|
|
1003
|
+
noBundle: props.noBundle,
|
|
1004
|
+
rules: "rules" in props ? props.rules : undefined,
|
|
1005
|
+
bundle: props.bundle,
|
|
1006
|
+
cwd,
|
|
1034
1007
|
compatibilityDate,
|
|
1035
1008
|
compatibilityFlags,
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
// If entrypoint is provided, set up hot reloading with esbuild context
|
|
1043
|
-
if (props.entrypoint) {
|
|
1044
|
-
const startPromise = new DeferredPromise<string>();
|
|
1009
|
+
outdir:
|
|
1010
|
+
props.bundle?.outdir ??
|
|
1011
|
+
path.join(process.cwd(), ".alchemy", ...this.scope.chain, id),
|
|
1012
|
+
sourceMap: "sourceMap" in props ? props.sourceMap : undefined,
|
|
1013
|
+
}),
|
|
1014
|
+
);
|
|
1045
1015
|
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
cwd,
|
|
1052
|
-
compatibilityDate,
|
|
1053
|
-
compatibilityFlags,
|
|
1054
|
-
},
|
|
1055
|
-
{
|
|
1056
|
-
onBuildStart: () => {
|
|
1057
|
-
logger.task("miniflare-server", {
|
|
1058
|
-
message: `${startPromise.status === "pending" ? "Building" : "Rebuilding"}`,
|
|
1059
|
-
status: "pending",
|
|
1060
|
-
resource: id,
|
|
1061
|
-
prefix: "build",
|
|
1062
|
-
prefixColor: "cyanBright",
|
|
1063
|
-
});
|
|
1064
|
-
},
|
|
1065
|
-
onBuildEnd: async (newScript) => {
|
|
1066
|
-
try {
|
|
1067
|
-
// Hot reload callback - update the miniflare worker
|
|
1068
|
-
const server = await miniflareServer.push({
|
|
1069
|
-
...sharedOptions,
|
|
1070
|
-
script: newScript,
|
|
1071
|
-
});
|
|
1072
|
-
if (startPromise.status === "pending") {
|
|
1073
|
-
logger.task("miniflare-server", {
|
|
1074
|
-
message: `Started Miniflare server at ${server.url}`,
|
|
1075
|
-
status: "success",
|
|
1076
|
-
resource: id,
|
|
1077
|
-
prefix: "ready",
|
|
1078
|
-
prefixColor: "cyanBright",
|
|
1079
|
-
});
|
|
1080
|
-
startPromise.resolve(server.url);
|
|
1081
|
-
} else {
|
|
1082
|
-
logger.task("miniflare-server", {
|
|
1083
|
-
message: `Updated Miniflare server at ${server.url}`,
|
|
1084
|
-
status: "success",
|
|
1085
|
-
resource: id,
|
|
1086
|
-
prefix: "reload",
|
|
1087
|
-
prefixColor: "cyanBright",
|
|
1088
|
-
});
|
|
1089
|
-
}
|
|
1090
|
-
} catch (error) {
|
|
1091
|
-
if (startPromise.status === "pending") {
|
|
1092
|
-
logger.error(error);
|
|
1093
|
-
logger.task("miniflare-server", {
|
|
1094
|
-
message: "Failed to start Miniflare server",
|
|
1095
|
-
status: "failure",
|
|
1096
|
-
resource: id,
|
|
1097
|
-
prefix: "error",
|
|
1098
|
-
prefixColor: "redBright",
|
|
1099
|
-
});
|
|
1100
|
-
startPromise.reject(
|
|
1101
|
-
new Error(
|
|
1102
|
-
`Failed to start Miniflare server for worker "${workerName}"`,
|
|
1103
|
-
{ cause: error },
|
|
1104
|
-
),
|
|
1105
|
-
);
|
|
1106
|
-
} else {
|
|
1107
|
-
logger.task("miniflare-server", {
|
|
1108
|
-
message: "Failed to update Miniflare server",
|
|
1109
|
-
status: "failure",
|
|
1110
|
-
resource: id,
|
|
1111
|
-
prefix: "error",
|
|
1112
|
-
prefixColor: "redBright",
|
|
1113
|
-
});
|
|
1114
|
-
logger.error(error);
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
},
|
|
1118
|
-
onBuildError: (errors) => {
|
|
1119
|
-
if (startPromise.status === "pending") {
|
|
1120
|
-
logger.task("miniflare-server", {
|
|
1121
|
-
message: "Failed to build worker",
|
|
1122
|
-
status: "failure",
|
|
1123
|
-
resource: id,
|
|
1124
|
-
prefix: "error",
|
|
1125
|
-
prefixColor: "redBright",
|
|
1126
|
-
});
|
|
1127
|
-
startPromise.reject(errors);
|
|
1128
|
-
} else {
|
|
1129
|
-
logger.task("miniflare-server", {
|
|
1130
|
-
message: "Failed to rebuild worker",
|
|
1131
|
-
status: "failure",
|
|
1132
|
-
resource: id,
|
|
1133
|
-
prefix: "error",
|
|
1134
|
-
prefixColor: "redBright",
|
|
1135
|
-
});
|
|
1136
|
-
logger.error(errors);
|
|
1137
|
-
}
|
|
1138
|
-
},
|
|
1139
|
-
},
|
|
1140
|
-
);
|
|
1016
|
+
if (dev.local) {
|
|
1017
|
+
let url: string | undefined;
|
|
1018
|
+
if (error) {
|
|
1019
|
+
throw error;
|
|
1020
|
+
}
|
|
1141
1021
|
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1022
|
+
switch (dev.type) {
|
|
1023
|
+
case "command":
|
|
1024
|
+
createDevCommand({
|
|
1025
|
+
id,
|
|
1026
|
+
command: dev.command,
|
|
1027
|
+
cwd: dev.cwd ?? process.cwd(),
|
|
1028
|
+
env: props.env ?? {},
|
|
1029
|
+
});
|
|
1030
|
+
url = dev.url;
|
|
1031
|
+
break;
|
|
1032
|
+
case "miniflare": {
|
|
1033
|
+
url = await createMiniflare({
|
|
1034
|
+
id,
|
|
1035
|
+
workerName,
|
|
1151
1036
|
compatibilityDate,
|
|
1152
1037
|
compatibilityFlags,
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
: scriptContent[props.entrypoint!].toString(),
|
|
1160
|
-
});
|
|
1161
|
-
url = server.url;
|
|
1038
|
+
bindings: props.bindings,
|
|
1039
|
+
bundle,
|
|
1040
|
+
port: dev.port,
|
|
1041
|
+
});
|
|
1042
|
+
break;
|
|
1043
|
+
}
|
|
1162
1044
|
}
|
|
1163
1045
|
|
|
1164
1046
|
return this({
|
|
@@ -1170,11 +1052,11 @@ export const _Worker = Resource(
|
|
|
1170
1052
|
compatibilityDate,
|
|
1171
1053
|
compatibilityFlags,
|
|
1172
1054
|
format: props.format || "esm", // Include format in the output
|
|
1173
|
-
bindings: props.bindings
|
|
1055
|
+
bindings: normalizeExportBindings(workerName, props.bindings),
|
|
1174
1056
|
env: props.env,
|
|
1175
1057
|
observability: props.observability,
|
|
1176
|
-
createdAt: now,
|
|
1177
|
-
updatedAt: now,
|
|
1058
|
+
createdAt: this.output?.createdAt ?? Date.now(),
|
|
1059
|
+
updatedAt: Date.now(),
|
|
1178
1060
|
eventSources: props.eventSources,
|
|
1179
1061
|
url,
|
|
1180
1062
|
dev: props.dev,
|
|
@@ -1187,65 +1069,53 @@ export const _Worker = Resource(
|
|
|
1187
1069
|
} as unknown as Worker<B>);
|
|
1188
1070
|
}
|
|
1189
1071
|
|
|
1190
|
-
// Create Cloudflare API client with automatic account discovery
|
|
1191
1072
|
const api = await createCloudflareApi(props);
|
|
1192
1073
|
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1074
|
+
if (this.phase === "delete") {
|
|
1075
|
+
await bundle?.delete?.();
|
|
1076
|
+
if (!props.version) {
|
|
1077
|
+
await deleteQueueConsumers(api, workerName);
|
|
1078
|
+
await deleteWorker(api, {
|
|
1079
|
+
scriptName: workerName,
|
|
1080
|
+
dispatchNamespace,
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
return this.destroy();
|
|
1084
|
+
} else if (error) {
|
|
1085
|
+
throw error;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
let assetsBinding: Assets | undefined;
|
|
1089
|
+
const workflowsBindings: Workflow[] = [];
|
|
1090
|
+
const containersBindings: Container[] = [];
|
|
1091
|
+
|
|
1092
|
+
for (const binding of Object.values(props.bindings ?? {})) {
|
|
1093
|
+
if (typeof binding === "object") {
|
|
1094
|
+
if (binding.type === "assets") {
|
|
1095
|
+
assetsBinding = binding;
|
|
1096
|
+
} else if (binding.type === "workflow") {
|
|
1097
|
+
workflowsBindings.push(binding);
|
|
1098
|
+
} else if (binding.type === "container") {
|
|
1099
|
+
containersBindings.push(binding);
|
|
1221
1100
|
}
|
|
1222
1101
|
}
|
|
1102
|
+
}
|
|
1223
1103
|
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1104
|
+
const putWorkerWithAssets = async (
|
|
1105
|
+
props: WorkerProps<B>,
|
|
1106
|
+
scriptBundle: WorkerBundle,
|
|
1107
|
+
) => {
|
|
1108
|
+
const assetUploadResult = assetsBinding
|
|
1109
|
+
? await uploadAssets(api, {
|
|
1110
|
+
workerName,
|
|
1111
|
+
assets: assetsBinding,
|
|
1112
|
+
assetConfig: props.assets,
|
|
1113
|
+
namespace: dispatchNamespace,
|
|
1114
|
+
})
|
|
1229
1115
|
: undefined;
|
|
1230
1116
|
|
|
1231
|
-
// Upload any assets and get completion tokens
|
|
1232
|
-
let assetUploadResult: AssetUploadResult | undefined;
|
|
1233
|
-
if (assetsBindings.length > 0) {
|
|
1234
|
-
// We'll use the first asset binding for now
|
|
1235
|
-
// In the future, we might want to support multiple asset bindings
|
|
1236
|
-
const assetBinding = assetsBindings[0];
|
|
1237
|
-
|
|
1238
|
-
// Upload the assets and get the completion token
|
|
1239
|
-
assetUploadResult = await uploadAssets(api, {
|
|
1240
|
-
workerName,
|
|
1241
|
-
assets: assetBinding.assets,
|
|
1242
|
-
assetConfig: props.assets,
|
|
1243
|
-
namespace: dispatchNamespace,
|
|
1244
|
-
});
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
1117
|
// Deploy worker (either as version or live worker)
|
|
1248
|
-
|
|
1118
|
+
return await putWorker(api, {
|
|
1249
1119
|
...props,
|
|
1250
1120
|
workerName,
|
|
1251
1121
|
scriptBundle,
|
|
@@ -1255,162 +1125,15 @@ export const _Worker = Resource(
|
|
|
1255
1125
|
compatibilityFlags,
|
|
1256
1126
|
assetUploadResult,
|
|
1257
1127
|
});
|
|
1258
|
-
versionResult.versionId;
|
|
1259
|
-
|
|
1260
|
-
for (const workflow of workflowsBindings) {
|
|
1261
|
-
if (
|
|
1262
|
-
workflow.scriptName === undefined ||
|
|
1263
|
-
workflow.scriptName === workerName
|
|
1264
|
-
) {
|
|
1265
|
-
await upsertWorkflow(api, {
|
|
1266
|
-
workflowName: workflow.workflowName,
|
|
1267
|
-
className: workflow.className,
|
|
1268
|
-
scriptName: workflow.scriptName ?? workerName,
|
|
1269
|
-
});
|
|
1270
|
-
}
|
|
1271
|
-
}
|
|
1272
|
-
|
|
1273
|
-
for (const container of containersBindings) {
|
|
1274
|
-
async function findNamespaceId() {
|
|
1275
|
-
const response = await api.get(
|
|
1276
|
-
`/accounts/${api.accountId}/workers/scripts/${workerName}/versions/${versionResult.deploymentId}`,
|
|
1277
|
-
);
|
|
1278
|
-
const result = (await response.json()) as {
|
|
1279
|
-
result: {
|
|
1280
|
-
resources: {
|
|
1281
|
-
bindings: WorkerBindingSpec[];
|
|
1282
|
-
};
|
|
1283
|
-
};
|
|
1284
|
-
};
|
|
1285
|
-
const namespaceId = result.result.resources.bindings.find(
|
|
1286
|
-
(binding): binding is WorkerBindingDurableObjectNamespace =>
|
|
1287
|
-
binding.type === "durable_object_namespace" &&
|
|
1288
|
-
binding.class_name === container.className,
|
|
1289
|
-
)?.namespace_id;
|
|
1290
|
-
if (!namespaceId) {
|
|
1291
|
-
throw new Error(
|
|
1292
|
-
`Namespace ID not found for container ${container.id}`,
|
|
1293
|
-
);
|
|
1294
|
-
}
|
|
1295
|
-
return namespaceId;
|
|
1296
|
-
}
|
|
1297
|
-
await ContainerApplication(container.id, {
|
|
1298
|
-
accountId: props.accountId,
|
|
1299
|
-
apiKey: props.apiKey,
|
|
1300
|
-
apiToken: props.apiToken,
|
|
1301
|
-
baseUrl: props.baseUrl,
|
|
1302
|
-
email: props.email,
|
|
1303
|
-
image: container.image,
|
|
1304
|
-
name: container.id,
|
|
1305
|
-
instanceType: container.instanceType,
|
|
1306
|
-
observability: container.observability,
|
|
1307
|
-
durableObjects: {
|
|
1308
|
-
namespaceId: await findNamespaceId(),
|
|
1309
|
-
},
|
|
1310
|
-
schedulingPolicy: container.schedulingPolicy,
|
|
1311
|
-
});
|
|
1312
|
-
}
|
|
1313
|
-
|
|
1314
|
-
await Promise.all(
|
|
1315
|
-
props.eventSources?.map((eventSource) => {
|
|
1316
|
-
if (isQueue(eventSource) || isQueueEventSource(eventSource)) {
|
|
1317
|
-
const queue = isQueue(eventSource)
|
|
1318
|
-
? eventSource
|
|
1319
|
-
: eventSource.queue;
|
|
1320
|
-
return QueueConsumer(`${queue.id}-consumer`, {
|
|
1321
|
-
queue,
|
|
1322
|
-
scriptName: workerName,
|
|
1323
|
-
accountId: api.accountId,
|
|
1324
|
-
adopt: props.adopt,
|
|
1325
|
-
settings: isQueueEventSource(eventSource)
|
|
1326
|
-
? eventSource.settings
|
|
1327
|
-
: queue.dlq
|
|
1328
|
-
? { deadLetterQueue: queue.dlq }
|
|
1329
|
-
: undefined,
|
|
1330
|
-
});
|
|
1331
|
-
}
|
|
1332
|
-
throw new Error(`Unsupported event source type: ${eventSource}`);
|
|
1333
|
-
}) ?? [],
|
|
1334
|
-
);
|
|
1335
|
-
|
|
1336
|
-
// Handle worker URL if requested
|
|
1337
|
-
let workerUrl: string | undefined;
|
|
1338
|
-
if (props.version) {
|
|
1339
|
-
// For versions, use the preview URL if available
|
|
1340
|
-
workerUrl = versionResult?.previewUrl;
|
|
1341
|
-
} else if (!props.namespace) {
|
|
1342
|
-
// namespaces don't support URLs
|
|
1343
|
-
|
|
1344
|
-
// For regular workers, use the normal URL configuration
|
|
1345
|
-
workerUrl = await configureURL(
|
|
1346
|
-
this,
|
|
1347
|
-
api,
|
|
1348
|
-
workerName,
|
|
1349
|
-
props.url ?? true,
|
|
1350
|
-
);
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
|
-
// Get current timestamp
|
|
1354
|
-
const now = Date.now();
|
|
1355
|
-
|
|
1356
|
-
// Update cron triggers
|
|
1357
|
-
if (props.crons) {
|
|
1358
|
-
const res = await api.put(
|
|
1359
|
-
`/accounts/${api.accountId}/workers/scripts/${workerName}/schedules`,
|
|
1360
|
-
props.crons.map((cron) => ({ cron })),
|
|
1361
|
-
);
|
|
1362
|
-
|
|
1363
|
-
if (!res.ok) {
|
|
1364
|
-
await handleApiError(
|
|
1365
|
-
res,
|
|
1366
|
-
"updating cron triggers",
|
|
1367
|
-
"worker",
|
|
1368
|
-
workerName,
|
|
1369
|
-
);
|
|
1370
|
-
}
|
|
1371
|
-
}
|
|
1372
|
-
|
|
1373
|
-
return { scriptBundle, workerUrl, now, versionResult };
|
|
1374
1128
|
};
|
|
1375
1129
|
|
|
1376
|
-
if (this.phase === "delete") {
|
|
1377
|
-
// only delete the worker if it's not a version
|
|
1378
|
-
if (!props.version) {
|
|
1379
|
-
// Delete any queue consumers attached to this worker first
|
|
1380
|
-
await deleteQueueConsumers(api, workerName);
|
|
1381
|
-
|
|
1382
|
-
await withExponentialBackoff(
|
|
1383
|
-
() =>
|
|
1384
|
-
deleteWorker(api, {
|
|
1385
|
-
workerName,
|
|
1386
|
-
namespace:
|
|
1387
|
-
typeof props.namespace === "string"
|
|
1388
|
-
? props.namespace
|
|
1389
|
-
: props.namespace?.namespaceId,
|
|
1390
|
-
url: this.output.url,
|
|
1391
|
-
}),
|
|
1392
|
-
(err) =>
|
|
1393
|
-
(err.status === 400 &&
|
|
1394
|
-
err.message.includes(
|
|
1395
|
-
"is still referenced by service bindings in Workers",
|
|
1396
|
-
)) ||
|
|
1397
|
-
err.status === 500 ||
|
|
1398
|
-
err.status === 503,
|
|
1399
|
-
10,
|
|
1400
|
-
100,
|
|
1401
|
-
);
|
|
1402
|
-
}
|
|
1403
|
-
return this.destroy();
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
1130
|
if (this.phase === "create") {
|
|
1407
1131
|
if (props.version) {
|
|
1408
1132
|
// When version is specified, we adopt existing workers or create them if they don't exist
|
|
1409
|
-
|
|
1410
|
-
if (!workerExists) {
|
|
1133
|
+
if (!(await workerExists(api, workerName))) {
|
|
1411
1134
|
// Create the base worker first if it doesn't exist
|
|
1412
1135
|
const baseWorkerProps = { ...props, version: undefined };
|
|
1413
|
-
await
|
|
1136
|
+
await putWorkerWithAssets(baseWorkerProps, await bundle.create());
|
|
1414
1137
|
}
|
|
1415
1138
|
// We always "adopt" when publishing versions
|
|
1416
1139
|
} else if (!props.adopt) {
|
|
@@ -1418,106 +1141,164 @@ export const _Worker = Resource(
|
|
|
1418
1141
|
}
|
|
1419
1142
|
}
|
|
1420
1143
|
|
|
1421
|
-
|
|
1144
|
+
let putWorkerResult: PutWorkerResult;
|
|
1145
|
+
if (dev.type === "remote") {
|
|
1146
|
+
// todo(john): clean this up and add log tail
|
|
1147
|
+
const controller = new AbortController();
|
|
1148
|
+
cleanups.push(() => controller.abort());
|
|
1149
|
+
const watcher = await bundle.watch(controller.signal);
|
|
1150
|
+
const promise = new DeferredPromise<PutWorkerResult>();
|
|
1151
|
+
void watcher.pipeTo(
|
|
1152
|
+
new WritableStream({
|
|
1153
|
+
async write(chunk) {
|
|
1154
|
+
switch (chunk.type) {
|
|
1155
|
+
case "start":
|
|
1156
|
+
logger.task("", {
|
|
1157
|
+
message: "start",
|
|
1158
|
+
status: "pending",
|
|
1159
|
+
resource: id,
|
|
1160
|
+
prefix: "build",
|
|
1161
|
+
prefixColor: "cyanBright",
|
|
1162
|
+
});
|
|
1163
|
+
break;
|
|
1164
|
+
case "end": {
|
|
1165
|
+
if (promise.status === "pending") {
|
|
1166
|
+
await putWorkerWithAssets(props, chunk.result)
|
|
1167
|
+
.then((result) => promise.resolve(result))
|
|
1168
|
+
.catch((error) => {
|
|
1169
|
+
controller.abort();
|
|
1170
|
+
promise.reject(error);
|
|
1171
|
+
});
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
1422
1174
|
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1175
|
+
logger.task("", {
|
|
1176
|
+
message: "reload",
|
|
1177
|
+
status: "success",
|
|
1178
|
+
resource: id,
|
|
1179
|
+
prefix: "build",
|
|
1180
|
+
prefixColor: "cyanBright",
|
|
1181
|
+
});
|
|
1182
|
+
await putWorker(api, {
|
|
1183
|
+
...props,
|
|
1184
|
+
workerName,
|
|
1185
|
+
scriptBundle: chunk.result,
|
|
1186
|
+
dispatchNamespace,
|
|
1187
|
+
version: props.version,
|
|
1188
|
+
compatibilityDate,
|
|
1189
|
+
compatibilityFlags,
|
|
1190
|
+
assetUploadResult: assetsBinding
|
|
1191
|
+
? {
|
|
1192
|
+
keepAssets: true,
|
|
1193
|
+
assetConfig: props.assets,
|
|
1194
|
+
}
|
|
1195
|
+
: undefined,
|
|
1196
|
+
unstable_cacheWorkerSettings: true,
|
|
1197
|
+
});
|
|
1198
|
+
logger.task("", {
|
|
1199
|
+
message: "updated",
|
|
1200
|
+
status: "success",
|
|
1201
|
+
resource: id,
|
|
1202
|
+
prefix: "build",
|
|
1203
|
+
prefixColor: "greenBright",
|
|
1204
|
+
});
|
|
1205
|
+
break;
|
|
1206
|
+
}
|
|
1207
|
+
case "error":
|
|
1208
|
+
logger.task("", {
|
|
1209
|
+
message: "error",
|
|
1210
|
+
status: "failure",
|
|
1211
|
+
resource: id,
|
|
1212
|
+
prefix: "build",
|
|
1213
|
+
prefixColor: "redBright",
|
|
1214
|
+
});
|
|
1215
|
+
logger.error(chunk.errors);
|
|
1216
|
+
break;
|
|
1217
|
+
}
|
|
1218
|
+
},
|
|
1219
|
+
}),
|
|
1426
1220
|
);
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1221
|
+
putWorkerResult = await promise.value;
|
|
1222
|
+
const tail = await createTail(api, id, workerName);
|
|
1223
|
+
cleanups.push(() => tail.close());
|
|
1224
|
+
} else {
|
|
1225
|
+
putWorkerResult = await putWorkerWithAssets(props, await bundle.create());
|
|
1430
1226
|
}
|
|
1431
1227
|
|
|
1432
|
-
|
|
1433
|
-
if (props.domains?.length) {
|
|
1434
|
-
ensureNoDuplicates(
|
|
1435
|
-
"Custom Domain",
|
|
1436
|
-
props.domains.map((domain) =>
|
|
1437
|
-
typeof domain === "string" ? domain : domain.domainName,
|
|
1438
|
-
),
|
|
1439
|
-
);
|
|
1228
|
+
const tasks: Promise<unknown>[] = [];
|
|
1440
1229
|
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
adopt:
|
|
1455
|
-
typeof customDomain === "string"
|
|
1456
|
-
? (props.adopt ?? false)
|
|
1457
|
-
: (customDomain.adopt ?? props.adopt),
|
|
1458
|
-
});
|
|
1459
|
-
}),
|
|
1460
|
-
);
|
|
1230
|
+
for (const workflow of workflowsBindings) {
|
|
1231
|
+
if (
|
|
1232
|
+
workflow.scriptName === undefined ||
|
|
1233
|
+
workflow.scriptName === workerName
|
|
1234
|
+
) {
|
|
1235
|
+
tasks.push(
|
|
1236
|
+
upsertWorkflow(api, {
|
|
1237
|
+
workflowName: workflow.workflowName,
|
|
1238
|
+
className: workflow.className,
|
|
1239
|
+
scriptName: workflow.scriptName ?? workerName,
|
|
1240
|
+
}),
|
|
1241
|
+
);
|
|
1242
|
+
}
|
|
1461
1243
|
}
|
|
1462
1244
|
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1245
|
+
if (containersBindings.length > 0) {
|
|
1246
|
+
tasks.push(
|
|
1247
|
+
getVersionMetadata(api, workerName, putWorkerResult.deployment_id).then(
|
|
1248
|
+
(versionMetadata) =>
|
|
1249
|
+
provisionContainers(api, {
|
|
1250
|
+
scriptName: workerName,
|
|
1251
|
+
containers: containersBindings,
|
|
1252
|
+
bindings: versionMetadata.resources.bindings,
|
|
1253
|
+
}),
|
|
1470
1254
|
),
|
|
1471
1255
|
);
|
|
1472
|
-
|
|
1473
|
-
// Create Route resources for each route and capture their outputs
|
|
1474
|
-
createdRoutes = await Promise.all(
|
|
1475
|
-
props.routes.map(async (routeConfig) => {
|
|
1476
|
-
const pattern =
|
|
1477
|
-
typeof routeConfig === "string" ? routeConfig : routeConfig.pattern;
|
|
1478
|
-
return await Route(pattern, {
|
|
1479
|
-
pattern,
|
|
1480
|
-
script: workerName,
|
|
1481
|
-
zoneId:
|
|
1482
|
-
typeof routeConfig === "string" ? undefined : routeConfig.zoneId, // Route resource will handle inference if not provided
|
|
1483
|
-
adopt:
|
|
1484
|
-
typeof routeConfig === "string"
|
|
1485
|
-
? (props.adopt ?? false)
|
|
1486
|
-
: (routeConfig.adopt ?? props.adopt),
|
|
1487
|
-
accountId: props.accountId,
|
|
1488
|
-
apiKey: props.apiKey,
|
|
1489
|
-
apiToken: props.apiToken,
|
|
1490
|
-
baseUrl: props.baseUrl,
|
|
1491
|
-
email: props.email,
|
|
1492
|
-
});
|
|
1493
|
-
}),
|
|
1494
|
-
);
|
|
1495
1256
|
}
|
|
1496
1257
|
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
isDurableObjectNamespace(binding) &&
|
|
1503
|
-
binding.scriptName === undefined
|
|
1504
|
-
? new DurableObjectNamespace(binding.id, {
|
|
1505
|
-
...binding,
|
|
1506
|
-
// re-export this binding mapping to the host worker (this worker)
|
|
1507
|
-
scriptName: workerName,
|
|
1508
|
-
})
|
|
1509
|
-
: isWorkflow(binding) && binding.scriptName === undefined
|
|
1510
|
-
? new Workflow(binding.id, {
|
|
1511
|
-
...binding,
|
|
1512
|
-
// re-export this binding mapping to the host worker (this worker)
|
|
1513
|
-
scriptName: workerName,
|
|
1514
|
-
})
|
|
1515
|
-
: binding,
|
|
1516
|
-
],
|
|
1258
|
+
if (!isDeepStrictEqual(props.crons, this.output?.crons)) {
|
|
1259
|
+
tasks.push(
|
|
1260
|
+
api.put(
|
|
1261
|
+
`/accounts/${api.accountId}/workers/scripts/${workerName}/schedules`,
|
|
1262
|
+
props.crons?.map((cron) => ({ cron })) ?? [],
|
|
1517
1263
|
),
|
|
1518
1264
|
);
|
|
1519
1265
|
}
|
|
1520
1266
|
|
|
1267
|
+
tasks.push(
|
|
1268
|
+
provisionEventSources(api, {
|
|
1269
|
+
scriptName: workerName,
|
|
1270
|
+
eventSources: props.eventSources,
|
|
1271
|
+
}),
|
|
1272
|
+
);
|
|
1273
|
+
|
|
1274
|
+
const [domains, routes, subdomain] = await Promise.all([
|
|
1275
|
+
// TODO: can you provision domains and routes in parallel, or is there a dependency?
|
|
1276
|
+
provisionDomains(api, {
|
|
1277
|
+
scriptName: workerName,
|
|
1278
|
+
adopt: props.adopt,
|
|
1279
|
+
domains: props.domains,
|
|
1280
|
+
}),
|
|
1281
|
+
provisionRoutes(api, {
|
|
1282
|
+
scriptName: workerName,
|
|
1283
|
+
adopt: props.adopt,
|
|
1284
|
+
routes: props.routes,
|
|
1285
|
+
}),
|
|
1286
|
+
provisionSubdomain(api, {
|
|
1287
|
+
scriptName: workerName,
|
|
1288
|
+
enable: props.url ?? dispatchNamespace === undefined,
|
|
1289
|
+
previewVersionId:
|
|
1290
|
+
props.version && putWorkerResult.metadata.has_preview
|
|
1291
|
+
? putWorkerResult.id
|
|
1292
|
+
: undefined,
|
|
1293
|
+
retain: !!props.version,
|
|
1294
|
+
forceDelete:
|
|
1295
|
+
this.phase === "create" && !!props.adopt && props.url === false,
|
|
1296
|
+
}),
|
|
1297
|
+
...tasks,
|
|
1298
|
+
]);
|
|
1299
|
+
|
|
1300
|
+
const now = Date.now();
|
|
1301
|
+
|
|
1521
1302
|
// Construct the output
|
|
1522
1303
|
return this({
|
|
1523
1304
|
...props,
|
|
@@ -1529,22 +1310,22 @@ export const _Worker = Resource(
|
|
|
1529
1310
|
compatibilityDate,
|
|
1530
1311
|
compatibilityFlags,
|
|
1531
1312
|
format: props.format || "esm", // Include format in the output
|
|
1532
|
-
bindings:
|
|
1313
|
+
bindings: normalizeExportBindings(workerName, props.bindings),
|
|
1533
1314
|
env: props.env,
|
|
1534
1315
|
observability: props.observability,
|
|
1535
|
-
createdAt: now,
|
|
1316
|
+
createdAt: this.output?.createdAt ?? now,
|
|
1536
1317
|
updatedAt: now,
|
|
1537
1318
|
eventSources: props.eventSources,
|
|
1538
|
-
url:
|
|
1319
|
+
url: subdomain?.url,
|
|
1539
1320
|
dev: props.dev,
|
|
1540
1321
|
// Include assets configuration in the output
|
|
1541
1322
|
assets: props.assets,
|
|
1542
1323
|
// Include cron triggers in the output
|
|
1543
1324
|
crons: props.crons,
|
|
1544
1325
|
// Include the created routes in the output
|
|
1545
|
-
routes
|
|
1326
|
+
routes,
|
|
1546
1327
|
// Include the created domains in the output
|
|
1547
|
-
domains
|
|
1328
|
+
domains,
|
|
1548
1329
|
// Include the dispatch namespace in the output
|
|
1549
1330
|
namespace: props.namespace,
|
|
1550
1331
|
// Include version information in the output
|
|
@@ -1555,48 +1336,442 @@ export const _Worker = Resource(
|
|
|
1555
1336
|
},
|
|
1556
1337
|
);
|
|
1557
1338
|
|
|
1558
|
-
|
|
1339
|
+
const cleanups: (() => any)[] = [];
|
|
1340
|
+
let exiting = false;
|
|
1341
|
+
|
|
1342
|
+
process.on("SIGINT", async () => {
|
|
1343
|
+
if (cleanups.length > 0) {
|
|
1344
|
+
if (!exiting) {
|
|
1345
|
+
exiting = true;
|
|
1346
|
+
logger.log(`\n${kleur.gray("Exiting...")}`);
|
|
1347
|
+
}
|
|
1348
|
+
// TODO: for some reason this runs twice...
|
|
1349
|
+
// and this whole thing feels hacky anyway
|
|
1350
|
+
await Promise.allSettled(cleanups.map((cleanup) => cleanup()));
|
|
1351
|
+
}
|
|
1352
|
+
process.exit(0);
|
|
1353
|
+
});
|
|
1354
|
+
|
|
1355
|
+
type Dev =
|
|
1356
|
+
| {
|
|
1357
|
+
type: "none";
|
|
1358
|
+
local: false;
|
|
1359
|
+
}
|
|
1360
|
+
| {
|
|
1361
|
+
type: "miniflare";
|
|
1362
|
+
port?: number;
|
|
1363
|
+
local: true;
|
|
1364
|
+
}
|
|
1365
|
+
| {
|
|
1366
|
+
type: "command";
|
|
1367
|
+
command: string;
|
|
1368
|
+
url: string;
|
|
1369
|
+
cwd?: string;
|
|
1370
|
+
local: true;
|
|
1371
|
+
}
|
|
1372
|
+
| {
|
|
1373
|
+
type: "remote";
|
|
1374
|
+
local: false;
|
|
1375
|
+
};
|
|
1376
|
+
|
|
1377
|
+
const normalizeDev = (ctx: Context<any>, dev: WorkerProps["dev"]): Dev => {
|
|
1378
|
+
if (!ctx.scope.dev || ctx.phase === "delete" || dev === false) {
|
|
1379
|
+
return {
|
|
1380
|
+
type: "none",
|
|
1381
|
+
local: false,
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
const devObj = dev === true ? {} : (dev ?? {});
|
|
1385
|
+
if ("command" in devObj) {
|
|
1386
|
+
// Commands are always local
|
|
1387
|
+
return {
|
|
1388
|
+
type: "command",
|
|
1389
|
+
...devObj,
|
|
1390
|
+
local: true,
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
if (devObj.remote === false || ctx.scope.dev === "prefer-local") {
|
|
1394
|
+
return {
|
|
1395
|
+
type: "miniflare",
|
|
1396
|
+
port: devObj.port,
|
|
1397
|
+
local: true,
|
|
1398
|
+
};
|
|
1399
|
+
}
|
|
1400
|
+
return {
|
|
1401
|
+
type: "remote",
|
|
1402
|
+
local: false,
|
|
1403
|
+
};
|
|
1404
|
+
};
|
|
1405
|
+
|
|
1406
|
+
const assertUnique = <T, Key extends keyof T>(
|
|
1407
|
+
inputs: T[],
|
|
1408
|
+
key: Key,
|
|
1409
|
+
message: string,
|
|
1410
|
+
) => {
|
|
1411
|
+
const ids = inputs.map((input) => input[key]);
|
|
1412
|
+
const duplicates = ids.filter((id, index) => ids.indexOf(id) !== index);
|
|
1413
|
+
if (duplicates.length > 0) {
|
|
1414
|
+
throw new Error(`Duplicate ${message} found: ${duplicates.join(", ")}`);
|
|
1415
|
+
}
|
|
1416
|
+
};
|
|
1417
|
+
|
|
1418
|
+
const normalizeExportBindings = (
|
|
1419
|
+
scriptName: string,
|
|
1420
|
+
bindings: Bindings = {},
|
|
1421
|
+
) => {
|
|
1422
|
+
return Object.fromEntries(
|
|
1423
|
+
Object.entries(bindings).map(([bindingName, binding]) => [
|
|
1424
|
+
bindingName,
|
|
1425
|
+
isDurableObjectNamespace(binding) && binding.scriptName === undefined
|
|
1426
|
+
? new DurableObjectNamespace(binding.id, {
|
|
1427
|
+
...binding,
|
|
1428
|
+
// re-export this binding mapping to the host worker (this worker)
|
|
1429
|
+
scriptName,
|
|
1430
|
+
})
|
|
1431
|
+
: isWorkflow(binding) && binding.scriptName === undefined
|
|
1432
|
+
? new Workflow(binding.id, {
|
|
1433
|
+
...binding,
|
|
1434
|
+
// re-export this binding mapping to the host worker (this worker)
|
|
1435
|
+
scriptName,
|
|
1436
|
+
})
|
|
1437
|
+
: binding,
|
|
1438
|
+
]),
|
|
1439
|
+
);
|
|
1440
|
+
};
|
|
1441
|
+
|
|
1442
|
+
const normalizeApiOptions = (api: CloudflareApi): CloudflareApiOptions => ({
|
|
1443
|
+
accountId: api.accountId,
|
|
1444
|
+
apiKey: api.apiKey,
|
|
1445
|
+
apiToken: api.apiToken,
|
|
1446
|
+
email: api.email,
|
|
1447
|
+
baseUrl: api.baseUrl,
|
|
1448
|
+
});
|
|
1449
|
+
|
|
1450
|
+
async function provisionContainers(
|
|
1559
1451
|
api: CloudflareApi,
|
|
1560
1452
|
props: {
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1453
|
+
scriptName: string;
|
|
1454
|
+
containers?: Container[];
|
|
1455
|
+
bindings: WorkerBindingSpec[];
|
|
1564
1456
|
},
|
|
1565
|
-
) {
|
|
1566
|
-
|
|
1457
|
+
): Promise<ContainerApplication[] | undefined> {
|
|
1458
|
+
if (!props.containers?.length) {
|
|
1459
|
+
return;
|
|
1460
|
+
}
|
|
1461
|
+
return await Promise.all(
|
|
1462
|
+
props.containers.map((container) => {
|
|
1463
|
+
const namespaceId = props.bindings.find(
|
|
1464
|
+
(binding): binding is WorkerBindingDurableObjectNamespace =>
|
|
1465
|
+
binding.type === "durable_object_namespace" &&
|
|
1466
|
+
binding.class_name === container.className,
|
|
1467
|
+
)?.namespace_id;
|
|
1468
|
+
if (!namespaceId) {
|
|
1469
|
+
throw new Error(`Namespace ID not found for container ${container.id}`);
|
|
1470
|
+
}
|
|
1471
|
+
return ContainerApplication(container.id, {
|
|
1472
|
+
image: container.image,
|
|
1473
|
+
name: container.id,
|
|
1474
|
+
instanceType: container.instanceType,
|
|
1475
|
+
observability: container.observability,
|
|
1476
|
+
durableObjects: {
|
|
1477
|
+
namespaceId,
|
|
1478
|
+
},
|
|
1479
|
+
schedulingPolicy: container.schedulingPolicy,
|
|
1480
|
+
adopt: container.adopt,
|
|
1481
|
+
...normalizeApiOptions(api),
|
|
1482
|
+
});
|
|
1483
|
+
}),
|
|
1484
|
+
);
|
|
1485
|
+
}
|
|
1567
1486
|
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1487
|
+
async function provisionEventSources(
|
|
1488
|
+
api: CloudflareApi,
|
|
1489
|
+
props: {
|
|
1490
|
+
scriptName: string;
|
|
1491
|
+
eventSources?: EventSource[];
|
|
1492
|
+
},
|
|
1493
|
+
): Promise<QueueConsumer[] | undefined> {
|
|
1494
|
+
if (!props.eventSources?.length) {
|
|
1495
|
+
return;
|
|
1496
|
+
}
|
|
1497
|
+
return await Promise.all(
|
|
1498
|
+
props.eventSources.map((eventSource) => {
|
|
1499
|
+
if (isQueue(eventSource)) {
|
|
1500
|
+
return QueueConsumer(`${eventSource.id}-consumer`, {
|
|
1501
|
+
queue: eventSource,
|
|
1502
|
+
scriptName: props.scriptName,
|
|
1503
|
+
settings: eventSource.dlq
|
|
1504
|
+
? { deadLetterQueue: eventSource.dlq }
|
|
1505
|
+
: undefined,
|
|
1506
|
+
...normalizeApiOptions(api),
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1509
|
+
if (isQueueEventSource(eventSource)) {
|
|
1510
|
+
return QueueConsumer(`${eventSource.queue.id}-consumer`, {
|
|
1511
|
+
queue: eventSource.queue,
|
|
1512
|
+
scriptName: props.scriptName,
|
|
1513
|
+
settings: eventSource.settings,
|
|
1514
|
+
...normalizeApiOptions(api),
|
|
1515
|
+
});
|
|
1516
|
+
}
|
|
1517
|
+
throw new Error(`Unsupported event source: ${eventSource}`);
|
|
1518
|
+
}),
|
|
1573
1519
|
);
|
|
1520
|
+
}
|
|
1574
1521
|
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1522
|
+
async function provisionDomains(
|
|
1523
|
+
api: CloudflareApi,
|
|
1524
|
+
props: {
|
|
1525
|
+
scriptName: string;
|
|
1526
|
+
adopt?: boolean;
|
|
1527
|
+
domains?: WorkerProps["domains"];
|
|
1528
|
+
},
|
|
1529
|
+
): Promise<CustomDomain[] | undefined> {
|
|
1530
|
+
if (!props.domains?.length) {
|
|
1531
|
+
return;
|
|
1578
1532
|
}
|
|
1533
|
+
const domains = props.domains.map((domain) => {
|
|
1534
|
+
if (typeof domain === "string") {
|
|
1535
|
+
return {
|
|
1536
|
+
name: domain,
|
|
1537
|
+
zoneId: undefined,
|
|
1538
|
+
adopt: props.adopt,
|
|
1539
|
+
};
|
|
1540
|
+
}
|
|
1541
|
+
return {
|
|
1542
|
+
name: domain.domainName,
|
|
1543
|
+
zoneId: domain.zoneId,
|
|
1544
|
+
adopt: domain.adopt ?? props.adopt,
|
|
1545
|
+
};
|
|
1546
|
+
});
|
|
1547
|
+
assertUnique(domains, "name", "Custom Domain");
|
|
1548
|
+
return await Promise.all(
|
|
1549
|
+
domains.map(async (domain) => {
|
|
1550
|
+
return await CustomDomain(domain.name, {
|
|
1551
|
+
workerName: props.scriptName,
|
|
1552
|
+
name: domain.name,
|
|
1553
|
+
zoneId: domain.zoneId,
|
|
1554
|
+
adopt: domain.adopt,
|
|
1555
|
+
...normalizeApiOptions(api),
|
|
1556
|
+
});
|
|
1557
|
+
}),
|
|
1558
|
+
);
|
|
1559
|
+
}
|
|
1579
1560
|
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1561
|
+
async function provisionRoutes(
|
|
1562
|
+
api: CloudflareApi,
|
|
1563
|
+
props: {
|
|
1564
|
+
scriptName: string;
|
|
1565
|
+
adopt?: boolean;
|
|
1566
|
+
routes?: WorkerProps["routes"];
|
|
1567
|
+
},
|
|
1568
|
+
): Promise<Route[] | undefined> {
|
|
1569
|
+
if (!props.routes?.length) {
|
|
1570
|
+
return;
|
|
1571
|
+
}
|
|
1572
|
+
const routes = props.routes.map((route) => {
|
|
1573
|
+
if (typeof route === "string") {
|
|
1574
|
+
return {
|
|
1575
|
+
pattern: route,
|
|
1576
|
+
adopt: props.adopt,
|
|
1577
|
+
};
|
|
1592
1578
|
}
|
|
1579
|
+
return {
|
|
1580
|
+
pattern: route.pattern,
|
|
1581
|
+
zoneId: route.zoneId,
|
|
1582
|
+
adopt: route.adopt ?? props.adopt,
|
|
1583
|
+
};
|
|
1584
|
+
});
|
|
1585
|
+
assertUnique(routes, "pattern", "Route");
|
|
1586
|
+
return await Promise.all(
|
|
1587
|
+
routes.map(async (route) => {
|
|
1588
|
+
return await Route(route.pattern, {
|
|
1589
|
+
pattern: route.pattern,
|
|
1590
|
+
script: props.scriptName,
|
|
1591
|
+
zoneId: route.zoneId,
|
|
1592
|
+
adopt: route.adopt,
|
|
1593
|
+
...normalizeApiOptions(api),
|
|
1594
|
+
});
|
|
1595
|
+
}),
|
|
1596
|
+
);
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
async function provisionSubdomain(
|
|
1600
|
+
api: CloudflareApi,
|
|
1601
|
+
props: {
|
|
1602
|
+
scriptName: string;
|
|
1603
|
+
enable: boolean;
|
|
1604
|
+
previewVersionId: string | undefined;
|
|
1605
|
+
retain: boolean;
|
|
1606
|
+
forceDelete: boolean;
|
|
1607
|
+
},
|
|
1608
|
+
): Promise<WorkerSubdomain | undefined> {
|
|
1609
|
+
if (props.enable) {
|
|
1610
|
+
return await WorkerSubdomain("url", {
|
|
1611
|
+
scriptName: props.scriptName,
|
|
1612
|
+
previewVersionId: props.previewVersionId,
|
|
1613
|
+
retain: props.retain,
|
|
1614
|
+
...normalizeApiOptions(api),
|
|
1615
|
+
});
|
|
1616
|
+
}
|
|
1617
|
+
if (props.forceDelete) {
|
|
1618
|
+
await disableWorkerSubdomain(api, props.scriptName);
|
|
1593
1619
|
}
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
async function createMiniflare(props: {
|
|
1623
|
+
id: string;
|
|
1624
|
+
workerName: string;
|
|
1625
|
+
compatibilityDate: string;
|
|
1626
|
+
compatibilityFlags: string[];
|
|
1627
|
+
bindings: Bindings | undefined;
|
|
1628
|
+
port: number | undefined;
|
|
1629
|
+
bundle: WorkerBundleProvider;
|
|
1630
|
+
}) {
|
|
1631
|
+
const sharedOptions: Omit<MiniflareWorkerOptions, "bundle"> = {
|
|
1632
|
+
name: props.workerName,
|
|
1633
|
+
compatibilityDate: props.compatibilityDate,
|
|
1634
|
+
compatibilityFlags: props.compatibilityFlags,
|
|
1635
|
+
bindings: props.bindings,
|
|
1636
|
+
port: props.port,
|
|
1637
|
+
};
|
|
1638
|
+
|
|
1639
|
+
const startPromise = new DeferredPromise<string>();
|
|
1640
|
+
// todo(john): streamline and share logging logic with remote dev
|
|
1641
|
+
type Events =
|
|
1642
|
+
| {
|
|
1643
|
+
type: "build-start" | "build-end";
|
|
1644
|
+
}
|
|
1645
|
+
| {
|
|
1646
|
+
type: "build-error";
|
|
1647
|
+
errors: esbuild.Message[];
|
|
1648
|
+
}
|
|
1649
|
+
| {
|
|
1650
|
+
type: "miniflare-ready";
|
|
1651
|
+
url: string;
|
|
1652
|
+
}
|
|
1653
|
+
| {
|
|
1654
|
+
type: "miniflare-error";
|
|
1655
|
+
error: Error;
|
|
1656
|
+
};
|
|
1657
|
+
const controller = new AbortController();
|
|
1658
|
+
cleanups.push(() => controller.abort());
|
|
1659
|
+
(await props.bundle.watch(controller.signal))
|
|
1660
|
+
.pipeThrough(
|
|
1661
|
+
new TransformStream<WorkerBundleChunk, Events>({
|
|
1662
|
+
async transform(chunk, controller) {
|
|
1663
|
+
switch (chunk.type) {
|
|
1664
|
+
case "start": {
|
|
1665
|
+
controller.enqueue({ type: "build-start" });
|
|
1666
|
+
break;
|
|
1667
|
+
}
|
|
1668
|
+
case "end": {
|
|
1669
|
+
controller.enqueue({ type: "build-end" });
|
|
1670
|
+
try {
|
|
1671
|
+
const server = await miniflareServer.push({
|
|
1672
|
+
...sharedOptions,
|
|
1673
|
+
bundle: chunk.result,
|
|
1674
|
+
});
|
|
1675
|
+
controller.enqueue({
|
|
1676
|
+
type: "miniflare-ready",
|
|
1677
|
+
url: server.url,
|
|
1678
|
+
});
|
|
1679
|
+
} catch (error) {
|
|
1680
|
+
controller.enqueue({
|
|
1681
|
+
type: "miniflare-error",
|
|
1682
|
+
error: error as Error,
|
|
1683
|
+
});
|
|
1684
|
+
}
|
|
1685
|
+
break;
|
|
1686
|
+
}
|
|
1687
|
+
case "error": {
|
|
1688
|
+
controller.enqueue({
|
|
1689
|
+
type: "build-error",
|
|
1690
|
+
errors: chunk.errors,
|
|
1691
|
+
});
|
|
1692
|
+
break;
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
},
|
|
1696
|
+
}),
|
|
1697
|
+
)
|
|
1698
|
+
.pipeTo(
|
|
1699
|
+
new WritableStream({
|
|
1700
|
+
write: async (chunk) => {
|
|
1701
|
+
switch (chunk.type) {
|
|
1702
|
+
case "build-start": {
|
|
1703
|
+
logger.task("", {
|
|
1704
|
+
message: "start",
|
|
1705
|
+
status: "pending",
|
|
1706
|
+
resource: props.id,
|
|
1707
|
+
prefix: "build",
|
|
1708
|
+
prefixColor: "cyanBright",
|
|
1709
|
+
});
|
|
1710
|
+
break;
|
|
1711
|
+
}
|
|
1712
|
+
case "build-end": {
|
|
1713
|
+
logger.task("", {
|
|
1714
|
+
message: startPromise.status === "pending" ? "load" : "reload",
|
|
1715
|
+
status: "success",
|
|
1716
|
+
resource: props.id,
|
|
1717
|
+
prefix: "build",
|
|
1718
|
+
prefixColor: "greenBright",
|
|
1719
|
+
});
|
|
1720
|
+
break;
|
|
1721
|
+
}
|
|
1722
|
+
case "build-error": {
|
|
1723
|
+
logger.task("", {
|
|
1724
|
+
message: "error",
|
|
1725
|
+
status: "failure",
|
|
1726
|
+
resource: props.id,
|
|
1727
|
+
prefix: "build",
|
|
1728
|
+
prefixColor: "redBright",
|
|
1729
|
+
});
|
|
1730
|
+
if (startPromise.status === "pending") {
|
|
1731
|
+
controller.abort();
|
|
1732
|
+
startPromise.reject(chunk.errors);
|
|
1733
|
+
} else {
|
|
1734
|
+
logger.error(chunk.errors);
|
|
1735
|
+
}
|
|
1736
|
+
break;
|
|
1737
|
+
}
|
|
1738
|
+
case "miniflare-ready": {
|
|
1739
|
+
logger.task("", {
|
|
1740
|
+
message: `ready at ${chunk.url}`,
|
|
1741
|
+
status: "success",
|
|
1742
|
+
resource: props.id,
|
|
1743
|
+
prefix: "miniflare",
|
|
1744
|
+
prefixColor: "greenBright",
|
|
1745
|
+
});
|
|
1746
|
+
if (startPromise.status === "pending") {
|
|
1747
|
+
startPromise.resolve(chunk.url);
|
|
1748
|
+
}
|
|
1749
|
+
break;
|
|
1750
|
+
}
|
|
1751
|
+
case "miniflare-error": {
|
|
1752
|
+
logger.task("", {
|
|
1753
|
+
message: "error",
|
|
1754
|
+
status: "failure",
|
|
1755
|
+
resource: props.id,
|
|
1756
|
+
prefix: "miniflare",
|
|
1757
|
+
prefixColor: "redBright",
|
|
1758
|
+
});
|
|
1759
|
+
if (startPromise.status === "pending") {
|
|
1760
|
+
startPromise.reject(chunk.error);
|
|
1761
|
+
} else {
|
|
1762
|
+
logger.error(chunk.error);
|
|
1763
|
+
}
|
|
1764
|
+
break;
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
},
|
|
1768
|
+
}),
|
|
1769
|
+
);
|
|
1594
1770
|
|
|
1595
|
-
|
|
1596
|
-
return;
|
|
1771
|
+
return await startPromise.value;
|
|
1597
1772
|
}
|
|
1598
1773
|
|
|
1599
|
-
function
|
|
1774
|
+
function createDevCommand(props: {
|
|
1600
1775
|
id: string;
|
|
1601
1776
|
command: string;
|
|
1602
1777
|
cwd: string;
|
|
@@ -1630,14 +1805,13 @@ function upsertDevCommand(props: {
|
|
|
1630
1805
|
},
|
|
1631
1806
|
stdio: ["inherit", "inherit", "inherit"],
|
|
1632
1807
|
});
|
|
1633
|
-
|
|
1808
|
+
cleanups.push(() => {
|
|
1634
1809
|
try {
|
|
1635
1810
|
unlinkSync(persistFile);
|
|
1636
1811
|
} catch {
|
|
1637
1812
|
// ignore
|
|
1638
1813
|
}
|
|
1639
|
-
proc.kill(
|
|
1640
|
-
process.exit(0);
|
|
1814
|
+
proc.kill();
|
|
1641
1815
|
});
|
|
1642
1816
|
if (proc.pid) {
|
|
1643
1817
|
mkdirSync(path.dirname(persistFile), { recursive: true });
|
|
@@ -1649,124 +1823,124 @@ type PutWorkerOptions = WorkerProps & {
|
|
|
1649
1823
|
dispatchNamespace?: string;
|
|
1650
1824
|
migrationTag?: string;
|
|
1651
1825
|
workerName: string;
|
|
1652
|
-
scriptBundle:
|
|
1826
|
+
scriptBundle: WorkerBundle;
|
|
1653
1827
|
version: string | undefined;
|
|
1654
1828
|
compatibilityDate: string;
|
|
1655
1829
|
compatibilityFlags: string[];
|
|
1656
|
-
assetUploadResult:
|
|
1830
|
+
assetUploadResult:
|
|
1831
|
+
| {
|
|
1832
|
+
completionToken?: string;
|
|
1833
|
+
keepAssets?: boolean;
|
|
1834
|
+
assetConfig?: AssetsConfig;
|
|
1835
|
+
}
|
|
1836
|
+
| undefined;
|
|
1837
|
+
unstable_cacheWorkerSettings?: boolean;
|
|
1657
1838
|
};
|
|
1658
1839
|
|
|
1659
|
-
|
|
1840
|
+
async function prepareWorkerUpload(
|
|
1660
1841
|
api: CloudflareApi,
|
|
1661
1842
|
props: PutWorkerOptions,
|
|
1662
|
-
)
|
|
1663
|
-
const {
|
|
1664
|
-
//
|
|
1665
|
-
dispatchNamespace,
|
|
1666
|
-
migrationTag,
|
|
1667
|
-
workerName,
|
|
1668
|
-
scriptBundle,
|
|
1669
|
-
version,
|
|
1670
|
-
} = props;
|
|
1843
|
+
) {
|
|
1671
1844
|
const scriptMetadata = await prepareWorkerMetadata(api, props);
|
|
1672
1845
|
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
const formData = new FormData();
|
|
1680
|
-
|
|
1681
|
-
function addFile(fileName: string, content: Buffer | string) {
|
|
1682
|
-
const contentType = getContentType(fileName) ?? "application/null";
|
|
1683
|
-
formData.append(
|
|
1684
|
-
fileName,
|
|
1685
|
-
new Blob([content], {
|
|
1686
|
-
type:
|
|
1687
|
-
contentType === "application/javascript" &&
|
|
1688
|
-
scriptMetadata.main_module
|
|
1689
|
-
? "application/javascript+module"
|
|
1690
|
-
: contentType,
|
|
1691
|
-
}),
|
|
1692
|
-
fileName,
|
|
1693
|
-
);
|
|
1694
|
-
}
|
|
1695
|
-
|
|
1696
|
-
if (typeof scriptBundle === "string") {
|
|
1697
|
-
addFile(scriptName, scriptBundle);
|
|
1698
|
-
} else {
|
|
1699
|
-
for (const [fileName, content] of Object.entries(scriptBundle)) {
|
|
1700
|
-
addFile(fileName, content);
|
|
1701
|
-
}
|
|
1702
|
-
}
|
|
1846
|
+
if (props.format === "cjs") {
|
|
1847
|
+
scriptMetadata.body_part = props.scriptBundle.entrypoint;
|
|
1848
|
+
} else {
|
|
1849
|
+
scriptMetadata.main_module = props.scriptBundle.entrypoint;
|
|
1850
|
+
}
|
|
1851
|
+
const body = new FormData();
|
|
1703
1852
|
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
...scriptMetadata,
|
|
1708
|
-
// Exclude migrations for worker versions - they're not allowed
|
|
1709
|
-
migrations: undefined,
|
|
1710
|
-
annotations: {
|
|
1711
|
-
"workers/tag": version,
|
|
1712
|
-
"workers/message": `Version ${version}`,
|
|
1713
|
-
},
|
|
1714
|
-
}
|
|
1715
|
-
: {
|
|
1716
|
-
...scriptMetadata,
|
|
1717
|
-
migrations: scriptMetadata.migrations
|
|
1718
|
-
? {
|
|
1719
|
-
...scriptMetadata.migrations,
|
|
1720
|
-
old_tag: migrationTag,
|
|
1721
|
-
new_tag: bumpMigrationTagVersion(migrationTag),
|
|
1722
|
-
}
|
|
1723
|
-
: undefined,
|
|
1724
|
-
};
|
|
1853
|
+
for await (const file of props.scriptBundle.files) {
|
|
1854
|
+
body.append(file.name, file);
|
|
1855
|
+
}
|
|
1725
1856
|
|
|
1726
|
-
|
|
1727
|
-
|
|
1857
|
+
// Prepare metadata - add version annotations if this is a version
|
|
1858
|
+
const finalMetadata = props.version
|
|
1859
|
+
? {
|
|
1860
|
+
...scriptMetadata,
|
|
1861
|
+
// Exclude migrations for worker versions - they're not allowed
|
|
1862
|
+
migrations: undefined,
|
|
1863
|
+
annotations: {
|
|
1864
|
+
"workers/tag": props.version,
|
|
1865
|
+
"workers/message": `Version ${props.version}`,
|
|
1866
|
+
},
|
|
1728
1867
|
}
|
|
1868
|
+
: {
|
|
1869
|
+
...scriptMetadata,
|
|
1870
|
+
migrations: scriptMetadata.migrations
|
|
1871
|
+
? {
|
|
1872
|
+
...scriptMetadata.migrations,
|
|
1873
|
+
old_tag: props.migrationTag,
|
|
1874
|
+
new_tag: bumpMigrationTagVersion(props.migrationTag),
|
|
1875
|
+
}
|
|
1876
|
+
: undefined,
|
|
1877
|
+
};
|
|
1729
1878
|
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1879
|
+
body.append(
|
|
1880
|
+
"metadata",
|
|
1881
|
+
new Blob([JSON.stringify(finalMetadata)], {
|
|
1882
|
+
type: "application/json",
|
|
1883
|
+
}),
|
|
1884
|
+
);
|
|
1885
|
+
|
|
1886
|
+
let endpoint: string;
|
|
1887
|
+
let method: "PUT" | "POST";
|
|
1888
|
+
if (props.version) {
|
|
1889
|
+
if (props.dispatchNamespace) {
|
|
1890
|
+
throw new Error(
|
|
1891
|
+
"Worker Preview Versions are not supported in Workers for Platforms",
|
|
1736
1892
|
);
|
|
1893
|
+
}
|
|
1894
|
+
// Upload worker version using the versions API
|
|
1895
|
+
endpoint = `/accounts/${api.accountId}/workers/scripts/${props.workerName}/versions`;
|
|
1896
|
+
method = "POST";
|
|
1897
|
+
} else {
|
|
1898
|
+
// Upload worker script with bindings
|
|
1899
|
+
endpoint = props.dispatchNamespace
|
|
1900
|
+
? `/accounts/${api.accountId}/workers/dispatch/namespaces/${props.dispatchNamespace}/scripts/${props.workerName}`
|
|
1901
|
+
: `/accounts/${api.accountId}/workers/scripts/${props.workerName}`;
|
|
1902
|
+
method = "PUT";
|
|
1903
|
+
}
|
|
1737
1904
|
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
"Worker Preview Versions are not supported in Workers for Platforms",
|
|
1745
|
-
);
|
|
1746
|
-
}
|
|
1747
|
-
// Upload worker version using the versions API
|
|
1748
|
-
endpoint = `/accounts/${api.accountId}/workers/scripts/${workerName}/versions`;
|
|
1749
|
-
method = "POST";
|
|
1750
|
-
} else {
|
|
1751
|
-
// Upload worker script with bindings
|
|
1752
|
-
endpoint = dispatchNamespace
|
|
1753
|
-
? `/accounts/${api.accountId}/workers/dispatch/namespaces/${dispatchNamespace}/scripts/${workerName}`
|
|
1754
|
-
: `/accounts/${api.accountId}/workers/scripts/${workerName}`;
|
|
1755
|
-
method = "PUT";
|
|
1756
|
-
}
|
|
1905
|
+
return {
|
|
1906
|
+
body,
|
|
1907
|
+
endpoint,
|
|
1908
|
+
method,
|
|
1909
|
+
};
|
|
1910
|
+
}
|
|
1757
1911
|
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1912
|
+
interface PutWorkerResult {
|
|
1913
|
+
id: string;
|
|
1914
|
+
number: number;
|
|
1915
|
+
metadata: {
|
|
1916
|
+
has_preview: boolean;
|
|
1917
|
+
};
|
|
1918
|
+
annotations?: {
|
|
1919
|
+
"workers/tag"?: string;
|
|
1920
|
+
};
|
|
1921
|
+
deployment_id: string;
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
export async function putWorker(
|
|
1925
|
+
api: CloudflareApi,
|
|
1926
|
+
props: PutWorkerOptions,
|
|
1927
|
+
): Promise<PutWorkerResult> {
|
|
1928
|
+
const {
|
|
1929
|
+
//
|
|
1930
|
+
workerName,
|
|
1931
|
+
version,
|
|
1932
|
+
} = props;
|
|
1933
|
+
|
|
1934
|
+
return withExponentialBackoff(
|
|
1935
|
+
async () => {
|
|
1936
|
+
const { body, endpoint, method } = await prepareWorkerUpload(api, props);
|
|
1937
|
+
const uploadResponse = await api.fetch(endpoint, {
|
|
1938
|
+
method,
|
|
1939
|
+
headers: {
|
|
1940
|
+
"Content-Type": "multipart/form-data",
|
|
1941
|
+
},
|
|
1942
|
+
body,
|
|
1943
|
+
});
|
|
1770
1944
|
|
|
1771
1945
|
// Check if the upload was successful
|
|
1772
1946
|
if (!uploadResponse.ok) {
|
|
@@ -1805,55 +1979,9 @@ export async function putWorker(
|
|
|
1805
1979
|
}
|
|
1806
1980
|
}
|
|
1807
1981
|
const responseData = (await uploadResponse.json()) as {
|
|
1808
|
-
result:
|
|
1809
|
-
id: string;
|
|
1810
|
-
number: number;
|
|
1811
|
-
metadata: {
|
|
1812
|
-
has_preview: boolean;
|
|
1813
|
-
};
|
|
1814
|
-
annotations?: {
|
|
1815
|
-
"workers/tag"?: string;
|
|
1816
|
-
};
|
|
1817
|
-
deployment_id: string;
|
|
1818
|
-
};
|
|
1819
|
-
};
|
|
1820
|
-
const result = responseData.result;
|
|
1821
|
-
|
|
1822
|
-
// Handle version response
|
|
1823
|
-
if (props.version) {
|
|
1824
|
-
// Get the account's workers.dev subdomain to construct preview URL
|
|
1825
|
-
let previewUrl: string | undefined;
|
|
1826
|
-
if (result.metadata?.has_preview) {
|
|
1827
|
-
// Need to get the subdomain
|
|
1828
|
-
const subdomainResponse = await api.get(
|
|
1829
|
-
`/accounts/${api.accountId}/workers/subdomain`,
|
|
1830
|
-
);
|
|
1831
|
-
|
|
1832
|
-
if (subdomainResponse.ok) {
|
|
1833
|
-
const subdomainData: {
|
|
1834
|
-
result: {
|
|
1835
|
-
subdomain: string;
|
|
1836
|
-
};
|
|
1837
|
-
} = await subdomainResponse.json();
|
|
1838
|
-
const subdomain = subdomainData.result?.subdomain;
|
|
1839
|
-
if (subdomain) {
|
|
1840
|
-
// Preview URL format: <FIRST_8_CHARS_OF_VERSION_ID>-<WORKER_NAME>.<SUBDOMAIN>.workers.dev
|
|
1841
|
-
const versionPrefix = result.id.substring(0, 8);
|
|
1842
|
-
previewUrl = `https://${versionPrefix}-${workerName}.${subdomain}.workers.dev`;
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
}
|
|
1846
|
-
|
|
1847
|
-
return {
|
|
1848
|
-
versionId: result.id,
|
|
1849
|
-
previewUrl,
|
|
1850
|
-
deploymentId: result.deployment_id,
|
|
1851
|
-
};
|
|
1852
|
-
}
|
|
1853
|
-
|
|
1854
|
-
return {
|
|
1855
|
-
deploymentId: result.deployment_id,
|
|
1982
|
+
result: PutWorkerResult;
|
|
1856
1983
|
};
|
|
1984
|
+
return responseData.result;
|
|
1857
1985
|
},
|
|
1858
1986
|
(err) =>
|
|
1859
1987
|
err.status === 404 ||
|
|
@@ -1868,28 +1996,25 @@ export async function putWorker(
|
|
|
1868
1996
|
);
|
|
1869
1997
|
}
|
|
1870
1998
|
|
|
1871
|
-
|
|
1872
|
-
api
|
|
1873
|
-
|
|
1874
|
-
): Promise<boolean> {
|
|
1875
|
-
const response = await api.get(
|
|
1876
|
-
`/accounts/${api.accountId}/workers/scripts/${workerName}`,
|
|
1999
|
+
async function workerExists(api: CloudflareApi, scriptName: string) {
|
|
2000
|
+
const res = await api.get(
|
|
2001
|
+
`/accounts/${api.accountId}/workers/scripts/${scriptName}`,
|
|
1877
2002
|
);
|
|
1878
|
-
return
|
|
2003
|
+
return res.status === 200;
|
|
1879
2004
|
}
|
|
1880
2005
|
|
|
1881
|
-
|
|
2006
|
+
async function assertWorkerDoesNotExist(
|
|
1882
2007
|
api: CloudflareApi,
|
|
1883
|
-
|
|
2008
|
+
scriptName: string,
|
|
1884
2009
|
) {
|
|
1885
2010
|
const response = await api.get(
|
|
1886
|
-
`/accounts/${api.accountId}/workers/scripts/${
|
|
2011
|
+
`/accounts/${api.accountId}/workers/scripts/${scriptName}`,
|
|
1887
2012
|
);
|
|
1888
2013
|
if (response.status === 404) {
|
|
1889
2014
|
return true;
|
|
1890
2015
|
}
|
|
1891
2016
|
if (response.status === 200) {
|
|
1892
|
-
const metadata = await
|
|
2017
|
+
const metadata = await getScriptMetadata(api, scriptName);
|
|
1893
2018
|
|
|
1894
2019
|
if (!metadata) {
|
|
1895
2020
|
throw new Error(
|
|
@@ -1898,7 +2023,7 @@ export async function assertWorkerDoesNotExist(
|
|
|
1898
2023
|
}
|
|
1899
2024
|
|
|
1900
2025
|
throw new Error(
|
|
1901
|
-
`Worker with name '${
|
|
2026
|
+
`Worker with name '${scriptName}' already exists. Please use a unique name.`,
|
|
1902
2027
|
);
|
|
1903
2028
|
}
|
|
1904
2029
|
throw new Error(
|
|
@@ -1906,80 +2031,84 @@ export async function assertWorkerDoesNotExist(
|
|
|
1906
2031
|
);
|
|
1907
2032
|
}
|
|
1908
2033
|
|
|
1909
|
-
|
|
1910
|
-
ctx: Context<Worker<B>> | Context<WorkerStub>,
|
|
1911
|
-
api: CloudflareApi,
|
|
1912
|
-
workerName: string,
|
|
1913
|
-
url: boolean,
|
|
1914
|
-
) {
|
|
1915
|
-
let workerUrl;
|
|
1916
|
-
if (url) {
|
|
1917
|
-
// Enable the workers.dev subdomain for this worker
|
|
1918
|
-
await api.post(
|
|
1919
|
-
`/accounts/${api.accountId}/workers/scripts/${workerName}/subdomain`,
|
|
1920
|
-
{ enabled: true, previews_enabled: true },
|
|
1921
|
-
{
|
|
1922
|
-
headers: { "Content-Type": "application/json" },
|
|
1923
|
-
},
|
|
1924
|
-
);
|
|
1925
|
-
|
|
1926
|
-
// Get the account's workers.dev subdomain
|
|
1927
|
-
const subdomain = await getAccountSubdomain(api);
|
|
1928
|
-
|
|
1929
|
-
if (subdomain) {
|
|
1930
|
-
workerUrl = `https://${workerName}.${subdomain}.workers.dev`;
|
|
1931
|
-
}
|
|
1932
|
-
} else if (url === false && ctx.output?.url) {
|
|
1933
|
-
// Explicitly disable URL if it was previously enabled
|
|
1934
|
-
const response = await api.post(
|
|
1935
|
-
`/accounts/${api.accountId}/workers/scripts/${workerName}/subdomain`,
|
|
1936
|
-
JSON.stringify({ enabled: false }),
|
|
1937
|
-
{
|
|
1938
|
-
headers: { "Content-Type": "application/json" },
|
|
1939
|
-
},
|
|
1940
|
-
);
|
|
1941
|
-
if (!response.ok) {
|
|
1942
|
-
throw new Error(
|
|
1943
|
-
`Failed to disable worker URL: ${response.status} ${response.statusText}`,
|
|
1944
|
-
);
|
|
1945
|
-
}
|
|
1946
|
-
}
|
|
1947
|
-
return workerUrl;
|
|
1948
|
-
}
|
|
1949
|
-
|
|
1950
|
-
export async function getWorkerScriptMetadata(
|
|
2034
|
+
async function getScriptMetadata(
|
|
1951
2035
|
api: CloudflareApi,
|
|
1952
|
-
|
|
2036
|
+
scriptName: string,
|
|
1953
2037
|
): Promise<WorkerScriptMetadata | undefined> {
|
|
1954
|
-
const
|
|
1955
|
-
`/accounts/${api.accountId}/workers/services/${
|
|
2038
|
+
const res = await api.get(
|
|
2039
|
+
`/accounts/${api.accountId}/workers/services/${scriptName}`,
|
|
1956
2040
|
);
|
|
1957
|
-
if (
|
|
1958
|
-
return
|
|
2041
|
+
if (res.status === 404) {
|
|
2042
|
+
return;
|
|
1959
2043
|
}
|
|
1960
|
-
if (!
|
|
2044
|
+
if (!res.ok) {
|
|
1961
2045
|
throw new Error(
|
|
1962
|
-
`Error getting worker script metadata: ${
|
|
2046
|
+
`Error getting worker script metadata: ${res.status} ${res.statusText}`,
|
|
1963
2047
|
);
|
|
1964
2048
|
}
|
|
1965
|
-
|
|
2049
|
+
const json = (await res.json()) as { result: WorkerScriptMetadata };
|
|
2050
|
+
return json.result;
|
|
1966
2051
|
}
|
|
1967
2052
|
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
* @param ctx Worker context containing eventSources
|
|
1971
|
-
* @param api CloudflareApi instance
|
|
1972
|
-
* @param workerName Name of the worker script
|
|
1973
|
-
*/
|
|
1974
|
-
async function deleteQueueConsumers(
|
|
1975
|
-
api: CloudflareApi,
|
|
1976
|
-
workerName: string,
|
|
1977
|
-
): Promise<void> {
|
|
1978
|
-
const consumers = await listQueueConsumersForWorker(api, workerName);
|
|
1979
|
-
|
|
2053
|
+
async function deleteQueueConsumers(api: CloudflareApi, scriptName: string) {
|
|
2054
|
+
const consumers = await listQueueConsumersForWorker(api, scriptName);
|
|
1980
2055
|
await Promise.all(
|
|
1981
2056
|
consumers.map(async (consumer) => {
|
|
1982
2057
|
await deleteQueueConsumer(api, consumer.queueId, consumer.consumerId);
|
|
1983
2058
|
}),
|
|
1984
2059
|
);
|
|
1985
2060
|
}
|
|
2061
|
+
|
|
2062
|
+
export async function deleteWorker(
|
|
2063
|
+
api: CloudflareApi,
|
|
2064
|
+
props: {
|
|
2065
|
+
scriptName: string;
|
|
2066
|
+
dispatchNamespace?: string;
|
|
2067
|
+
},
|
|
2068
|
+
) {
|
|
2069
|
+
await withExponentialBackoff(
|
|
2070
|
+
async () => {
|
|
2071
|
+
const deleteResponse = await api.delete(
|
|
2072
|
+
props.dispatchNamespace
|
|
2073
|
+
? `/accounts/${api.accountId}/workers/dispatch/namespaces/${props.dispatchNamespace}/scripts/${props.scriptName}?force=true`
|
|
2074
|
+
: `/accounts/${api.accountId}/workers/scripts/${props.scriptName}?force=true`,
|
|
2075
|
+
);
|
|
2076
|
+
|
|
2077
|
+
if (!deleteResponse.ok && deleteResponse.status !== 404) {
|
|
2078
|
+
await handleApiError(
|
|
2079
|
+
deleteResponse,
|
|
2080
|
+
"delete",
|
|
2081
|
+
"worker",
|
|
2082
|
+
props.scriptName,
|
|
2083
|
+
);
|
|
2084
|
+
}
|
|
2085
|
+
},
|
|
2086
|
+
(err) =>
|
|
2087
|
+
(err.status === 400 &&
|
|
2088
|
+
err.message.includes(
|
|
2089
|
+
"is still referenced by service bindings in Workers",
|
|
2090
|
+
)) ||
|
|
2091
|
+
err.status === 500 ||
|
|
2092
|
+
err.status === 503,
|
|
2093
|
+
10,
|
|
2094
|
+
100,
|
|
2095
|
+
);
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
async function getVersionMetadata(
|
|
2099
|
+
api: CloudflareApi,
|
|
2100
|
+
scriptName: string,
|
|
2101
|
+
deploymentId: string,
|
|
2102
|
+
) {
|
|
2103
|
+
const response = await api.get(
|
|
2104
|
+
`/accounts/${api.accountId}/workers/scripts/${scriptName}/versions/${deploymentId}`,
|
|
2105
|
+
);
|
|
2106
|
+
const result = (await response.json()) as {
|
|
2107
|
+
result: {
|
|
2108
|
+
resources: {
|
|
2109
|
+
bindings: WorkerBindingSpec[];
|
|
2110
|
+
};
|
|
2111
|
+
};
|
|
2112
|
+
};
|
|
2113
|
+
return result.result;
|
|
2114
|
+
}
|