alchemy 0.44.4 → 0.45.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/drizzle/0000_busy_mauler.sql +19 -0
- package/drizzle/0001_concerned_iceman.sql +20 -0
- package/drizzle/meta/0000_snapshot.json +137 -0
- package/drizzle/meta/0001_snapshot.json +106 -0
- package/drizzle/meta/_journal.json +20 -0
- 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 +13 -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/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,161 +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(this, api, {
|
|
1346
|
-
...props,
|
|
1347
|
-
workerName,
|
|
1348
|
-
url: props.url ?? true,
|
|
1349
|
-
});
|
|
1350
|
-
}
|
|
1351
|
-
|
|
1352
|
-
// Get current timestamp
|
|
1353
|
-
const now = Date.now();
|
|
1354
|
-
|
|
1355
|
-
// Update cron triggers
|
|
1356
|
-
if (props.crons) {
|
|
1357
|
-
const res = await api.put(
|
|
1358
|
-
`/accounts/${api.accountId}/workers/scripts/${workerName}/schedules`,
|
|
1359
|
-
props.crons.map((cron) => ({ cron })),
|
|
1360
|
-
);
|
|
1361
|
-
|
|
1362
|
-
if (!res.ok) {
|
|
1363
|
-
await handleApiError(
|
|
1364
|
-
res,
|
|
1365
|
-
"updating cron triggers",
|
|
1366
|
-
"worker",
|
|
1367
|
-
workerName,
|
|
1368
|
-
);
|
|
1369
|
-
}
|
|
1370
|
-
}
|
|
1371
|
-
|
|
1372
|
-
return { scriptBundle, workerUrl, now, versionResult };
|
|
1373
1128
|
};
|
|
1374
1129
|
|
|
1375
|
-
if (this.phase === "delete") {
|
|
1376
|
-
// only delete the worker if it's not a version
|
|
1377
|
-
if (!props.version) {
|
|
1378
|
-
// Delete any queue consumers attached to this worker first
|
|
1379
|
-
await deleteQueueConsumers(api, workerName);
|
|
1380
|
-
|
|
1381
|
-
await withExponentialBackoff(
|
|
1382
|
-
() =>
|
|
1383
|
-
deleteWorker(api, {
|
|
1384
|
-
workerName,
|
|
1385
|
-
namespace:
|
|
1386
|
-
typeof props.namespace === "string"
|
|
1387
|
-
? props.namespace
|
|
1388
|
-
: props.namespace?.namespaceId,
|
|
1389
|
-
url: this.output.url,
|
|
1390
|
-
}),
|
|
1391
|
-
(err) =>
|
|
1392
|
-
(err.status === 400 &&
|
|
1393
|
-
err.message.includes(
|
|
1394
|
-
"is still referenced by service bindings in Workers",
|
|
1395
|
-
)) ||
|
|
1396
|
-
err.status === 500 ||
|
|
1397
|
-
err.status === 503,
|
|
1398
|
-
10,
|
|
1399
|
-
100,
|
|
1400
|
-
);
|
|
1401
|
-
}
|
|
1402
|
-
return this.destroy();
|
|
1403
|
-
}
|
|
1404
|
-
|
|
1405
1130
|
if (this.phase === "create") {
|
|
1406
1131
|
if (props.version) {
|
|
1407
1132
|
// When version is specified, we adopt existing workers or create them if they don't exist
|
|
1408
|
-
|
|
1409
|
-
if (!workerExists) {
|
|
1133
|
+
if (!(await workerExists(api, workerName))) {
|
|
1410
1134
|
// Create the base worker first if it doesn't exist
|
|
1411
1135
|
const baseWorkerProps = { ...props, version: undefined };
|
|
1412
|
-
await
|
|
1136
|
+
await putWorkerWithAssets(baseWorkerProps, await bundle.create());
|
|
1413
1137
|
}
|
|
1414
1138
|
// We always "adopt" when publishing versions
|
|
1415
1139
|
} else if (!props.adopt) {
|
|
@@ -1417,106 +1141,164 @@ export const _Worker = Resource(
|
|
|
1417
1141
|
}
|
|
1418
1142
|
}
|
|
1419
1143
|
|
|
1420
|
-
|
|
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
|
+
}
|
|
1421
1174
|
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
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
|
+
}),
|
|
1425
1220
|
);
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
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());
|
|
1429
1226
|
}
|
|
1430
1227
|
|
|
1431
|
-
|
|
1432
|
-
if (props.domains?.length) {
|
|
1433
|
-
ensureNoDuplicates(
|
|
1434
|
-
"Custom Domain",
|
|
1435
|
-
props.domains.map((domain) =>
|
|
1436
|
-
typeof domain === "string" ? domain : domain.domainName,
|
|
1437
|
-
),
|
|
1438
|
-
);
|
|
1228
|
+
const tasks: Promise<unknown>[] = [];
|
|
1439
1229
|
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
adopt:
|
|
1454
|
-
typeof customDomain === "string"
|
|
1455
|
-
? (props.adopt ?? false)
|
|
1456
|
-
: (customDomain.adopt ?? props.adopt),
|
|
1457
|
-
});
|
|
1458
|
-
}),
|
|
1459
|
-
);
|
|
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
|
+
}
|
|
1460
1243
|
}
|
|
1461
1244
|
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
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
|
+
}),
|
|
1469
1254
|
),
|
|
1470
1255
|
);
|
|
1471
|
-
|
|
1472
|
-
// Create Route resources for each route and capture their outputs
|
|
1473
|
-
createdRoutes = await Promise.all(
|
|
1474
|
-
props.routes.map(async (routeConfig) => {
|
|
1475
|
-
const pattern =
|
|
1476
|
-
typeof routeConfig === "string" ? routeConfig : routeConfig.pattern;
|
|
1477
|
-
return await Route(pattern, {
|
|
1478
|
-
pattern,
|
|
1479
|
-
script: workerName,
|
|
1480
|
-
zoneId:
|
|
1481
|
-
typeof routeConfig === "string" ? undefined : routeConfig.zoneId, // Route resource will handle inference if not provided
|
|
1482
|
-
adopt:
|
|
1483
|
-
typeof routeConfig === "string"
|
|
1484
|
-
? (props.adopt ?? false)
|
|
1485
|
-
: (routeConfig.adopt ?? props.adopt),
|
|
1486
|
-
accountId: props.accountId,
|
|
1487
|
-
apiKey: props.apiKey,
|
|
1488
|
-
apiToken: props.apiToken,
|
|
1489
|
-
baseUrl: props.baseUrl,
|
|
1490
|
-
email: props.email,
|
|
1491
|
-
});
|
|
1492
|
-
}),
|
|
1493
|
-
);
|
|
1494
1256
|
}
|
|
1495
1257
|
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
isDurableObjectNamespace(binding) &&
|
|
1502
|
-
binding.scriptName === undefined
|
|
1503
|
-
? new DurableObjectNamespace(binding.id, {
|
|
1504
|
-
...binding,
|
|
1505
|
-
// re-export this binding mapping to the host worker (this worker)
|
|
1506
|
-
scriptName: workerName,
|
|
1507
|
-
})
|
|
1508
|
-
: isWorkflow(binding) && binding.scriptName === undefined
|
|
1509
|
-
? new Workflow(binding.id, {
|
|
1510
|
-
...binding,
|
|
1511
|
-
// re-export this binding mapping to the host worker (this worker)
|
|
1512
|
-
scriptName: workerName,
|
|
1513
|
-
})
|
|
1514
|
-
: binding,
|
|
1515
|
-
],
|
|
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 })) ?? [],
|
|
1516
1263
|
),
|
|
1517
1264
|
);
|
|
1518
1265
|
}
|
|
1519
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
|
+
|
|
1520
1302
|
// Construct the output
|
|
1521
1303
|
return this({
|
|
1522
1304
|
...props,
|
|
@@ -1528,22 +1310,22 @@ export const _Worker = Resource(
|
|
|
1528
1310
|
compatibilityDate,
|
|
1529
1311
|
compatibilityFlags,
|
|
1530
1312
|
format: props.format || "esm", // Include format in the output
|
|
1531
|
-
bindings:
|
|
1313
|
+
bindings: normalizeExportBindings(workerName, props.bindings),
|
|
1532
1314
|
env: props.env,
|
|
1533
1315
|
observability: props.observability,
|
|
1534
|
-
createdAt: now,
|
|
1316
|
+
createdAt: this.output?.createdAt ?? now,
|
|
1535
1317
|
updatedAt: now,
|
|
1536
1318
|
eventSources: props.eventSources,
|
|
1537
|
-
url:
|
|
1319
|
+
url: subdomain?.url,
|
|
1538
1320
|
dev: props.dev,
|
|
1539
1321
|
// Include assets configuration in the output
|
|
1540
1322
|
assets: props.assets,
|
|
1541
1323
|
// Include cron triggers in the output
|
|
1542
1324
|
crons: props.crons,
|
|
1543
1325
|
// Include the created routes in the output
|
|
1544
|
-
routes
|
|
1326
|
+
routes,
|
|
1545
1327
|
// Include the created domains in the output
|
|
1546
|
-
domains
|
|
1328
|
+
domains,
|
|
1547
1329
|
// Include the dispatch namespace in the output
|
|
1548
1330
|
namespace: props.namespace,
|
|
1549
1331
|
// Include version information in the output
|
|
@@ -1554,48 +1336,442 @@ export const _Worker = Resource(
|
|
|
1554
1336
|
},
|
|
1555
1337
|
);
|
|
1556
1338
|
|
|
1557
|
-
|
|
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(
|
|
1558
1451
|
api: CloudflareApi,
|
|
1559
1452
|
props: {
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1453
|
+
scriptName: string;
|
|
1454
|
+
containers?: Container[];
|
|
1455
|
+
bindings: WorkerBindingSpec[];
|
|
1563
1456
|
},
|
|
1564
|
-
) {
|
|
1565
|
-
|
|
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
|
+
}
|
|
1566
1486
|
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
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
|
+
}),
|
|
1572
1519
|
);
|
|
1520
|
+
}
|
|
1573
1521
|
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
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;
|
|
1577
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
|
+
}
|
|
1578
1560
|
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
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
|
+
};
|
|
1591
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
|
+
});
|
|
1592
1616
|
}
|
|
1617
|
+
if (props.forceDelete) {
|
|
1618
|
+
await disableWorkerSubdomain(api, props.scriptName);
|
|
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
|
+
};
|
|
1593
1638
|
|
|
1594
|
-
|
|
1595
|
-
|
|
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
|
+
);
|
|
1770
|
+
|
|
1771
|
+
return await startPromise.value;
|
|
1596
1772
|
}
|
|
1597
1773
|
|
|
1598
|
-
function
|
|
1774
|
+
function createDevCommand(props: {
|
|
1599
1775
|
id: string;
|
|
1600
1776
|
command: string;
|
|
1601
1777
|
cwd: string;
|
|
@@ -1629,14 +1805,13 @@ function upsertDevCommand(props: {
|
|
|
1629
1805
|
},
|
|
1630
1806
|
stdio: ["inherit", "inherit", "inherit"],
|
|
1631
1807
|
});
|
|
1632
|
-
|
|
1808
|
+
cleanups.push(() => {
|
|
1633
1809
|
try {
|
|
1634
1810
|
unlinkSync(persistFile);
|
|
1635
1811
|
} catch {
|
|
1636
1812
|
// ignore
|
|
1637
1813
|
}
|
|
1638
|
-
proc.kill(
|
|
1639
|
-
process.exit(0);
|
|
1814
|
+
proc.kill();
|
|
1640
1815
|
});
|
|
1641
1816
|
if (proc.pid) {
|
|
1642
1817
|
mkdirSync(path.dirname(persistFile), { recursive: true });
|
|
@@ -1648,124 +1823,124 @@ type PutWorkerOptions = WorkerProps & {
|
|
|
1648
1823
|
dispatchNamespace?: string;
|
|
1649
1824
|
migrationTag?: string;
|
|
1650
1825
|
workerName: string;
|
|
1651
|
-
scriptBundle:
|
|
1826
|
+
scriptBundle: WorkerBundle;
|
|
1652
1827
|
version: string | undefined;
|
|
1653
1828
|
compatibilityDate: string;
|
|
1654
1829
|
compatibilityFlags: string[];
|
|
1655
|
-
assetUploadResult:
|
|
1830
|
+
assetUploadResult:
|
|
1831
|
+
| {
|
|
1832
|
+
completionToken?: string;
|
|
1833
|
+
keepAssets?: boolean;
|
|
1834
|
+
assetConfig?: AssetsConfig;
|
|
1835
|
+
}
|
|
1836
|
+
| undefined;
|
|
1837
|
+
unstable_cacheWorkerSettings?: boolean;
|
|
1656
1838
|
};
|
|
1657
1839
|
|
|
1658
|
-
|
|
1840
|
+
async function prepareWorkerUpload(
|
|
1659
1841
|
api: CloudflareApi,
|
|
1660
1842
|
props: PutWorkerOptions,
|
|
1661
|
-
)
|
|
1662
|
-
const {
|
|
1663
|
-
//
|
|
1664
|
-
dispatchNamespace,
|
|
1665
|
-
migrationTag,
|
|
1666
|
-
workerName,
|
|
1667
|
-
scriptBundle,
|
|
1668
|
-
version,
|
|
1669
|
-
} = props;
|
|
1843
|
+
) {
|
|
1670
1844
|
const scriptMetadata = await prepareWorkerMetadata(api, props);
|
|
1671
1845
|
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
const formData = new FormData();
|
|
1679
|
-
|
|
1680
|
-
function addFile(fileName: string, content: Buffer | string) {
|
|
1681
|
-
const contentType = getContentType(fileName) ?? "application/null";
|
|
1682
|
-
formData.append(
|
|
1683
|
-
fileName,
|
|
1684
|
-
new Blob([content], {
|
|
1685
|
-
type:
|
|
1686
|
-
contentType === "application/javascript" &&
|
|
1687
|
-
scriptMetadata.main_module
|
|
1688
|
-
? "application/javascript+module"
|
|
1689
|
-
: contentType,
|
|
1690
|
-
}),
|
|
1691
|
-
fileName,
|
|
1692
|
-
);
|
|
1693
|
-
}
|
|
1694
|
-
|
|
1695
|
-
if (typeof scriptBundle === "string") {
|
|
1696
|
-
addFile(scriptName, scriptBundle);
|
|
1697
|
-
} else {
|
|
1698
|
-
for (const [fileName, content] of Object.entries(scriptBundle)) {
|
|
1699
|
-
addFile(fileName, content);
|
|
1700
|
-
}
|
|
1701
|
-
}
|
|
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();
|
|
1702
1852
|
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
...scriptMetadata,
|
|
1707
|
-
// Exclude migrations for worker versions - they're not allowed
|
|
1708
|
-
migrations: undefined,
|
|
1709
|
-
annotations: {
|
|
1710
|
-
"workers/tag": version,
|
|
1711
|
-
"workers/message": `Version ${version}`,
|
|
1712
|
-
},
|
|
1713
|
-
}
|
|
1714
|
-
: {
|
|
1715
|
-
...scriptMetadata,
|
|
1716
|
-
migrations: scriptMetadata.migrations
|
|
1717
|
-
? {
|
|
1718
|
-
...scriptMetadata.migrations,
|
|
1719
|
-
old_tag: migrationTag,
|
|
1720
|
-
new_tag: bumpMigrationTagVersion(migrationTag),
|
|
1721
|
-
}
|
|
1722
|
-
: undefined,
|
|
1723
|
-
};
|
|
1853
|
+
for await (const file of props.scriptBundle.files) {
|
|
1854
|
+
body.append(file.name, file);
|
|
1855
|
+
}
|
|
1724
1856
|
|
|
1725
|
-
|
|
1726
|
-
|
|
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
|
+
},
|
|
1727
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
|
+
};
|
|
1728
1878
|
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
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",
|
|
1735
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
|
+
}
|
|
1736
1904
|
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
"Worker Preview Versions are not supported in Workers for Platforms",
|
|
1744
|
-
);
|
|
1745
|
-
}
|
|
1746
|
-
// Upload worker version using the versions API
|
|
1747
|
-
endpoint = `/accounts/${api.accountId}/workers/scripts/${workerName}/versions`;
|
|
1748
|
-
method = "POST";
|
|
1749
|
-
} else {
|
|
1750
|
-
// Upload worker script with bindings
|
|
1751
|
-
endpoint = dispatchNamespace
|
|
1752
|
-
? `/accounts/${api.accountId}/workers/dispatch/namespaces/${dispatchNamespace}/scripts/${workerName}`
|
|
1753
|
-
: `/accounts/${api.accountId}/workers/scripts/${workerName}`;
|
|
1754
|
-
method = "PUT";
|
|
1755
|
-
}
|
|
1905
|
+
return {
|
|
1906
|
+
body,
|
|
1907
|
+
endpoint,
|
|
1908
|
+
method,
|
|
1909
|
+
};
|
|
1910
|
+
}
|
|
1756
1911
|
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
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
|
+
});
|
|
1769
1944
|
|
|
1770
1945
|
// Check if the upload was successful
|
|
1771
1946
|
if (!uploadResponse.ok) {
|
|
@@ -1804,55 +1979,9 @@ export async function putWorker(
|
|
|
1804
1979
|
}
|
|
1805
1980
|
}
|
|
1806
1981
|
const responseData = (await uploadResponse.json()) as {
|
|
1807
|
-
result:
|
|
1808
|
-
id: string;
|
|
1809
|
-
number: number;
|
|
1810
|
-
metadata: {
|
|
1811
|
-
has_preview: boolean;
|
|
1812
|
-
};
|
|
1813
|
-
annotations?: {
|
|
1814
|
-
"workers/tag"?: string;
|
|
1815
|
-
};
|
|
1816
|
-
deployment_id: string;
|
|
1817
|
-
};
|
|
1818
|
-
};
|
|
1819
|
-
const result = responseData.result;
|
|
1820
|
-
|
|
1821
|
-
// Handle version response
|
|
1822
|
-
if (props.version) {
|
|
1823
|
-
// Get the account's workers.dev subdomain to construct preview URL
|
|
1824
|
-
let previewUrl: string | undefined;
|
|
1825
|
-
if (result.metadata?.has_preview) {
|
|
1826
|
-
// Need to get the subdomain
|
|
1827
|
-
const subdomainResponse = await api.get(
|
|
1828
|
-
`/accounts/${api.accountId}/workers/subdomain`,
|
|
1829
|
-
);
|
|
1830
|
-
|
|
1831
|
-
if (subdomainResponse.ok) {
|
|
1832
|
-
const subdomainData: {
|
|
1833
|
-
result: {
|
|
1834
|
-
subdomain: string;
|
|
1835
|
-
};
|
|
1836
|
-
} = await subdomainResponse.json();
|
|
1837
|
-
const subdomain = subdomainData.result?.subdomain;
|
|
1838
|
-
if (subdomain) {
|
|
1839
|
-
// Preview URL format: <FIRST_8_CHARS_OF_VERSION_ID>-<WORKER_NAME>.<SUBDOMAIN>.workers.dev
|
|
1840
|
-
const versionPrefix = result.id.substring(0, 8);
|
|
1841
|
-
previewUrl = `https://${versionPrefix}-${workerName}.${subdomain}.workers.dev`;
|
|
1842
|
-
}
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
|
|
1846
|
-
return {
|
|
1847
|
-
versionId: result.id,
|
|
1848
|
-
previewUrl,
|
|
1849
|
-
deploymentId: result.deployment_id,
|
|
1850
|
-
};
|
|
1851
|
-
}
|
|
1852
|
-
|
|
1853
|
-
return {
|
|
1854
|
-
deploymentId: result.deployment_id,
|
|
1982
|
+
result: PutWorkerResult;
|
|
1855
1983
|
};
|
|
1984
|
+
return responseData.result;
|
|
1856
1985
|
},
|
|
1857
1986
|
(err) =>
|
|
1858
1987
|
err.status === 404 ||
|
|
@@ -1867,28 +1996,25 @@ export async function putWorker(
|
|
|
1867
1996
|
);
|
|
1868
1997
|
}
|
|
1869
1998
|
|
|
1870
|
-
|
|
1871
|
-
api
|
|
1872
|
-
|
|
1873
|
-
): Promise<boolean> {
|
|
1874
|
-
const response = await api.get(
|
|
1875
|
-
`/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}`,
|
|
1876
2002
|
);
|
|
1877
|
-
return
|
|
2003
|
+
return res.status === 200;
|
|
1878
2004
|
}
|
|
1879
2005
|
|
|
1880
|
-
|
|
2006
|
+
async function assertWorkerDoesNotExist(
|
|
1881
2007
|
api: CloudflareApi,
|
|
1882
|
-
|
|
2008
|
+
scriptName: string,
|
|
1883
2009
|
) {
|
|
1884
2010
|
const response = await api.get(
|
|
1885
|
-
`/accounts/${api.accountId}/workers/scripts/${
|
|
2011
|
+
`/accounts/${api.accountId}/workers/scripts/${scriptName}`,
|
|
1886
2012
|
);
|
|
1887
2013
|
if (response.status === 404) {
|
|
1888
2014
|
return true;
|
|
1889
2015
|
}
|
|
1890
2016
|
if (response.status === 200) {
|
|
1891
|
-
const metadata = await
|
|
2017
|
+
const metadata = await getScriptMetadata(api, scriptName);
|
|
1892
2018
|
|
|
1893
2019
|
if (!metadata) {
|
|
1894
2020
|
throw new Error(
|
|
@@ -1897,7 +2023,7 @@ export async function assertWorkerDoesNotExist(
|
|
|
1897
2023
|
}
|
|
1898
2024
|
|
|
1899
2025
|
throw new Error(
|
|
1900
|
-
`Worker with name '${
|
|
2026
|
+
`Worker with name '${scriptName}' already exists. Please use a unique name.`,
|
|
1901
2027
|
);
|
|
1902
2028
|
}
|
|
1903
2029
|
throw new Error(
|
|
@@ -1905,107 +2031,84 @@ export async function assertWorkerDoesNotExist(
|
|
|
1905
2031
|
);
|
|
1906
2032
|
}
|
|
1907
2033
|
|
|
1908
|
-
|
|
1909
|
-
ctx: Context<Worker<B>> | Context<WorkerStub>,
|
|
2034
|
+
async function getScriptMetadata(
|
|
1910
2035
|
api: CloudflareApi,
|
|
1911
|
-
|
|
1912
|
-
workerName: string;
|
|
1913
|
-
url: boolean;
|
|
1914
|
-
adopt?: boolean;
|
|
1915
|
-
},
|
|
1916
|
-
) {
|
|
1917
|
-
const { workerName, url } = props;
|
|
1918
|
-
let workerUrl;
|
|
1919
|
-
if (url) {
|
|
1920
|
-
// Enable the workers.dev subdomain for this worker
|
|
1921
|
-
await api.post(
|
|
1922
|
-
`/accounts/${api.accountId}/workers/scripts/${workerName}/subdomain`,
|
|
1923
|
-
{ enabled: true, previews_enabled: true },
|
|
1924
|
-
{
|
|
1925
|
-
headers: { "Content-Type": "application/json" },
|
|
1926
|
-
},
|
|
1927
|
-
);
|
|
1928
|
-
|
|
1929
|
-
// Get the account's workers.dev subdomain
|
|
1930
|
-
const subdomain = await getAccountSubdomain(api);
|
|
1931
|
-
|
|
1932
|
-
if (subdomain) {
|
|
1933
|
-
workerUrl = `https://${workerName}.${subdomain}.workers.dev`;
|
|
1934
|
-
}
|
|
1935
|
-
} else if (
|
|
1936
|
-
url === false &&
|
|
1937
|
-
(ctx.output?.url || (ctx.phase === "create" && props.adopt))
|
|
1938
|
-
) {
|
|
1939
|
-
// Explicitly disable URL if it was previously enabled
|
|
1940
|
-
const response = await api.post(
|
|
1941
|
-
`/accounts/${api.accountId}/workers/scripts/${workerName}/subdomain`,
|
|
1942
|
-
JSON.stringify({ enabled: false }),
|
|
1943
|
-
{
|
|
1944
|
-
headers: { "Content-Type": "application/json" },
|
|
1945
|
-
},
|
|
1946
|
-
);
|
|
1947
|
-
if (!response.ok) {
|
|
1948
|
-
throw new Error(
|
|
1949
|
-
`Failed to disable worker URL: ${response.status} ${response.statusText}`,
|
|
1950
|
-
);
|
|
1951
|
-
}
|
|
1952
|
-
}
|
|
1953
|
-
return workerUrl;
|
|
1954
|
-
}
|
|
1955
|
-
|
|
1956
|
-
export async function getWorkerSubdomainConfig(
|
|
1957
|
-
api: CloudflareApi,
|
|
1958
|
-
workerName: string,
|
|
1959
|
-
) {
|
|
1960
|
-
// Query Cloudflare API to verify subdomain is disabled
|
|
1961
|
-
const subdomainResponse = await api.get(
|
|
1962
|
-
`/accounts/${api.accountId}/workers/scripts/${workerName}/subdomain`,
|
|
1963
|
-
);
|
|
1964
|
-
|
|
1965
|
-
if (subdomainResponse.status === 404) {
|
|
1966
|
-
return undefined;
|
|
1967
|
-
}
|
|
1968
|
-
|
|
1969
|
-
const subdomainData: any = await subdomainResponse.json();
|
|
1970
|
-
return subdomainData.result as {
|
|
1971
|
-
enabled: boolean;
|
|
1972
|
-
previews_enabled: boolean;
|
|
1973
|
-
};
|
|
1974
|
-
}
|
|
1975
|
-
|
|
1976
|
-
export async function getWorkerScriptMetadata(
|
|
1977
|
-
api: CloudflareApi,
|
|
1978
|
-
workerName: string,
|
|
2036
|
+
scriptName: string,
|
|
1979
2037
|
): Promise<WorkerScriptMetadata | undefined> {
|
|
1980
|
-
const
|
|
1981
|
-
`/accounts/${api.accountId}/workers/services/${
|
|
2038
|
+
const res = await api.get(
|
|
2039
|
+
`/accounts/${api.accountId}/workers/services/${scriptName}`,
|
|
1982
2040
|
);
|
|
1983
|
-
if (
|
|
1984
|
-
return
|
|
2041
|
+
if (res.status === 404) {
|
|
2042
|
+
return;
|
|
1985
2043
|
}
|
|
1986
|
-
if (!
|
|
2044
|
+
if (!res.ok) {
|
|
1987
2045
|
throw new Error(
|
|
1988
|
-
`Error getting worker script metadata: ${
|
|
2046
|
+
`Error getting worker script metadata: ${res.status} ${res.statusText}`,
|
|
1989
2047
|
);
|
|
1990
2048
|
}
|
|
1991
|
-
|
|
2049
|
+
const json = (await res.json()) as { result: WorkerScriptMetadata };
|
|
2050
|
+
return json.result;
|
|
1992
2051
|
}
|
|
1993
2052
|
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
* @param ctx Worker context containing eventSources
|
|
1997
|
-
* @param api CloudflareApi instance
|
|
1998
|
-
* @param workerName Name of the worker script
|
|
1999
|
-
*/
|
|
2000
|
-
async function deleteQueueConsumers(
|
|
2001
|
-
api: CloudflareApi,
|
|
2002
|
-
workerName: string,
|
|
2003
|
-
): Promise<void> {
|
|
2004
|
-
const consumers = await listQueueConsumersForWorker(api, workerName);
|
|
2005
|
-
|
|
2053
|
+
async function deleteQueueConsumers(api: CloudflareApi, scriptName: string) {
|
|
2054
|
+
const consumers = await listQueueConsumersForWorker(api, scriptName);
|
|
2006
2055
|
await Promise.all(
|
|
2007
2056
|
consumers.map(async (consumer) => {
|
|
2008
2057
|
await deleteQueueConsumer(api, consumer.queueId, consumer.consumerId);
|
|
2009
2058
|
}),
|
|
2010
2059
|
);
|
|
2011
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
|
+
}
|