alchemy 0.45.6 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/bin/alchemy.mjs +19285 -15137
- 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 +66 -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/auth-wrangler.d.ts +25 -0
- package/lib/cloudflare/auth-wrangler.d.ts.map +1 -0
- package/lib/cloudflare/auth-wrangler.js +224 -0
- package/lib/cloudflare/auth-wrangler.js.map +1 -0
- package/lib/cloudflare/auth.d.ts.map +1 -1
- package/lib/cloudflare/auth.js +7 -116
- 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/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 +7 -21
- 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 +18 -8
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +31 -7
- 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 +2 -0
- package/lib/util/memoize.d.ts.map +1 -1
- package/lib/util/memoize.js +14 -7
- package/lib/util/memoize.js.map +1 -1
- package/lib/util/neverthrow.d.ts +9 -0
- package/lib/util/neverthrow.d.ts.map +1 -0
- package/lib/util/neverthrow.js +29 -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/auth-wrangler.ts +314 -0
- package/src/cloudflare/auth.ts +8 -156
- 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/state.ts +35 -0
- package/src/cloudflare/user.ts +55 -70
- 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 +65 -19
- 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 +18 -7
- package/src/util/neverthrow.ts +36 -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
package/package.json
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alchemy",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"module": "./lib/index.js",
|
|
3
|
+
"version": "0.46.0",
|
|
6
4
|
"license": "Apache-2.0",
|
|
5
|
+
"author": "Sam Goodwin <sam@alchemy.run>",
|
|
6
|
+
"homepage": "https://alchemy.run",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git+https://github.com/sam-goodwin/alchemy.git",
|
|
10
10
|
"directory": "alchemy"
|
|
11
11
|
},
|
|
12
|
+
"type": "module",
|
|
13
|
+
"module": "./lib/index.js",
|
|
14
|
+
"bin": {
|
|
15
|
+
"alchemy": "bin/alchemy.mjs"
|
|
16
|
+
},
|
|
12
17
|
"scripts": {
|
|
13
18
|
"build:cli": "bun ./scripts/bundle-cli.ts",
|
|
14
19
|
"build:workers": "bun ./scripts/build-workers.ts",
|
|
15
20
|
"build": "rm -rf ./*.tsbuildinfo && rm -rf ./lib && tsc -b && bun run build:cli && bun run build:workers",
|
|
16
|
-
"
|
|
21
|
+
"drizzle:generate": "bun run scripts/drizzle-generate.ts",
|
|
17
22
|
"docs:gen": "rm -rf ./docs && typedoc",
|
|
18
23
|
"postbuild": "cpx 'src/**/*/types.d.ts' lib && cpx 'src/**/*.txt' lib",
|
|
19
24
|
"publish:npm": "cp ../README.md . && bun run build && bun run build:cli && npm publish && rm README.md"
|
|
20
25
|
},
|
|
21
|
-
"bin": {
|
|
22
|
-
"alchemy": "bin/alchemy.mjs"
|
|
23
|
-
},
|
|
24
|
-
"author": "Sam Goodwin <sam@alchemy.run>",
|
|
25
|
-
"homepage": "https://alchemy.run",
|
|
26
26
|
"files": [
|
|
27
27
|
"bin",
|
|
28
|
-
"drizzle",
|
|
28
|
+
"drizzle/default",
|
|
29
29
|
"lib",
|
|
30
30
|
"src",
|
|
31
31
|
"templates",
|
|
@@ -112,9 +112,9 @@
|
|
|
112
112
|
"bun": "./src/web/shadcn.ts",
|
|
113
113
|
"import": "./lib/web/shadcn.js"
|
|
114
114
|
},
|
|
115
|
-
"./
|
|
116
|
-
"bun": "./src/
|
|
117
|
-
"import": "./lib/
|
|
115
|
+
"./state": {
|
|
116
|
+
"bun": "./src/state/index.ts",
|
|
117
|
+
"import": "./lib/state/index.js"
|
|
118
118
|
},
|
|
119
119
|
"./web/astro": {
|
|
120
120
|
"bun": "./src/web/astro.ts",
|
|
@@ -149,6 +149,8 @@
|
|
|
149
149
|
"kleur": "^4.1.5",
|
|
150
150
|
"libsodium-wrappers": "^0.7.15",
|
|
151
151
|
"miniflare": "^4.20250617.4",
|
|
152
|
+
"neverthrow": "^8.2.0",
|
|
153
|
+
"open": "^10.1.2",
|
|
152
154
|
"pathe": "^2.0.3",
|
|
153
155
|
"turndown": "^7.0.0",
|
|
154
156
|
"unenv": "2.0.0-rc.15",
|
|
@@ -174,10 +176,11 @@
|
|
|
174
176
|
"arktype": "^2.0.0",
|
|
175
177
|
"cloudflare": "^4.0.0",
|
|
176
178
|
"drizzle-orm": "^0.44.2",
|
|
179
|
+
"execa": "^9.6.0",
|
|
177
180
|
"hono": "^4.0.0",
|
|
178
181
|
"prettier": "^3.0.0",
|
|
179
182
|
"stripe": "^17.0.0",
|
|
180
|
-
"zod": "^
|
|
183
|
+
"zod": "^4.0.5"
|
|
181
184
|
},
|
|
182
185
|
"devDependencies": {
|
|
183
186
|
"@ai-sdk/anthropic": "^1.1.6",
|
|
@@ -206,7 +209,6 @@
|
|
|
206
209
|
"cpx": "^1.5.0",
|
|
207
210
|
"dofs": "^0.1.0",
|
|
208
211
|
"drizzle-kit": "^0.31.4",
|
|
209
|
-
"execa": "^9.6.0",
|
|
210
212
|
"fs-extra": "^11.3.0",
|
|
211
213
|
"globby": "^14.1.0",
|
|
212
214
|
"libsodium-wrappers": "^0.7.15",
|
|
@@ -214,7 +216,7 @@
|
|
|
214
216
|
"openpgp": "^6.1.0",
|
|
215
217
|
"picocolors": "^1.1.1",
|
|
216
218
|
"prettier": "^3.5.3",
|
|
217
|
-
"trpc-cli": "^0.
|
|
219
|
+
"trpc-cli": "^0.10.0",
|
|
218
220
|
"turndown": "^7.2.0",
|
|
219
221
|
"typedoc": "^0.28.1",
|
|
220
222
|
"typedoc-plugin-markdown": "^4.6.0",
|
package/src/apply.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { alchemy } from "./alchemy.ts";
|
|
2
2
|
import { context } from "./context.ts";
|
|
3
|
+
import { destroy } from "./destroy.ts";
|
|
3
4
|
import {
|
|
4
5
|
PROVIDERS,
|
|
5
6
|
ResourceFQN,
|
|
@@ -33,7 +34,14 @@ export function apply<Out extends Resource>(
|
|
|
33
34
|
return _apply(resource, props, options);
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
export class ReplacedSignal extends Error {
|
|
37
|
+
export class ReplacedSignal extends Error {
|
|
38
|
+
public force: boolean;
|
|
39
|
+
|
|
40
|
+
constructor(force?: boolean) {
|
|
41
|
+
super();
|
|
42
|
+
this.force = force ?? false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
37
45
|
|
|
38
46
|
async function _apply<Out extends Resource>(
|
|
39
47
|
resource: PendingResource<Out>,
|
|
@@ -165,7 +173,7 @@ async function _apply<Out extends Resource>(
|
|
|
165
173
|
props: state.oldProps,
|
|
166
174
|
state,
|
|
167
175
|
isReplacement: false,
|
|
168
|
-
replace: () => {
|
|
176
|
+
replace: async (force?: boolean) => {
|
|
169
177
|
if (phase === "create") {
|
|
170
178
|
throw new Error(
|
|
171
179
|
`Resource ${resource[ResourceKind]} ${resource[ResourceFQN]} cannot be replaced in create phase.`,
|
|
@@ -177,8 +185,19 @@ async function _apply<Out extends Resource>(
|
|
|
177
185
|
);
|
|
178
186
|
}
|
|
179
187
|
|
|
188
|
+
if (force) {
|
|
189
|
+
await destroy(resource, {
|
|
190
|
+
quiet: scope.quiet,
|
|
191
|
+
strategy: "sequential",
|
|
192
|
+
replace: {
|
|
193
|
+
props: state.oldProps,
|
|
194
|
+
output: resource,
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
180
199
|
isReplaced = true;
|
|
181
|
-
throw new ReplacedSignal();
|
|
200
|
+
throw new ReplacedSignal(force);
|
|
182
201
|
},
|
|
183
202
|
});
|
|
184
203
|
|
|
@@ -227,13 +246,15 @@ async function _apply<Out extends Resource>(
|
|
|
227
246
|
)(resource[ResourceID], props),
|
|
228
247
|
);
|
|
229
248
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
249
|
+
if (!error.force) {
|
|
250
|
+
const pendingDeletions =
|
|
251
|
+
(await scope.get<PendingDeletions>("pendingDeletions")) ?? [];
|
|
252
|
+
pendingDeletions.push({
|
|
253
|
+
resource: oldOutput,
|
|
254
|
+
oldProps: state.oldProps,
|
|
255
|
+
});
|
|
256
|
+
await scope.set("pendingDeletions", pendingDeletions);
|
|
257
|
+
}
|
|
237
258
|
} else {
|
|
238
259
|
throw error;
|
|
239
260
|
}
|
package/src/build-date.ts
CHANGED
package/src/cloudflare/ai.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* ```ts
|
|
10
10
|
* import { Worker, Ai } from "alchemy/cloudflare";
|
|
11
11
|
*
|
|
12
|
-
* const ai =
|
|
12
|
+
* const ai = Ai();
|
|
13
13
|
*
|
|
14
14
|
* await Worker("my-worker", {
|
|
15
15
|
* name: "my-worker",
|
|
@@ -22,12 +22,17 @@
|
|
|
22
22
|
*
|
|
23
23
|
* @see https://developers.cloudflare.com/workers-ai/
|
|
24
24
|
*/
|
|
25
|
-
export
|
|
26
|
-
|
|
25
|
+
export function Ai<Models extends AiModelListType = AiModelListType>() {
|
|
26
|
+
return {
|
|
27
|
+
type: "ai",
|
|
28
|
+
_phantom: undefined! as Models,
|
|
29
|
+
} as const;
|
|
30
|
+
}
|
|
27
31
|
|
|
32
|
+
export type Ai<Models extends AiModelListType = AiModelListType> = {
|
|
33
|
+
type: "ai";
|
|
28
34
|
/**
|
|
29
35
|
* @internal
|
|
30
36
|
*/
|
|
31
|
-
///@ts-ignore
|
|
32
37
|
_phantom: Models;
|
|
33
|
-
}
|
|
38
|
+
};
|
|
@@ -6,21 +6,30 @@ export interface AnalyticsEngineDatasetProps {
|
|
|
6
6
|
dataset: string;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
export type AnalyticsEngineDataset = {
|
|
10
|
+
type: "analytics_engine";
|
|
11
|
+
id: string;
|
|
12
|
+
dataset: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
9
15
|
/**
|
|
16
|
+
* Creates a binding for an Analytics Engine dataset.
|
|
17
|
+
*
|
|
10
18
|
* @example
|
|
19
|
+
* ```ts
|
|
11
20
|
* // Create a binding for an Analytics Engine dataset
|
|
12
|
-
* const dataset =
|
|
21
|
+
* const dataset = AnalyticsEngineDataset("ae-dataset", {
|
|
13
22
|
* dataset: "WEATHER",
|
|
14
23
|
* });
|
|
24
|
+
* ```
|
|
15
25
|
*/
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
+
export function AnalyticsEngineDataset(
|
|
27
|
+
id: string,
|
|
28
|
+
props: AnalyticsEngineDatasetProps,
|
|
29
|
+
): AnalyticsEngineDataset {
|
|
30
|
+
return {
|
|
31
|
+
type: "analytics_engine",
|
|
32
|
+
id,
|
|
33
|
+
dataset: props.dataset,
|
|
34
|
+
};
|
|
26
35
|
}
|
|
@@ -47,6 +47,11 @@ export interface CloudflareApiError {
|
|
|
47
47
|
* Error message
|
|
48
48
|
*/
|
|
49
49
|
message: string;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Error documentation URL
|
|
53
|
+
*/
|
|
54
|
+
documentation_url?: string;
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
/**
|
|
@@ -68,3 +73,29 @@ export async function extractCloudflareError(
|
|
|
68
73
|
return `HTTP ${response.status}: ${response.statusText}`;
|
|
69
74
|
}
|
|
70
75
|
}
|
|
76
|
+
|
|
77
|
+
export async function extractCloudflareResult<T>(
|
|
78
|
+
label: string,
|
|
79
|
+
promise: Promise<Response>,
|
|
80
|
+
): Promise<T> {
|
|
81
|
+
const response = await promise.catch(() => {
|
|
82
|
+
throw new Error(`Failed to ${label}: Failed to fetch`);
|
|
83
|
+
});
|
|
84
|
+
const json = (await response.json().catch(() => {
|
|
85
|
+
throw new Error(
|
|
86
|
+
`Failed to ${label} (${response.status}): The API returned an invalid response`,
|
|
87
|
+
);
|
|
88
|
+
})) as CloudflareApiResponse<T>;
|
|
89
|
+
if (json.success) {
|
|
90
|
+
return json.result;
|
|
91
|
+
} else {
|
|
92
|
+
const error = new Error(
|
|
93
|
+
`Failed to ${label} (${response.status} ${response.statusText}):\n${json.errors.map((e) => `- [${e.code}] ${e.message}${e.documentation_url ? ` (${e.documentation_url})` : ""}`).join("\n")}`,
|
|
94
|
+
);
|
|
95
|
+
Error.captureStackTrace(error, extractCloudflareResult);
|
|
96
|
+
Object.assign(error, {
|
|
97
|
+
status: response.status,
|
|
98
|
+
});
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import kleur from "kleur";
|
|
2
|
+
import { err, ok, ResultAsync } from "neverthrow";
|
|
3
|
+
import crypto from "node:crypto";
|
|
4
|
+
import fs from "node:fs/promises";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import open from "open";
|
|
8
|
+
import { HTTPServer } from "../util/http-server.ts";
|
|
9
|
+
import { memoize, memoizeSync } from "../util/memoize.ts";
|
|
10
|
+
import { detached, ensure, singleFlight } from "../util/neverthrow.ts";
|
|
11
|
+
import { createXdgAppPaths } from "../util/xdg-paths.ts";
|
|
12
|
+
|
|
13
|
+
const CLIENT_ID = "54d11594-84e4-41aa-b438-e81b8fa78ee7";
|
|
14
|
+
const REDIRECT_URI = "http://localhost:8976/oauth/callback";
|
|
15
|
+
const ALCHEMY_BASE_URL = "https://alchemy.run";
|
|
16
|
+
export const DEFAULT_SCOPES = [
|
|
17
|
+
"account:read",
|
|
18
|
+
"user:read",
|
|
19
|
+
"workers:write",
|
|
20
|
+
"workers_kv:write",
|
|
21
|
+
"workers_routes:write",
|
|
22
|
+
"workers_scripts:write",
|
|
23
|
+
"workers_tail:read",
|
|
24
|
+
"d1:write",
|
|
25
|
+
"pages:write",
|
|
26
|
+
"zone:read",
|
|
27
|
+
"ssl_certs:write",
|
|
28
|
+
"ai:write",
|
|
29
|
+
"queues:write",
|
|
30
|
+
"pipelines:write",
|
|
31
|
+
"secrets_store:write",
|
|
32
|
+
"containers:write",
|
|
33
|
+
"cloudchamber:write",
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
interface WranglerConfig {
|
|
37
|
+
oauth_token: string;
|
|
38
|
+
refresh_token: string;
|
|
39
|
+
expiration_time: Date;
|
|
40
|
+
scopes: string[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const getWranglerConfigPath = memoize(async () => {
|
|
44
|
+
const xdgConfigDir = createXdgAppPaths(".wrangler").config();
|
|
45
|
+
const legacyConfigDir = path.join(os.homedir(), ".wrangler");
|
|
46
|
+
const configDir = (await fs
|
|
47
|
+
.stat(legacyConfigDir)
|
|
48
|
+
.then((stat) => stat.isDirectory())
|
|
49
|
+
.catch(() => false))
|
|
50
|
+
? legacyConfigDir
|
|
51
|
+
: xdgConfigDir;
|
|
52
|
+
return path.join(configDir, "config", "default.toml");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const readWranglerConfig = () => {
|
|
56
|
+
return ResultAsync.fromSafePromise(getWranglerConfigPath())
|
|
57
|
+
.andThen((path) =>
|
|
58
|
+
ResultAsync.fromPromise(
|
|
59
|
+
fs.readFile(path, "utf-8").then(async (text) => {
|
|
60
|
+
const toml = await import("@iarna/toml");
|
|
61
|
+
return toml.parse(text.replace(/\r\n/g, "\n"));
|
|
62
|
+
}),
|
|
63
|
+
() => new Error("Failed to read Wrangler config."),
|
|
64
|
+
),
|
|
65
|
+
)
|
|
66
|
+
.andThen((config) => {
|
|
67
|
+
if (
|
|
68
|
+
typeof config.oauth_token !== "string" ||
|
|
69
|
+
typeof config.refresh_token !== "string" ||
|
|
70
|
+
!config.expiration_time ||
|
|
71
|
+
!Array.isArray(config.scopes)
|
|
72
|
+
) {
|
|
73
|
+
return err(new Error("Invalid Wrangler config."));
|
|
74
|
+
}
|
|
75
|
+
return ok({
|
|
76
|
+
oauth_token: config.oauth_token,
|
|
77
|
+
refresh_token: config.refresh_token,
|
|
78
|
+
expiration_time: new Date(config.expiration_time as any),
|
|
79
|
+
scopes: Array.from(config.scopes as string[]),
|
|
80
|
+
} as WranglerConfig);
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const writeWranglerConfig = (config: WranglerConfig) => {
|
|
85
|
+
return ResultAsync.fromSafePromise(getWranglerConfigPath()).map(
|
|
86
|
+
async (configPath) => {
|
|
87
|
+
const toml = await import("@iarna/toml");
|
|
88
|
+
await fs.writeFile(
|
|
89
|
+
configPath,
|
|
90
|
+
toml.stringify({
|
|
91
|
+
oauth_token: config.oauth_token,
|
|
92
|
+
refresh_token: config.refresh_token,
|
|
93
|
+
expiration_time: config.expiration_time,
|
|
94
|
+
scopes: config.scopes,
|
|
95
|
+
}),
|
|
96
|
+
);
|
|
97
|
+
},
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const fetchToken = (
|
|
102
|
+
body:
|
|
103
|
+
| {
|
|
104
|
+
grant_type: "refresh_token";
|
|
105
|
+
refresh_token: string;
|
|
106
|
+
client_id: string;
|
|
107
|
+
}
|
|
108
|
+
| {
|
|
109
|
+
grant_type: "authorization_code";
|
|
110
|
+
code: string;
|
|
111
|
+
code_verifier: string;
|
|
112
|
+
client_id: string;
|
|
113
|
+
redirect_uri: string;
|
|
114
|
+
},
|
|
115
|
+
) => {
|
|
116
|
+
return ResultAsync.fromPromise(
|
|
117
|
+
fetch("https://dash.cloudflare.com/oauth2/token", {
|
|
118
|
+
method: "POST",
|
|
119
|
+
headers: {
|
|
120
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
121
|
+
},
|
|
122
|
+
body: new URLSearchParams(body),
|
|
123
|
+
}),
|
|
124
|
+
() =>
|
|
125
|
+
new OAuthError({
|
|
126
|
+
error: "fetch_error",
|
|
127
|
+
error_description: "Failed to fetch OAuth token.",
|
|
128
|
+
status_code: 0,
|
|
129
|
+
}),
|
|
130
|
+
)
|
|
131
|
+
.andThen((res) =>
|
|
132
|
+
ResultAsync.fromPromise(
|
|
133
|
+
res.json(),
|
|
134
|
+
() =>
|
|
135
|
+
new OAuthError({
|
|
136
|
+
error: "invalid_response",
|
|
137
|
+
error_description: "The server returned an invalid response.",
|
|
138
|
+
status_code: res.status,
|
|
139
|
+
}),
|
|
140
|
+
).andThen((json) =>
|
|
141
|
+
res.ok ? ok(json as OAuthTokens) : err(new OAuthError(json as any)),
|
|
142
|
+
),
|
|
143
|
+
)
|
|
144
|
+
.map(
|
|
145
|
+
(tokens): WranglerConfig => ({
|
|
146
|
+
oauth_token: tokens.access_token,
|
|
147
|
+
refresh_token: tokens.refresh_token,
|
|
148
|
+
expiration_time: new Date(Date.now() + tokens.expires_in * 1000),
|
|
149
|
+
scopes: tokens.scope.split(" "),
|
|
150
|
+
}),
|
|
151
|
+
)
|
|
152
|
+
.andTee((config) => writeWranglerConfig(config));
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
interface OAuthTokens {
|
|
156
|
+
access_token: string;
|
|
157
|
+
refresh_token: string;
|
|
158
|
+
expires_in: number;
|
|
159
|
+
scope: string;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export const getRefreshedWranglerConfig = singleFlight(
|
|
163
|
+
memoizeSync(
|
|
164
|
+
() => {
|
|
165
|
+
return readWranglerConfig()
|
|
166
|
+
.andThen((config) => {
|
|
167
|
+
if (config.expiration_time.getTime() > Date.now() + 10 * 1000) {
|
|
168
|
+
return ok(config);
|
|
169
|
+
}
|
|
170
|
+
return fetchToken({
|
|
171
|
+
grant_type: "refresh_token",
|
|
172
|
+
refresh_token: config.refresh_token,
|
|
173
|
+
client_id: CLIENT_ID,
|
|
174
|
+
});
|
|
175
|
+
})
|
|
176
|
+
.orElse((error) => {
|
|
177
|
+
if (isInteractive()) {
|
|
178
|
+
return wranglerLogin();
|
|
179
|
+
}
|
|
180
|
+
if (error instanceof OAuthError) {
|
|
181
|
+
return err(error);
|
|
182
|
+
}
|
|
183
|
+
return ok(null);
|
|
184
|
+
});
|
|
185
|
+
},
|
|
186
|
+
() => Math.floor(Date.now() / 5000).toString(),
|
|
187
|
+
),
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
const isInteractive = () => {
|
|
191
|
+
return process.stdin.isTTY && process.stdout.isTTY && !process.env.CI;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const generateAuthorizationURL = (scopes: string[]) => {
|
|
195
|
+
const state = crypto.randomBytes(32).toString("base64url");
|
|
196
|
+
const verifier = crypto.randomBytes(96).toString("base64url");
|
|
197
|
+
const challenge = crypto
|
|
198
|
+
.createHash("sha256")
|
|
199
|
+
.update(verifier)
|
|
200
|
+
.digest("base64url");
|
|
201
|
+
const url = new URL("https://dash.cloudflare.com/oauth2/auth");
|
|
202
|
+
url.search = new URLSearchParams({
|
|
203
|
+
response_type: "code",
|
|
204
|
+
client_id: CLIENT_ID,
|
|
205
|
+
redirect_uri: REDIRECT_URI,
|
|
206
|
+
scope: [...scopes, "offline_access"].join(" "),
|
|
207
|
+
state,
|
|
208
|
+
code_challenge: challenge,
|
|
209
|
+
code_challenge_method: "S256",
|
|
210
|
+
}).toString();
|
|
211
|
+
return { url: url.toString(), state, verifier };
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
class OAuthError extends Error {
|
|
215
|
+
readonly error: string;
|
|
216
|
+
readonly error_verbose?: string;
|
|
217
|
+
readonly error_hint?: string;
|
|
218
|
+
readonly status_code: number;
|
|
219
|
+
constructor(params: {
|
|
220
|
+
error: string;
|
|
221
|
+
error_verbose?: string;
|
|
222
|
+
error_description: string;
|
|
223
|
+
error_hint?: string;
|
|
224
|
+
status_code: number;
|
|
225
|
+
}) {
|
|
226
|
+
console.dir(params, { depth: null });
|
|
227
|
+
super(params.error_description);
|
|
228
|
+
this.error = params.error;
|
|
229
|
+
this.error_verbose = params.error_verbose;
|
|
230
|
+
this.error_hint = params.error_hint;
|
|
231
|
+
this.status_code = params.status_code;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export const wranglerLogin = (
|
|
236
|
+
scopes: string[] = DEFAULT_SCOPES,
|
|
237
|
+
log: (message: string) => void = console.log, // using console.log instead of logger.log to avoid bundling hell with CLI
|
|
238
|
+
) => {
|
|
239
|
+
const challenge = generateAuthorizationURL(scopes);
|
|
240
|
+
log(
|
|
241
|
+
[
|
|
242
|
+
"Opening browser to authorize with Cloudflare...",
|
|
243
|
+
"",
|
|
244
|
+
kleur.gray(
|
|
245
|
+
"If you are not automatically redirected, please open the following URL in your browser:",
|
|
246
|
+
),
|
|
247
|
+
challenge.url,
|
|
248
|
+
].join("\n"),
|
|
249
|
+
);
|
|
250
|
+
open(challenge.url);
|
|
251
|
+
const { result, ok, err } = detached<WranglerConfig, OAuthError>();
|
|
252
|
+
const server = new HTTPServer({
|
|
253
|
+
port: 8976,
|
|
254
|
+
fetch: async (request) => {
|
|
255
|
+
const url = new URL(request.url);
|
|
256
|
+
if (url.pathname !== "/oauth/callback") {
|
|
257
|
+
return new Response("Not found", { status: 404 });
|
|
258
|
+
}
|
|
259
|
+
const error = url.searchParams.get("error");
|
|
260
|
+
const error_description = url.searchParams.get("error_description");
|
|
261
|
+
const code = url.searchParams.get("code");
|
|
262
|
+
const state = url.searchParams.get("state");
|
|
263
|
+
if (error) {
|
|
264
|
+
err(
|
|
265
|
+
new OAuthError({
|
|
266
|
+
error,
|
|
267
|
+
error_description: error_description ?? "Unknown error",
|
|
268
|
+
status_code: 400,
|
|
269
|
+
}),
|
|
270
|
+
);
|
|
271
|
+
return Response.redirect(`${ALCHEMY_BASE_URL}/auth/error`);
|
|
272
|
+
}
|
|
273
|
+
if (!code || !state || state !== challenge.state) {
|
|
274
|
+
err(
|
|
275
|
+
new OAuthError({
|
|
276
|
+
error: "invalid_request",
|
|
277
|
+
error_description: "Invalid request",
|
|
278
|
+
status_code: 400,
|
|
279
|
+
}),
|
|
280
|
+
);
|
|
281
|
+
return Response.redirect(`${ALCHEMY_BASE_URL}/auth/error`);
|
|
282
|
+
}
|
|
283
|
+
const tokens = await fetchToken({
|
|
284
|
+
grant_type: "authorization_code",
|
|
285
|
+
code,
|
|
286
|
+
code_verifier: challenge.verifier,
|
|
287
|
+
client_id: CLIENT_ID,
|
|
288
|
+
redirect_uri: REDIRECT_URI,
|
|
289
|
+
});
|
|
290
|
+
if (tokens.isErr()) {
|
|
291
|
+
err(tokens.error);
|
|
292
|
+
return Response.redirect(`${ALCHEMY_BASE_URL}/auth/error`);
|
|
293
|
+
}
|
|
294
|
+
ok(tokens.value);
|
|
295
|
+
return Response.redirect(`${ALCHEMY_BASE_URL}/auth/success`);
|
|
296
|
+
},
|
|
297
|
+
});
|
|
298
|
+
const timeout = setTimeout(
|
|
299
|
+
() => {
|
|
300
|
+
err(
|
|
301
|
+
new OAuthError({
|
|
302
|
+
error: "timeout",
|
|
303
|
+
error_description: "Authorization timed out after 5 minutes",
|
|
304
|
+
status_code: 408,
|
|
305
|
+
}),
|
|
306
|
+
);
|
|
307
|
+
},
|
|
308
|
+
1000 * 60 * 5,
|
|
309
|
+
);
|
|
310
|
+
return ensure(result, async () => {
|
|
311
|
+
clearTimeout(timeout);
|
|
312
|
+
await server.stop();
|
|
313
|
+
});
|
|
314
|
+
};
|