alchemy 0.45.6 → 0.46.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/README.md +2 -2
- package/bin/alchemy.mjs +19280 -15136
- package/bin/alchemy.ts +14 -56
- package/bin/commands/create.ts +307 -137
- package/bin/commands/deploy.ts +23 -0
- package/bin/commands/destroy.ts +19 -0
- package/bin/commands/dev.ts +21 -0
- package/bin/commands/login.ts +63 -0
- package/bin/commands/run.ts +29 -0
- package/bin/services/dependencies.ts +0 -5
- package/bin/services/execute-alchemy.ts +160 -0
- package/bin/services/git.ts +27 -0
- package/bin/services/github-workflow.ts +229 -0
- package/bin/services/package-manager.ts +51 -68
- package/bin/services/template-manager.ts +10 -21
- package/bin/trpc.ts +3 -0
- package/bin/types.ts +4 -2
- package/lib/apply.d.ts +2 -0
- package/lib/apply.d.ts.map +1 -1
- package/lib/apply.js +26 -8
- package/lib/apply.js.map +1 -1
- package/lib/build-date.d.ts +1 -1
- package/lib/build-date.js +1 -1
- package/lib/cloudflare/ai.d.ts +8 -4
- package/lib/cloudflare/ai.d.ts.map +1 -1
- package/lib/cloudflare/ai.js +6 -8
- package/lib/cloudflare/ai.js.map +1 -1
- package/lib/cloudflare/analytics-engine.d.ts +11 -7
- package/lib/cloudflare/analytics-engine.d.ts.map +1 -1
- package/lib/cloudflare/analytics-engine.js +11 -9
- package/lib/cloudflare/analytics-engine.js.map +1 -1
- package/lib/cloudflare/{types.d.ts → api-response.d.ts} +6 -1
- package/lib/cloudflare/api-response.d.ts.map +1 -0
- package/lib/cloudflare/api-response.js +38 -0
- package/lib/cloudflare/api-response.js.map +1 -0
- package/lib/cloudflare/api.d.ts +9 -5
- package/lib/cloudflare/api.d.ts.map +1 -1
- package/lib/cloudflare/api.js +6 -46
- package/lib/cloudflare/api.js.map +1 -1
- package/lib/cloudflare/auth.d.ts +16 -35
- package/lib/cloudflare/auth.d.ts.map +1 -1
- package/lib/cloudflare/auth.js +50 -129
- package/lib/cloudflare/auth.js.map +1 -1
- package/lib/cloudflare/browser-rendering.d.ts +12 -3
- package/lib/cloudflare/browser-rendering.d.ts.map +1 -1
- package/lib/cloudflare/browser-rendering.js +12 -2
- package/lib/cloudflare/browser-rendering.js.map +1 -1
- package/lib/cloudflare/bundle/fs.d.ts.map +1 -1
- package/lib/cloudflare/bundle/fs.js +3 -0
- package/lib/cloudflare/bundle/fs.js.map +1 -1
- package/lib/cloudflare/bundle/internal-worker-bundle.d.ts +6 -0
- package/lib/cloudflare/bundle/internal-worker-bundle.d.ts.map +1 -0
- package/lib/cloudflare/bundle/internal-worker-bundle.js +14 -0
- package/lib/cloudflare/bundle/internal-worker-bundle.js.map +1 -0
- package/lib/cloudflare/compatibility-presets.d.ts +22 -0
- package/lib/cloudflare/compatibility-presets.d.ts.map +1 -0
- package/lib/cloudflare/compatibility-presets.js +27 -0
- package/lib/cloudflare/compatibility-presets.js.map +1 -0
- package/lib/cloudflare/container.d.ts +5 -1
- package/lib/cloudflare/container.d.ts.map +1 -1
- package/lib/cloudflare/container.js +42 -2
- package/lib/cloudflare/container.js.map +1 -1
- package/lib/cloudflare/dispatch-namespace.d.ts +5 -0
- package/lib/cloudflare/dispatch-namespace.d.ts.map +1 -1
- package/lib/cloudflare/dispatch-namespace.js +8 -0
- package/lib/cloudflare/dispatch-namespace.js.map +1 -1
- package/lib/cloudflare/durable-object-namespace.d.ts +23 -15
- package/lib/cloudflare/durable-object-namespace.d.ts.map +1 -1
- package/lib/cloudflare/durable-object-namespace.js +22 -21
- package/lib/cloudflare/durable-object-namespace.js.map +1 -1
- package/lib/cloudflare/hyperdrive.d.ts +19 -5
- package/lib/cloudflare/hyperdrive.d.ts.map +1 -1
- package/lib/cloudflare/hyperdrive.js +14 -0
- package/lib/cloudflare/hyperdrive.js.map +1 -1
- package/lib/cloudflare/images.d.ts +27 -17
- package/lib/cloudflare/images.d.ts.map +1 -1
- package/lib/cloudflare/images.js +13 -8
- package/lib/cloudflare/images.js.map +1 -1
- package/lib/cloudflare/index.d.ts +1 -3
- package/lib/cloudflare/index.d.ts.map +1 -1
- package/lib/cloudflare/index.js +1 -3
- package/lib/cloudflare/index.js.map +1 -1
- package/lib/cloudflare/miniflare/miniflare.d.ts +3 -3
- package/lib/cloudflare/miniflare/miniflare.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare.js +7 -7
- package/lib/cloudflare/miniflare/miniflare.js.map +1 -1
- package/lib/cloudflare/miniflare/{mixed-mode.d.ts → remote-binding-proxy.d.ts} +5 -5
- package/lib/cloudflare/miniflare/remote-binding-proxy.d.ts.map +1 -0
- package/lib/cloudflare/miniflare/{mixed-mode.js → remote-binding-proxy.js} +16 -52
- package/lib/cloudflare/miniflare/remote-binding-proxy.js.map +1 -0
- package/lib/cloudflare/oauth.d.ts +22 -0
- package/lib/cloudflare/oauth.d.ts.map +1 -0
- package/lib/cloudflare/oauth.js +213 -0
- package/lib/cloudflare/oauth.js.map +1 -0
- package/lib/cloudflare/state.d.ts +26 -0
- package/lib/cloudflare/state.d.ts.map +1 -0
- package/lib/cloudflare/state.js +14 -0
- package/lib/cloudflare/state.js.map +1 -0
- package/lib/cloudflare/user.d.ts +2 -2
- package/lib/cloudflare/user.d.ts.map +1 -1
- package/lib/cloudflare/user.js +24 -47
- package/lib/cloudflare/user.js.map +1 -1
- package/lib/cloudflare/vectorize-index.d.ts.map +1 -1
- package/lib/cloudflare/vectorize-index.js +5 -2
- package/lib/cloudflare/vectorize-index.js.map +1 -1
- package/lib/cloudflare/version-metadata.d.ts +15 -3
- package/lib/cloudflare/version-metadata.d.ts.map +1 -1
- package/lib/cloudflare/version-metadata.js +11 -2
- package/lib/cloudflare/version-metadata.js.map +1 -1
- package/lib/cloudflare/vite.d.ts.map +1 -1
- package/lib/cloudflare/vite.js +2 -1
- package/lib/cloudflare/vite.js.map +1 -1
- package/lib/cloudflare/worker-metadata.d.ts +13 -2
- package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
- package/lib/cloudflare/worker-metadata.js +10 -15
- package/lib/cloudflare/worker-metadata.js.map +1 -1
- package/lib/cloudflare/worker-subdomain.d.ts +7 -0
- package/lib/cloudflare/worker-subdomain.d.ts.map +1 -1
- package/lib/cloudflare/worker-subdomain.js +17 -22
- package/lib/cloudflare/worker-subdomain.js.map +1 -1
- package/lib/cloudflare/{worker/tail.d.ts → worker-tail.d.ts} +2 -2
- package/lib/cloudflare/worker-tail.d.ts.map +1 -0
- package/lib/cloudflare/{worker/tail.js → worker-tail.js} +11 -9
- package/lib/cloudflare/worker-tail.js.map +1 -0
- package/lib/cloudflare/worker.d.ts +19 -8
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +35 -10
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/cloudflare/workflow.d.ts +22 -11
- package/lib/cloudflare/workflow.d.ts.map +1 -1
- package/lib/cloudflare/workflow.js +23 -18
- package/lib/cloudflare/workflow.js.map +1 -1
- package/lib/context.d.ts +2 -2
- package/lib/context.d.ts.map +1 -1
- package/lib/docker/api.d.ts.map +1 -1
- package/lib/docker/api.js +30 -8
- package/lib/docker/api.js.map +1 -1
- package/lib/fs/file-system-state-store.d.ts +5 -20
- package/lib/fs/file-system-state-store.d.ts.map +1 -1
- package/lib/fs/file-system-state-store.js +5 -121
- package/lib/fs/file-system-state-store.js.map +1 -1
- package/lib/fs/index.d.ts +0 -1
- package/lib/fs/index.d.ts.map +1 -1
- package/lib/fs/index.js +0 -1
- package/lib/fs/index.js.map +1 -1
- package/lib/llms.cloudflare.txt +6 -5
- package/lib/planetscale/password.js +1 -1
- package/lib/planetscale/password.js.map +1 -1
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +3 -6
- package/lib/scope.js.map +1 -1
- package/lib/state/cloudflare-state-store.d.ts +34 -0
- package/lib/state/cloudflare-state-store.d.ts.map +1 -0
- package/lib/state/cloudflare-state-store.js +116 -0
- package/lib/state/cloudflare-state-store.js.map +1 -0
- package/lib/state/d1-state-store.d.ts +15 -0
- package/lib/state/d1-state-store.d.ts.map +1 -0
- package/lib/{cloudflare → state}/d1-state-store.js +31 -27
- package/lib/state/d1-state-store.js.map +1 -0
- package/lib/{cloudflare/do-state-store/types.d.ts → state/dofs-state-store/api.d.ts} +1 -1
- package/lib/state/dofs-state-store/api.d.ts.map +1 -0
- package/lib/state/dofs-state-store/api.js +1 -0
- package/lib/state/dofs-state-store/api.js.map +1 -0
- package/lib/{cloudflare/do-state-store/store.d.ts → state/dofs-state-store/index.d.ts} +10 -5
- package/lib/state/dofs-state-store/index.d.ts.map +1 -0
- package/lib/{cloudflare/do-state-store/store.js → state/dofs-state-store/index.js} +15 -11
- package/lib/state/dofs-state-store/index.js.map +1 -0
- package/lib/{cloudflare/do-state-store/internal.d.ts → state/dofs-state-store/store.d.ts} +4 -5
- package/lib/state/dofs-state-store/store.d.ts.map +1 -0
- package/lib/{cloudflare/do-state-store/internal.js → state/dofs-state-store/store.js} +7 -22
- package/lib/state/dofs-state-store/store.js.map +1 -0
- package/lib/state/file-system-state-store.d.ts +21 -0
- package/lib/state/file-system-state-store.d.ts.map +1 -0
- package/lib/state/file-system-state-store.js +122 -0
- package/lib/state/file-system-state-store.js.map +1 -0
- package/lib/state/index.d.ts +7 -0
- package/lib/state/index.d.ts.map +1 -0
- package/lib/state/index.js +7 -0
- package/lib/state/index.js.map +1 -0
- package/lib/state/migrations.d.ts +2 -0
- package/lib/state/migrations.d.ts.map +1 -0
- package/lib/state/migrations.js +3 -0
- package/lib/state/migrations.js.map +1 -0
- package/lib/state/operations.d.ts +36 -0
- package/lib/state/operations.d.ts.map +1 -0
- package/lib/state/operations.js +126 -0
- package/lib/state/operations.js.map +1 -0
- package/lib/state/proxy.d.ts +53 -0
- package/lib/state/proxy.d.ts.map +1 -0
- package/lib/state/proxy.js +65 -0
- package/lib/state/proxy.js.map +1 -0
- package/lib/{cloudflare → state}/r2-rest-state-store.d.ts +3 -1
- package/lib/state/r2-rest-state-store.d.ts.map +1 -0
- package/lib/{cloudflare → state}/r2-rest-state-store.js +6 -4
- package/lib/state/r2-rest-state-store.js.map +1 -0
- package/lib/state/schema.d.ts.map +1 -0
- package/lib/state/schema.js.map +1 -0
- package/lib/{sqlite → state}/sqlite-state-store.d.ts +5 -3
- package/lib/state/sqlite-state-store.d.ts.map +1 -0
- package/lib/{sqlite → state}/sqlite-state-store.js +15 -6
- package/lib/state/sqlite-state-store.js.map +1 -0
- package/lib/test/vitest.d.ts.map +1 -1
- package/lib/test/vitest.js +3 -6
- package/lib/test/vitest.js.map +1 -1
- package/lib/util/detect-node-runtime.d.ts +3 -0
- package/lib/util/detect-node-runtime.d.ts.map +1 -0
- package/lib/util/detect-node-runtime.js +10 -0
- package/lib/util/detect-node-runtime.js.map +1 -0
- package/lib/util/detect-package-manager.d.ts +2 -2
- package/lib/util/detect-package-manager.d.ts.map +1 -1
- package/lib/util/detect-package-manager.js +15 -5
- package/lib/util/detect-package-manager.js.map +1 -1
- package/lib/util/http-server.d.ts.map +1 -0
- package/lib/{cloudflare/miniflare → util}/http-server.js +1 -1
- package/lib/util/http-server.js.map +1 -0
- package/lib/util/memoize.d.ts +1 -0
- package/lib/util/memoize.d.ts.map +1 -1
- package/lib/util/memoize.js +2 -8
- package/lib/util/memoize.js.map +1 -1
- package/lib/util/neverthrow.d.ts +16 -0
- package/lib/util/neverthrow.d.ts.map +1 -0
- package/lib/util/neverthrow.js +46 -0
- package/lib/util/neverthrow.js.map +1 -0
- package/package.json +18 -16
- package/src/apply.ts +31 -10
- package/src/build-date.ts +1 -1
- package/src/cloudflare/ai.ts +10 -5
- package/src/cloudflare/analytics-engine.ts +20 -11
- package/src/cloudflare/{types.ts → api-response.ts} +31 -0
- package/src/cloudflare/api.ts +18 -57
- package/src/cloudflare/auth.ts +79 -211
- package/src/cloudflare/browser-rendering.ts +16 -2
- package/src/cloudflare/bundle/fs.ts +5 -0
- package/src/cloudflare/bundle/internal-worker-bundle.ts +21 -0
- package/src/cloudflare/compatibility-presets.ts +34 -0
- package/src/cloudflare/container.ts +70 -3
- package/src/cloudflare/dispatch-namespace.ts +28 -0
- package/src/cloudflare/durable-object-namespace.ts +38 -27
- package/src/cloudflare/hyperdrive.ts +19 -5
- package/src/cloudflare/images.ts +32 -17
- package/src/cloudflare/index.ts +1 -3
- package/src/cloudflare/miniflare/miniflare.ts +10 -7
- package/src/cloudflare/miniflare/{mixed-mode.ts → remote-binding-proxy.ts} +25 -75
- package/src/cloudflare/oauth.ts +300 -0
- package/src/cloudflare/state.ts +35 -0
- package/src/cloudflare/user.ts +40 -73
- package/src/cloudflare/vectorize-index.ts +7 -2
- package/src/cloudflare/version-metadata.ts +19 -2
- package/src/cloudflare/vite.ts +2 -1
- package/src/cloudflare/worker-metadata.ts +18 -43
- package/src/cloudflare/worker-subdomain.ts +43 -37
- package/src/cloudflare/{worker/tail.ts → worker-tail.ts} +13 -10
- package/src/cloudflare/worker.ts +74 -23
- package/src/cloudflare/workflow.ts +38 -19
- package/src/context.ts +2 -2
- package/src/docker/api.ts +33 -8
- package/src/fs/file-system-state-store.ts +5 -148
- package/src/fs/index.ts +0 -1
- package/src/llms.cloudflare.txt +6 -5
- package/src/planetscale/password.ts +1 -1
- package/src/scope.ts +3 -6
- package/src/state/cloudflare-state-store.ts +170 -0
- package/src/state/d1-state-store.ts +102 -0
- package/src/{cloudflare/do-state-store/store.ts → state/dofs-state-store/index.ts} +20 -13
- package/src/{cloudflare/do-state-store/internal.ts → state/dofs-state-store/store.ts} +9 -27
- package/src/state/file-system-state-store.ts +149 -0
- package/src/state/index.ts +6 -0
- package/src/state/migrations.ts +9 -0
- package/src/state/operations.ts +152 -0
- package/src/state/proxy.ts +132 -0
- package/src/{cloudflare → state}/r2-rest-state-store.ts +11 -8
- package/src/{sqlite → state}/sqlite-state-store.ts +18 -10
- package/src/test/vitest.ts +8 -6
- package/src/util/detect-node-runtime.ts +12 -0
- package/src/util/detect-package-manager.ts +19 -6
- package/src/{cloudflare/miniflare → util}/http-server.ts +1 -1
- package/src/util/memoize.ts +2 -8
- package/src/util/neverthrow.ts +64 -0
- package/templates/astro/package.json +3 -3
- package/templates/nuxt/package.json +3 -3
- package/templates/react-router/package.json +3 -3
- package/templates/rwsdk/alchemy.run.ts +1 -1
- package/templates/rwsdk/package.json +3 -3
- package/templates/sveltekit/package.json +3 -3
- package/templates/tanstack-start/package.json +3 -3
- package/templates/typescript/package.json +3 -2
- package/templates/typescript/tsconfig.json +1 -0
- package/templates/vite/package.json +3 -3
- package/workers/cloudflare-state-store.js +5638 -0
- package/workers/cloudflare-state-store.ts +108 -0
- package/workers/{do-state-store.js → dofs-state-store.js} +4 -4
- package/workers/{do-state-store.ts → dofs-state-store.ts} +12 -8
- package/workers/{mixed-mode-proxy-worker.js → remote-binding-proxy.js} +3 -3
- package/workers/remote-binding-proxy.ts +45 -0
- package/lib/cloudflare/d1-state-store.d.ts +0 -10
- package/lib/cloudflare/d1-state-store.d.ts.map +0 -1
- package/lib/cloudflare/d1-state-store.js.map +0 -1
- package/lib/cloudflare/do-state-store/index.d.ts +0 -2
- package/lib/cloudflare/do-state-store/index.d.ts.map +0 -1
- package/lib/cloudflare/do-state-store/index.js +0 -2
- package/lib/cloudflare/do-state-store/index.js.map +0 -1
- package/lib/cloudflare/do-state-store/internal.d.ts.map +0 -1
- package/lib/cloudflare/do-state-store/internal.js.map +0 -1
- package/lib/cloudflare/do-state-store/store.d.ts.map +0 -1
- package/lib/cloudflare/do-state-store/store.js.map +0 -1
- package/lib/cloudflare/do-state-store/types.d.ts.map +0 -1
- package/lib/cloudflare/do-state-store/types.js +0 -1
- package/lib/cloudflare/do-state-store/types.js.map +0 -1
- package/lib/cloudflare/miniflare/http-server.d.ts.map +0 -1
- package/lib/cloudflare/miniflare/http-server.js.map +0 -1
- package/lib/cloudflare/miniflare/mixed-mode.d.ts.map +0 -1
- package/lib/cloudflare/miniflare/mixed-mode.js.map +0 -1
- package/lib/cloudflare/r2-rest-state-store.d.ts.map +0 -1
- package/lib/cloudflare/r2-rest-state-store.js.map +0 -1
- package/lib/cloudflare/types.d.ts.map +0 -1
- package/lib/cloudflare/types.js +0 -19
- package/lib/cloudflare/types.js.map +0 -1
- package/lib/cloudflare/worker/shared.d.ts +0 -4
- package/lib/cloudflare/worker/shared.d.ts.map +0 -1
- package/lib/cloudflare/worker/shared.js +0 -21
- package/lib/cloudflare/worker/shared.js.map +0 -1
- package/lib/cloudflare/worker/tail.d.ts.map +0 -1
- package/lib/cloudflare/worker/tail.js.map +0 -1
- package/lib/sqlite/base-sqlite-state-store.d.ts +0 -31
- package/lib/sqlite/base-sqlite-state-store.d.ts.map +0 -1
- package/lib/sqlite/base-sqlite-state-store.js +0 -124
- package/lib/sqlite/base-sqlite-state-store.js.map +0 -1
- package/lib/sqlite/index.d.ts +0 -2
- package/lib/sqlite/index.d.ts.map +0 -1
- package/lib/sqlite/index.js +0 -2
- package/lib/sqlite/index.js.map +0 -1
- package/lib/sqlite/schema.d.ts.map +0 -1
- package/lib/sqlite/schema.js.map +0 -1
- package/lib/sqlite/sqlite-state-store.d.ts.map +0 -1
- package/lib/sqlite/sqlite-state-store.js.map +0 -1
- package/src/cloudflare/d1-state-store.ts +0 -105
- package/src/cloudflare/do-state-store/index.ts +0 -1
- package/src/cloudflare/worker/shared.ts +0 -30
- package/src/sqlite/base-sqlite-state-store.ts +0 -199
- package/src/sqlite/index.ts +0 -1
- package/templates/typescript/src/worker.js +0 -5
- package/workers/mixed-mode-proxy-worker.ts +0 -46
- /package/drizzle/{0000_busy_mauler.sql → default/0000_busy_mauler.sql} +0 -0
- /package/drizzle/{0001_concerned_iceman.sql → default/0001_concerned_iceman.sql} +0 -0
- /package/drizzle/{meta → default/meta}/0000_snapshot.json +0 -0
- /package/drizzle/{meta → default/meta}/0001_snapshot.json +0 -0
- /package/drizzle/{meta → default/meta}/_journal.json +0 -0
- /package/lib/{sqlite → state}/schema.d.ts +0 -0
- /package/lib/{sqlite → state}/schema.js +0 -0
- /package/lib/{cloudflare/miniflare → util}/http-server.d.ts +0 -0
- /package/src/{cloudflare/do-state-store/types.ts → state/dofs-state-store/api.ts} +0 -0
- /package/src/{sqlite → state}/schema.ts +0 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import kleur from "kleur";
|
|
2
|
+
import { err, ok, okAsync, ResultAsync } from "neverthrow";
|
|
3
|
+
import assert from "node:assert";
|
|
4
|
+
import crypto from "node:crypto";
|
|
5
|
+
import fs from "node:fs/promises";
|
|
6
|
+
import os from "node:os";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import open from "open";
|
|
9
|
+
import { HTTPServer } from "../util/http-server.ts";
|
|
10
|
+
import { memoize } from "../util/memoize.ts";
|
|
11
|
+
import {
|
|
12
|
+
detached,
|
|
13
|
+
ensure,
|
|
14
|
+
fetchJSON,
|
|
15
|
+
HTTPError,
|
|
16
|
+
singleFlight,
|
|
17
|
+
} from "../util/neverthrow.ts";
|
|
18
|
+
import { createXdgAppPaths } from "../util/xdg-paths.ts";
|
|
19
|
+
|
|
20
|
+
const CLIENT_ID = "54d11594-84e4-41aa-b438-e81b8fa78ee7";
|
|
21
|
+
const REDIRECT_URI = "http://localhost:8976/oauth/callback";
|
|
22
|
+
export const DEFAULT_SCOPES = [
|
|
23
|
+
"account:read",
|
|
24
|
+
"user:read",
|
|
25
|
+
"workers:write",
|
|
26
|
+
"workers_kv:write",
|
|
27
|
+
"workers_routes:write",
|
|
28
|
+
"workers_scripts:write",
|
|
29
|
+
"workers_tail:read",
|
|
30
|
+
"d1:write",
|
|
31
|
+
"pages:write",
|
|
32
|
+
"zone:read",
|
|
33
|
+
"ssl_certs:write",
|
|
34
|
+
"ai:write",
|
|
35
|
+
"queues:write",
|
|
36
|
+
"pipelines:write",
|
|
37
|
+
"secrets_store:write",
|
|
38
|
+
"containers:write",
|
|
39
|
+
"cloudchamber:write",
|
|
40
|
+
];
|
|
41
|
+
const ALCHEMY_BASE_URL = "https://alchemy.run";
|
|
42
|
+
|
|
43
|
+
interface WranglerConfig {
|
|
44
|
+
oauth_token: string;
|
|
45
|
+
refresh_token: string;
|
|
46
|
+
expiration_time: Date;
|
|
47
|
+
scopes: string[];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let cached: WranglerConfig | undefined;
|
|
51
|
+
|
|
52
|
+
export const getRefreshedWranglerConfig = singleFlight(() =>
|
|
53
|
+
readWranglerConfig()
|
|
54
|
+
.andThen((config) => {
|
|
55
|
+
if (config.expiration_time.getTime() > Date.now() + 10 * 1000) {
|
|
56
|
+
return ok(config);
|
|
57
|
+
}
|
|
58
|
+
return fetchToken({
|
|
59
|
+
grant_type: "refresh_token",
|
|
60
|
+
refresh_token: config.refresh_token,
|
|
61
|
+
client_id: CLIENT_ID,
|
|
62
|
+
});
|
|
63
|
+
})
|
|
64
|
+
.orElse((error) => {
|
|
65
|
+
if (isInteractive()) {
|
|
66
|
+
return wranglerLogin();
|
|
67
|
+
}
|
|
68
|
+
return err(error);
|
|
69
|
+
}),
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const getWranglerConfigPath = memoize(async () => {
|
|
73
|
+
const xdgConfigDir = createXdgAppPaths(".wrangler").config();
|
|
74
|
+
const legacyConfigDir = path.join(os.homedir(), ".wrangler");
|
|
75
|
+
const configDir = (await fs
|
|
76
|
+
.stat(legacyConfigDir)
|
|
77
|
+
.then((stat) => stat.isDirectory())
|
|
78
|
+
.catch(() => false))
|
|
79
|
+
? legacyConfigDir
|
|
80
|
+
: xdgConfigDir;
|
|
81
|
+
return path.join(configDir, "config", "default.toml");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const readWranglerConfig = () => {
|
|
85
|
+
if (cached) {
|
|
86
|
+
return okAsync(cached);
|
|
87
|
+
}
|
|
88
|
+
return ResultAsync.fromPromise(
|
|
89
|
+
getWranglerConfigPath().then(async (path): Promise<WranglerConfig> => {
|
|
90
|
+
const text = await fs.readFile(path, "utf-8");
|
|
91
|
+
const toml = await import("@iarna/toml");
|
|
92
|
+
const config = toml.parse(text.replace(/\r\n/g, "\n"));
|
|
93
|
+
assert(typeof config.oauth_token === "string");
|
|
94
|
+
assert(typeof config.refresh_token === "string");
|
|
95
|
+
assert(config.expiration_time instanceof Date);
|
|
96
|
+
assert(Array.isArray(config.scopes));
|
|
97
|
+
return {
|
|
98
|
+
oauth_token: config.oauth_token,
|
|
99
|
+
refresh_token: config.refresh_token,
|
|
100
|
+
expiration_time: new Date(config.expiration_time),
|
|
101
|
+
scopes: config.scopes as string[],
|
|
102
|
+
};
|
|
103
|
+
}),
|
|
104
|
+
() => new Error("Cloudflare credentials are missing or invalid."),
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const writeWranglerConfig = (config: WranglerConfig) => {
|
|
109
|
+
cached = config;
|
|
110
|
+
return ResultAsync.fromSafePromise(getWranglerConfigPath()).map(
|
|
111
|
+
async (configPath) => {
|
|
112
|
+
const toml = await import("@iarna/toml");
|
|
113
|
+
await fs.writeFile(
|
|
114
|
+
configPath,
|
|
115
|
+
toml.stringify({
|
|
116
|
+
oauth_token: config.oauth_token,
|
|
117
|
+
refresh_token: config.refresh_token,
|
|
118
|
+
expiration_time: config.expiration_time,
|
|
119
|
+
scopes: config.scopes,
|
|
120
|
+
}),
|
|
121
|
+
);
|
|
122
|
+
},
|
|
123
|
+
);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export const wranglerLogin = (
|
|
127
|
+
scopes: string[] = DEFAULT_SCOPES,
|
|
128
|
+
log: (message: string) => void = console.log, // using console.log instead of logger.log to avoid bundling hell with CLI
|
|
129
|
+
) => {
|
|
130
|
+
const challenge = generateAuthorizationURL(scopes);
|
|
131
|
+
log(
|
|
132
|
+
[
|
|
133
|
+
"Opening browser to authorize with Cloudflare...",
|
|
134
|
+
"",
|
|
135
|
+
kleur.gray(
|
|
136
|
+
"If you are not automatically redirected, please open the following URL in your browser:",
|
|
137
|
+
),
|
|
138
|
+
challenge.url,
|
|
139
|
+
].join("\n"),
|
|
140
|
+
);
|
|
141
|
+
open(challenge.url);
|
|
142
|
+
const { result, ok, err } = detached<WranglerConfig, OAuthError>();
|
|
143
|
+
const renderResponse = async (type: "success" | "error") => {
|
|
144
|
+
return Response.redirect(`${ALCHEMY_BASE_URL}/auth/${type}`);
|
|
145
|
+
};
|
|
146
|
+
const server = new HTTPServer({
|
|
147
|
+
port: 8976,
|
|
148
|
+
fetch: async (request) => {
|
|
149
|
+
const url = new URL(request.url);
|
|
150
|
+
if (url.pathname !== "/oauth/callback") {
|
|
151
|
+
return new Response("Not found", { status: 404 });
|
|
152
|
+
}
|
|
153
|
+
const error = url.searchParams.get("error");
|
|
154
|
+
const error_description = url.searchParams.get("error_description");
|
|
155
|
+
const code = url.searchParams.get("code");
|
|
156
|
+
const state = url.searchParams.get("state");
|
|
157
|
+
if (error) {
|
|
158
|
+
err(
|
|
159
|
+
new OAuthError({
|
|
160
|
+
error,
|
|
161
|
+
error_description: error_description ?? "Unknown error",
|
|
162
|
+
status_code: 400,
|
|
163
|
+
}),
|
|
164
|
+
);
|
|
165
|
+
return renderResponse("error");
|
|
166
|
+
}
|
|
167
|
+
if (!code || !state || state !== challenge.state) {
|
|
168
|
+
err(
|
|
169
|
+
new OAuthError({
|
|
170
|
+
error: "invalid_request",
|
|
171
|
+
error_description: "Invalid request",
|
|
172
|
+
status_code: 400,
|
|
173
|
+
}),
|
|
174
|
+
);
|
|
175
|
+
return renderResponse("error");
|
|
176
|
+
}
|
|
177
|
+
const tokens = await fetchToken({
|
|
178
|
+
grant_type: "authorization_code",
|
|
179
|
+
code,
|
|
180
|
+
code_verifier: challenge.verifier,
|
|
181
|
+
client_id: CLIENT_ID,
|
|
182
|
+
redirect_uri: REDIRECT_URI,
|
|
183
|
+
});
|
|
184
|
+
if (tokens.isErr()) {
|
|
185
|
+
err(tokens.error);
|
|
186
|
+
return renderResponse("error");
|
|
187
|
+
}
|
|
188
|
+
ok(tokens.value);
|
|
189
|
+
return renderResponse("success");
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
const timeout = setTimeout(
|
|
193
|
+
() => {
|
|
194
|
+
err(
|
|
195
|
+
new OAuthError({
|
|
196
|
+
error: "timeout",
|
|
197
|
+
error_description: "Authorization timed out after 5 minutes",
|
|
198
|
+
status_code: 408,
|
|
199
|
+
}),
|
|
200
|
+
);
|
|
201
|
+
},
|
|
202
|
+
1000 * 60 * 5,
|
|
203
|
+
);
|
|
204
|
+
return ensure(result, () => {
|
|
205
|
+
clearTimeout(timeout);
|
|
206
|
+
void server.stop();
|
|
207
|
+
});
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const generateAuthorizationURL = (scopes: string[]) => {
|
|
211
|
+
const state = crypto.randomBytes(32).toString("base64url");
|
|
212
|
+
const verifier = crypto.randomBytes(96).toString("base64url");
|
|
213
|
+
const challenge = crypto
|
|
214
|
+
.createHash("sha256")
|
|
215
|
+
.update(verifier)
|
|
216
|
+
.digest("base64url");
|
|
217
|
+
const url = new URL("https://dash.cloudflare.com/oauth2/auth");
|
|
218
|
+
url.search = new URLSearchParams({
|
|
219
|
+
response_type: "code",
|
|
220
|
+
client_id: CLIENT_ID,
|
|
221
|
+
redirect_uri: "http://localhost:8976/oauth/callback",
|
|
222
|
+
scope: [...scopes, "offline_access"].join(" "),
|
|
223
|
+
state,
|
|
224
|
+
code_challenge: challenge,
|
|
225
|
+
code_challenge_method: "S256",
|
|
226
|
+
}).toString();
|
|
227
|
+
return { url: url.toString(), state, verifier };
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
interface OAuthTokens {
|
|
231
|
+
access_token: string;
|
|
232
|
+
refresh_token: string;
|
|
233
|
+
expires_in: number;
|
|
234
|
+
scope: string;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
interface OAuthErrorParams {
|
|
238
|
+
error: string;
|
|
239
|
+
error_description: string;
|
|
240
|
+
error_verbose?: string;
|
|
241
|
+
error_hint?: string;
|
|
242
|
+
status_code: number;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
class OAuthError extends Error {
|
|
246
|
+
constructor(params: OAuthErrorParams) {
|
|
247
|
+
super(
|
|
248
|
+
`Cloudflare authentication failed with error ${params.error} (${params.status_code}): ${params.error_description}`,
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const fetchToken = (
|
|
254
|
+
body:
|
|
255
|
+
| {
|
|
256
|
+
grant_type: "refresh_token";
|
|
257
|
+
refresh_token: string;
|
|
258
|
+
client_id: string;
|
|
259
|
+
}
|
|
260
|
+
| {
|
|
261
|
+
grant_type: "authorization_code";
|
|
262
|
+
code: string;
|
|
263
|
+
code_verifier: string;
|
|
264
|
+
client_id: string;
|
|
265
|
+
redirect_uri: string;
|
|
266
|
+
},
|
|
267
|
+
) => {
|
|
268
|
+
return fetchJSON<OAuthTokens, OAuthErrorParams>(
|
|
269
|
+
"https://dash.cloudflare.com/oauth2/token",
|
|
270
|
+
{
|
|
271
|
+
method: "POST",
|
|
272
|
+
headers: {
|
|
273
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
274
|
+
},
|
|
275
|
+
body: new URLSearchParams(body),
|
|
276
|
+
},
|
|
277
|
+
)
|
|
278
|
+
.map(
|
|
279
|
+
(tokens): WranglerConfig => ({
|
|
280
|
+
oauth_token: tokens.access_token,
|
|
281
|
+
refresh_token: tokens.refresh_token,
|
|
282
|
+
expiration_time: new Date(Date.now() + tokens.expires_in * 1000),
|
|
283
|
+
scopes: tokens.scope.split(" "),
|
|
284
|
+
}),
|
|
285
|
+
)
|
|
286
|
+
.mapErr((error) =>
|
|
287
|
+
error instanceof HTTPError
|
|
288
|
+
? new OAuthError({
|
|
289
|
+
error: "http_error",
|
|
290
|
+
error_description: error.message,
|
|
291
|
+
status_code: error.status,
|
|
292
|
+
})
|
|
293
|
+
: new OAuthError(error),
|
|
294
|
+
)
|
|
295
|
+
.andTee((config) => writeWranglerConfig(config));
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
const isInteractive = () => {
|
|
299
|
+
return process.stdin.isTTY && process.stdout.isTTY && !process.env.CI;
|
|
300
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
D1StateStore as _D1StateStore,
|
|
3
|
+
DOFSStateStore as _DOFSStateStore,
|
|
4
|
+
R2RestStateStore as _R2RestStateStore,
|
|
5
|
+
} from "../state/index.ts";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated Use `R2RestStateStore` from `alchemy/state` instead.
|
|
9
|
+
*/
|
|
10
|
+
export const R2RestStateStore = _R2RestStateStore;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @deprecated Use `R2RestStateStore` from `alchemy/state` instead.
|
|
14
|
+
*/
|
|
15
|
+
export type R2RestStateStore = _R2RestStateStore;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated This state store is no longer recommended for production use. Please use {@link https://alchemy.run/guides/cloudflare-state-store/ CloudflareStateStore} from `alchemy/state` instead.
|
|
19
|
+
*/
|
|
20
|
+
export const DOStateStore = _DOFSStateStore;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated Use `DOStateStore` from `alchemy/state` instead.
|
|
24
|
+
*/
|
|
25
|
+
export type DOStateStore = _DOFSStateStore;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @deprecated Use `D1StateStore` from `alchemy/state` instead.
|
|
29
|
+
*/
|
|
30
|
+
export const D1StateStore = _D1StateStore;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @deprecated Use `D1StateStore` from `alchemy/state` instead.
|
|
34
|
+
*/
|
|
35
|
+
export type D1StateStore = _D1StateStore;
|
package/src/cloudflare/user.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Secret } from "../secret.ts";
|
|
2
2
|
import { logger } from "../util/logger.ts";
|
|
3
|
-
import {
|
|
3
|
+
import { memoize } from "../util/memoize.ts";
|
|
4
|
+
import { extractCloudflareResult } from "./api-response.ts";
|
|
4
5
|
import {
|
|
5
6
|
getCloudflareAuthHeaders,
|
|
6
7
|
type CloudflareAuthOptions,
|
|
@@ -55,82 +56,48 @@ export interface CloudflareOrganization {
|
|
|
55
56
|
roles: string[];
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
email: options.email,
|
|
67
|
-
});
|
|
68
|
-
if (accountCache[cacheKey]) {
|
|
69
|
-
return accountCache[cacheKey];
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const headers = await getCloudflareAuthHeaders(options);
|
|
73
|
-
const accounts = await fetch(
|
|
74
|
-
"https://api.cloudflare.com/client/v4/accounts",
|
|
75
|
-
{
|
|
76
|
-
headers,
|
|
77
|
-
},
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
if (accounts.ok) {
|
|
81
|
-
return (accountCache[cacheKey] ??= ((await accounts.json()) as any).result);
|
|
82
|
-
} else {
|
|
83
|
-
throw new CloudflareApiError(
|
|
84
|
-
`Failed to get accounts for authorized user, please make sure you're authenticated (see: https://alchemy.run/guides/cloudflare/) or explicitly set the Cloudflare Account ID (see: https://alchemy.run/guides/cloudflare/#account-id)`,
|
|
85
|
-
accounts,
|
|
59
|
+
export const getCloudflareAccountId = memoize(
|
|
60
|
+
async (options: CloudflareAuthOptions): Promise<string> => {
|
|
61
|
+
const headers = await getCloudflareAuthHeaders(options);
|
|
62
|
+
const accounts = await extractCloudflareResult<CloudflareAccount[]>(
|
|
63
|
+
"get accounts for authorized user",
|
|
64
|
+
fetch("https://api.cloudflare.com/client/v4/accounts", {
|
|
65
|
+
headers,
|
|
66
|
+
}),
|
|
86
67
|
);
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const emailCache: Record<string, string> = {};
|
|
91
|
-
|
|
92
|
-
export async function getUserEmailFromApiKey(apiKey: string): Promise<string> {
|
|
93
|
-
if (emailCache[apiKey]) {
|
|
94
|
-
return emailCache[apiKey];
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
try {
|
|
98
|
-
const baseUrl = "https://api.cloudflare.com/client/v4";
|
|
99
|
-
|
|
100
|
-
// Call the /user endpoint to get user information
|
|
101
|
-
const response = await fetch(`${baseUrl}/user`, {
|
|
102
|
-
headers: {
|
|
103
|
-
"Content-Type": "application/json",
|
|
104
|
-
"X-Auth-Key": apiKey,
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
if (!response.ok) {
|
|
68
|
+
if (!accounts[0]) {
|
|
109
69
|
throw new Error(
|
|
110
|
-
|
|
70
|
+
"No accounts found for authorized user. Please make sure you're authenticated (see: https://alchemy.run/guides/cloudflare/) or explicitly set the Cloudflare Account ID (see: https://alchemy.run/guides/cloudflare/#account-id)",
|
|
111
71
|
);
|
|
112
72
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
};
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
if (!data.success || !data.result || !data.result.email) {
|
|
125
|
-
throw new Error("Cloudflare API did not return valid user information");
|
|
73
|
+
if (accounts.length > 1) {
|
|
74
|
+
logger.warnOnce(
|
|
75
|
+
[
|
|
76
|
+
"Multiple Cloudflare accounts found for authorized user:",
|
|
77
|
+
accounts.map((a, i) => `${i + 1}: ${a.name} (${a.id})`).join("\n"),
|
|
78
|
+
"The first account will be used by default. To use a different account, explicitly set the Cloudflare Account ID (see: https://alchemy.run/guides/cloudflare/#account-id)",
|
|
79
|
+
].join("\n"),
|
|
80
|
+
);
|
|
126
81
|
}
|
|
82
|
+
return accounts[0].id;
|
|
83
|
+
},
|
|
84
|
+
);
|
|
127
85
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
86
|
+
export const getUserEmailFromApiKey = memoize(
|
|
87
|
+
async (apiKey: string): Promise<string> => {
|
|
88
|
+
const result = await extractCloudflareResult<{
|
|
89
|
+
id: string;
|
|
90
|
+
name: string;
|
|
91
|
+
email: string;
|
|
92
|
+
}>(
|
|
93
|
+
"automatically discover email for API Key authentication",
|
|
94
|
+
fetch("https://api.cloudflare.com/client/v4/user", {
|
|
95
|
+
headers: {
|
|
96
|
+
"Content-Type": "application/json",
|
|
97
|
+
"X-Auth-Key": apiKey,
|
|
98
|
+
},
|
|
99
|
+
}),
|
|
134
100
|
);
|
|
135
|
-
|
|
136
|
-
}
|
|
101
|
+
return result.email;
|
|
102
|
+
},
|
|
103
|
+
);
|
|
@@ -169,7 +169,7 @@ const _VectorizeIndex = Resource(
|
|
|
169
169
|
if (
|
|
170
170
|
props.adopt &&
|
|
171
171
|
error instanceof CloudflareApiError &&
|
|
172
|
-
error.message.includes("
|
|
172
|
+
error.message.includes("vectorize.index.duplicate_name")
|
|
173
173
|
) {
|
|
174
174
|
logger.log(`Index ${indexName} already exists, adopting it`);
|
|
175
175
|
// Find the existing index
|
|
@@ -321,7 +321,12 @@ export async function deleteIndex(
|
|
|
321
321
|
`/accounts/${api.accountId}/vectorize/v2/indexes/${indexName}`,
|
|
322
322
|
);
|
|
323
323
|
|
|
324
|
-
if (
|
|
324
|
+
if (
|
|
325
|
+
!deleteResponse.ok &&
|
|
326
|
+
// not 404 (Not Found) or 410 (Gone)
|
|
327
|
+
deleteResponse.status !== 404 &&
|
|
328
|
+
deleteResponse.status !== 410
|
|
329
|
+
) {
|
|
325
330
|
const errorData: any = await deleteResponse.json().catch(() => ({
|
|
326
331
|
errors: [{ message: deleteResponse.statusText }],
|
|
327
332
|
}));
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Type representing a version metadata binding.
|
|
2
3
|
* @see https://developers.cloudflare.com/workers/runtime-apis/bindings/version-metadata/
|
|
3
4
|
*/
|
|
4
|
-
export
|
|
5
|
-
|
|
5
|
+
export type VersionMetadata = {
|
|
6
|
+
type: "version_metadata";
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates a version metadata binding that provides access to version information at runtime.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const metadata = VersionMetadata();
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @see https://developers.cloudflare.com/workers/runtime-apis/bindings/version-metadata/
|
|
18
|
+
*/
|
|
19
|
+
export function VersionMetadata(): VersionMetadata {
|
|
20
|
+
return {
|
|
21
|
+
type: "version_metadata",
|
|
22
|
+
};
|
|
6
23
|
}
|
package/src/cloudflare/vite.ts
CHANGED
|
@@ -18,12 +18,13 @@ export async function Vite<B extends Bindings>(
|
|
|
18
18
|
props: ViteProps<B>,
|
|
19
19
|
): Promise<Vite<B>> {
|
|
20
20
|
const defaultAssets = path.join("dist", "client");
|
|
21
|
-
const packageManager = detectPackageManager();
|
|
21
|
+
const packageManager = await detectPackageManager();
|
|
22
22
|
const devCommand = {
|
|
23
23
|
npm: "npx vite dev",
|
|
24
24
|
bun: "bun vite dev",
|
|
25
25
|
pnpm: "pnpm vite dev",
|
|
26
26
|
yarn: "yarn vite dev",
|
|
27
|
+
deno: "deno vite dev",
|
|
27
28
|
}[packageManager];
|
|
28
29
|
return Website(id, {
|
|
29
30
|
...props,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { assertNever } from "../util/assert-never.ts";
|
|
2
2
|
import { logger } from "../util/logger.ts";
|
|
3
3
|
import { memoize } from "../util/memoize.ts";
|
|
4
|
+
import { extractCloudflareResult } from "./api-response.ts";
|
|
4
5
|
import type { CloudflareApi } from "./api.ts";
|
|
5
6
|
import {
|
|
6
7
|
Self,
|
|
@@ -200,7 +201,7 @@ export interface WorkerMetadata {
|
|
|
200
201
|
|
|
201
202
|
export async function prepareWorkerMetadata(
|
|
202
203
|
api: CloudflareApi,
|
|
203
|
-
props: WorkerProps & {
|
|
204
|
+
props: Omit<WorkerProps, "entrypoint"> & {
|
|
204
205
|
compatibilityDate: string;
|
|
205
206
|
compatibilityFlags: string[];
|
|
206
207
|
workerName: string;
|
|
@@ -210,6 +211,7 @@ export async function prepareWorkerMetadata(
|
|
|
210
211
|
keepAssets?: boolean;
|
|
211
212
|
assetConfig?: AssetsConfig;
|
|
212
213
|
};
|
|
214
|
+
tags?: string[];
|
|
213
215
|
unstable_cacheWorkerSettings?: boolean;
|
|
214
216
|
},
|
|
215
217
|
): Promise<WorkerMetadata> {
|
|
@@ -226,7 +228,7 @@ export async function prepareWorkerMetadata(
|
|
|
226
228
|
// we use Cloudflare Worker tags to store a mapping between Alchemy's stable identifier and the binding name
|
|
227
229
|
// e.g.
|
|
228
230
|
// {
|
|
229
|
-
// BINDING_NAME:
|
|
231
|
+
// BINDING_NAME: DurableObjectNamespace("stable-id")
|
|
230
232
|
// }
|
|
231
233
|
// will be stored as alchemy:do:stable-id:BINDING_NAME
|
|
232
234
|
// TODO(sam): should we base64 encode to ensure no `:` collision risk?
|
|
@@ -323,6 +325,7 @@ export async function prepareWorkerMetadata(
|
|
|
323
325
|
),
|
|
324
326
|
// encode the migraiton tag if there is one so we can avoid the failed PutWorker after adoption
|
|
325
327
|
...(newMigrationTag ? [`alchemy:migration-tag:${newMigrationTag}`] : []),
|
|
328
|
+
...(props.tags ?? []),
|
|
326
329
|
],
|
|
327
330
|
migrations: {
|
|
328
331
|
old_tag: oldMigrationTag,
|
|
@@ -640,6 +643,7 @@ interface WorkerSettings {
|
|
|
640
643
|
compatibility_date: string;
|
|
641
644
|
compatibility_flags: string[];
|
|
642
645
|
migrations: SingleStepMigration | MultiStepMigration;
|
|
646
|
+
tags: string[];
|
|
643
647
|
[key: string]: any;
|
|
644
648
|
}
|
|
645
649
|
|
|
@@ -648,51 +652,22 @@ const getWorkerSettingsWithCache = memoize(
|
|
|
648
652
|
(api, workerName) => `${api.accountId}:${workerName}`,
|
|
649
653
|
);
|
|
650
654
|
|
|
651
|
-
async function getWorkerSettings(
|
|
655
|
+
export async function getWorkerSettings(
|
|
652
656
|
api: CloudflareApi,
|
|
653
657
|
workerName: string,
|
|
654
658
|
): Promise<WorkerSettings | undefined> {
|
|
655
659
|
// Fetch the bindings for a worker by calling the Cloudflare API endpoint:
|
|
656
660
|
// GET /accounts/:account_id/workers/scripts/:script_name/bindings
|
|
657
661
|
// See: https://developers.cloudflare.com/api/resources/workers/subresources/scripts/subresources/script_and_version_settings/methods/get/
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
}
|
|
669
|
-
// The result is an object with a "result" property containing the bindings array
|
|
670
|
-
const { result, success, errors } = (await response.json()) as {
|
|
671
|
-
result: {
|
|
672
|
-
bindings: WorkerBindingSpec[];
|
|
673
|
-
compatibility_date: string;
|
|
674
|
-
compatibility_flags: string[];
|
|
675
|
-
migrations: SingleStepMigration | MultiStepMigration;
|
|
676
|
-
[key: string]: any;
|
|
677
|
-
};
|
|
678
|
-
success: boolean;
|
|
679
|
-
errors: Array<{
|
|
680
|
-
code: number;
|
|
681
|
-
message: string;
|
|
682
|
-
documentation_url: string;
|
|
683
|
-
[key: string]: any;
|
|
684
|
-
}>;
|
|
685
|
-
messages: Array<{
|
|
686
|
-
code: number;
|
|
687
|
-
message: string;
|
|
688
|
-
documentation_url: string;
|
|
689
|
-
[key: string]: any;
|
|
690
|
-
}>;
|
|
691
|
-
};
|
|
692
|
-
if (!success) {
|
|
693
|
-
throw new Error(
|
|
694
|
-
`Error getting worker bindings: ${response.status} ${response.statusText}\nErrors:\n${errors.map((e) => `- [${e.code}] ${e.message} (${e.documentation_url})`).join("\n")}`,
|
|
695
|
-
);
|
|
696
|
-
}
|
|
697
|
-
return result;
|
|
662
|
+
return await extractCloudflareResult<WorkerSettings>(
|
|
663
|
+
`get worker settings for ${workerName}`,
|
|
664
|
+
api.get(
|
|
665
|
+
`/accounts/${api.accountId}/workers/scripts/${workerName}/settings`,
|
|
666
|
+
),
|
|
667
|
+
).catch((error) => {
|
|
668
|
+
if (error.status === 404) {
|
|
669
|
+
return undefined;
|
|
670
|
+
}
|
|
671
|
+
throw error;
|
|
672
|
+
});
|
|
698
673
|
}
|