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
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Context } from "../context.ts";
|
|
2
2
|
import { Resource } from "../resource.ts";
|
|
3
|
+
import { memoize } from "../util/memoize.ts";
|
|
4
|
+
import { extractCloudflareResult } from "./api-response.ts";
|
|
3
5
|
import {
|
|
4
6
|
createCloudflareApi,
|
|
5
7
|
type CloudflareApi,
|
|
6
8
|
type CloudflareApiOptions,
|
|
7
9
|
} from "./api.ts";
|
|
8
|
-
import type { CloudflareApiResponse } from "./types.ts";
|
|
9
|
-
import { getAccountSubdomain } from "./worker/shared.ts";
|
|
10
10
|
|
|
11
11
|
interface WorkerSubdomainProps extends CloudflareApiOptions {
|
|
12
12
|
/**
|
|
@@ -49,16 +49,7 @@ export const WorkerSubdomain = Resource(
|
|
|
49
49
|
}
|
|
50
50
|
return this.destroy();
|
|
51
51
|
}
|
|
52
|
-
await
|
|
53
|
-
`enable subdomain for "${props.scriptName}"`,
|
|
54
|
-
api.post(
|
|
55
|
-
`/accounts/${api.accountId}/workers/scripts/${props.scriptName}/subdomain`,
|
|
56
|
-
{ enabled: true, previews_enabled: true },
|
|
57
|
-
{
|
|
58
|
-
headers: { "Content-Type": "application/json" },
|
|
59
|
-
},
|
|
60
|
-
),
|
|
61
|
-
);
|
|
52
|
+
await enableWorkerSubdomain(api, props.scriptName);
|
|
62
53
|
const subdomain = await getAccountSubdomain(api);
|
|
63
54
|
const base = `${subdomain}.workers.dev`;
|
|
64
55
|
let url: string;
|
|
@@ -77,7 +68,7 @@ export async function disableWorkerSubdomain(
|
|
|
77
68
|
api: CloudflareApi,
|
|
78
69
|
scriptName: string,
|
|
79
70
|
) {
|
|
80
|
-
await
|
|
71
|
+
await extractCloudflareResult<SubdomainResponse>(
|
|
81
72
|
`disable subdomain for "${scriptName}"`,
|
|
82
73
|
api.post(
|
|
83
74
|
`/accounts/${api.accountId}/workers/scripts/${scriptName}/subdomain`,
|
|
@@ -91,33 +82,48 @@ export async function disableWorkerSubdomain(
|
|
|
91
82
|
});
|
|
92
83
|
}
|
|
93
84
|
|
|
85
|
+
export async function enableWorkerSubdomain(
|
|
86
|
+
api: CloudflareApi,
|
|
87
|
+
scriptName: string,
|
|
88
|
+
) {
|
|
89
|
+
await extractCloudflareResult<SubdomainResponse>(
|
|
90
|
+
`enable subdomain for "${scriptName}"`,
|
|
91
|
+
api.post(
|
|
92
|
+
`/accounts/${api.accountId}/workers/scripts/${scriptName}/subdomain`,
|
|
93
|
+
{ enabled: true, previews_enabled: true },
|
|
94
|
+
),
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export async function getWorkerSubdomain(
|
|
99
|
+
api: CloudflareApi,
|
|
100
|
+
scriptName: string,
|
|
101
|
+
) {
|
|
102
|
+
return await extractCloudflareResult<SubdomainResponse>(
|
|
103
|
+
`get subdomain for "${scriptName}"`,
|
|
104
|
+
api.get(
|
|
105
|
+
`/accounts/${api.accountId}/workers/scripts/${scriptName}/subdomain`,
|
|
106
|
+
),
|
|
107
|
+
).catch((error): SubdomainResponse => {
|
|
108
|
+
if (error.status === 404) {
|
|
109
|
+
return { enabled: false, previews_enabled: false };
|
|
110
|
+
}
|
|
111
|
+
throw error;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
94
115
|
interface SubdomainResponse {
|
|
95
116
|
enabled: boolean;
|
|
96
117
|
previews_enabled: boolean;
|
|
97
118
|
}
|
|
98
119
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
throw new Error(`Failed to ${label}: Failed to fetch`);
|
|
105
|
-
});
|
|
106
|
-
const json = (await response.json().catch(() => {
|
|
107
|
-
throw new Error(
|
|
108
|
-
`Failed to ${label} (${response.status}): The API returned an invalid response`,
|
|
120
|
+
export const getAccountSubdomain = memoize(
|
|
121
|
+
async (api: CloudflareApi) => {
|
|
122
|
+
const result = await extractCloudflareResult<{ subdomain: string }>(
|
|
123
|
+
`get subdomain for account ${api.accountId}`,
|
|
124
|
+
api.get(`/accounts/${api.accountId}/workers/subdomain`),
|
|
109
125
|
);
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const error = new Error(
|
|
115
|
-
`Failed to ${label} (${response.status}): ${json.errors.map((e) => `${e.code}: ${e.message}`).join(", ")}`,
|
|
116
|
-
);
|
|
117
|
-
Error.captureStackTrace(error, wrapFetch);
|
|
118
|
-
Object.assign(error, {
|
|
119
|
-
status: response.status,
|
|
120
|
-
});
|
|
121
|
-
throw error;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
126
|
+
return result.subdomain;
|
|
127
|
+
},
|
|
128
|
+
(api) => api.accountId,
|
|
129
|
+
);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import kleur from "kleur";
|
|
2
2
|
import { WebSocket } from "ws";
|
|
3
|
-
import { logger } from "
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
3
|
+
import { logger } from "../util/logger.ts";
|
|
4
|
+
import type { CloudflareApiResponse } from "./api-response.ts";
|
|
5
|
+
import type { CloudflareApi } from "./api.ts";
|
|
6
6
|
|
|
7
7
|
export const createTail = async (
|
|
8
8
|
api: CloudflareApi,
|
|
@@ -47,7 +47,12 @@ class TailClient {
|
|
|
47
47
|
}
|
|
48
48
|
const res = await this.api.post(
|
|
49
49
|
`/accounts/${this.api.accountId}/workers/scripts/${this.scriptName}/tails`,
|
|
50
|
-
{},
|
|
50
|
+
{ filters: [] },
|
|
51
|
+
{
|
|
52
|
+
headers: {
|
|
53
|
+
"Content-Type": "application/json",
|
|
54
|
+
},
|
|
55
|
+
},
|
|
51
56
|
);
|
|
52
57
|
const json = (await res.json()) as CloudflareApiResponse<Tail>;
|
|
53
58
|
if (!json.success) {
|
|
@@ -72,11 +77,7 @@ class TailClient {
|
|
|
72
77
|
throw new Error(`Failed to connect to tail for ${this.scriptName}`);
|
|
73
78
|
}
|
|
74
79
|
const tail = await this.create();
|
|
75
|
-
const ws = new WebSocket(tail.url,
|
|
76
|
-
headers: {
|
|
77
|
-
"Sec-WebSocket-Protocol": "trace-v1",
|
|
78
|
-
},
|
|
79
|
-
});
|
|
80
|
+
const ws = new WebSocket(tail.url, "trace-v1");
|
|
80
81
|
ws.on("open", () => {
|
|
81
82
|
this.ping(ws);
|
|
82
83
|
if (DEBUG) {
|
|
@@ -92,7 +93,9 @@ class TailClient {
|
|
|
92
93
|
return;
|
|
93
94
|
}
|
|
94
95
|
logger.log(`reconnecting to tail for "${this.scriptName}"`);
|
|
95
|
-
|
|
96
|
+
setTimeout(() => {
|
|
97
|
+
this.connect(attempt + 1);
|
|
98
|
+
}, 1000);
|
|
96
99
|
});
|
|
97
100
|
ws.on("error", (event) => {
|
|
98
101
|
logger.error(`error on tail for "${this.scriptName}": ${event}`);
|
package/src/cloudflare/worker.ts
CHANGED
|
@@ -48,6 +48,10 @@ import {
|
|
|
48
48
|
normalizeWorkerBundle,
|
|
49
49
|
} from "./bundle/index.ts";
|
|
50
50
|
import { wrap } from "./bundle/normalize.ts";
|
|
51
|
+
import {
|
|
52
|
+
type CompatibilityPreset,
|
|
53
|
+
unionCompatibilityFlags,
|
|
54
|
+
} from "./compatibility-presets.ts";
|
|
51
55
|
import { type Container, ContainerApplication } from "./container.ts";
|
|
52
56
|
import { CustomDomain } from "./custom-domain.ts";
|
|
53
57
|
import { isD1Database } from "./d1-database.ts";
|
|
@@ -81,7 +85,7 @@ import {
|
|
|
81
85
|
} from "./worker-metadata.ts";
|
|
82
86
|
import { WorkerStub, isWorkerStub } from "./worker-stub.ts";
|
|
83
87
|
import { WorkerSubdomain, disableWorkerSubdomain } from "./worker-subdomain.ts";
|
|
84
|
-
import { createTail } from "./worker
|
|
88
|
+
import { createTail } from "./worker-tail.ts";
|
|
85
89
|
import { Workflow, isWorkflow, upsertWorkflow } from "./workflow.ts";
|
|
86
90
|
|
|
87
91
|
/**
|
|
@@ -215,6 +219,15 @@ export interface BaseWorkerProps<
|
|
|
215
219
|
*/
|
|
216
220
|
compatibilityFlags?: string[];
|
|
217
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Compatibility preset to automatically include common compatibility flags
|
|
224
|
+
*
|
|
225
|
+
* - "node": Includes nodejs_compat flag for Node.js compatibility
|
|
226
|
+
*
|
|
227
|
+
* @default undefined (no preset)
|
|
228
|
+
*/
|
|
229
|
+
compatibility?: CompatibilityPreset;
|
|
230
|
+
|
|
218
231
|
/**
|
|
219
232
|
* Configuration for static assets
|
|
220
233
|
*/
|
|
@@ -618,8 +631,8 @@ export function WorkerRef<
|
|
|
618
631
|
* @example
|
|
619
632
|
* // Create a real-time chat worker using Durable Objects
|
|
620
633
|
* // for state management:
|
|
621
|
-
* const chatRooms =
|
|
622
|
-
* const userStore =
|
|
634
|
+
* const chatRooms = DurableObjectNamespace("chat-rooms");
|
|
635
|
+
* const userStore = DurableObjectNamespace("user-store");
|
|
623
636
|
*
|
|
624
637
|
* const chat = await Worker("chat", {
|
|
625
638
|
* name: "chat-worker",
|
|
@@ -693,7 +706,7 @@ export function WorkerRef<
|
|
|
693
706
|
* entrypoint: "./src/data.ts",
|
|
694
707
|
* bindings: {
|
|
695
708
|
* // Bind to its own durable object
|
|
696
|
-
* STORAGE:
|
|
709
|
+
* STORAGE: DurableObjectNamespace("storage", {
|
|
697
710
|
* className: "DataStorage"
|
|
698
711
|
* })
|
|
699
712
|
* }
|
|
@@ -834,7 +847,13 @@ export function Worker<const B extends Bindings>(
|
|
|
834
847
|
...(props as any),
|
|
835
848
|
url: true,
|
|
836
849
|
compatibilityFlags: Array.from(
|
|
837
|
-
new Set([
|
|
850
|
+
new Set([
|
|
851
|
+
"nodejs_compat",
|
|
852
|
+
...unionCompatibilityFlags(
|
|
853
|
+
props.compatibility,
|
|
854
|
+
props.compatibilityFlags,
|
|
855
|
+
),
|
|
856
|
+
]),
|
|
838
857
|
),
|
|
839
858
|
entrypoint: meta!.filename,
|
|
840
859
|
name: workerName,
|
|
@@ -987,7 +1006,10 @@ export const _Worker = Resource(
|
|
|
987
1006
|
const workerName = props.name ?? id;
|
|
988
1007
|
const compatibilityDate =
|
|
989
1008
|
props.compatibilityDate ?? DEFAULT_COMPATIBILITY_DATE;
|
|
990
|
-
const compatibilityFlags =
|
|
1009
|
+
const compatibilityFlags = unionCompatibilityFlags(
|
|
1010
|
+
props.compatibility,
|
|
1011
|
+
props.compatibilityFlags,
|
|
1012
|
+
);
|
|
991
1013
|
const dispatchNamespace =
|
|
992
1014
|
typeof props.namespace === "string"
|
|
993
1015
|
? props.namespace
|
|
@@ -1085,6 +1107,26 @@ export const _Worker = Resource(
|
|
|
1085
1107
|
throw error;
|
|
1086
1108
|
}
|
|
1087
1109
|
|
|
1110
|
+
if (this.phase === "update") {
|
|
1111
|
+
const oldName = this.output.name ?? this.output.id;
|
|
1112
|
+
const newName = workerName;
|
|
1113
|
+
|
|
1114
|
+
if (oldName !== newName) {
|
|
1115
|
+
if (dispatchNamespace) {
|
|
1116
|
+
await this.replace(true);
|
|
1117
|
+
} else {
|
|
1118
|
+
const renameResponse = await api.patch(
|
|
1119
|
+
`/accounts/${api.accountId}/workers/services/${oldName}`,
|
|
1120
|
+
{ id: newName },
|
|
1121
|
+
);
|
|
1122
|
+
|
|
1123
|
+
if (!renameResponse.ok) {
|
|
1124
|
+
await handleApiError(renameResponse, "rename", "worker", oldName);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1088
1130
|
let assetsBinding: Assets | undefined;
|
|
1089
1131
|
const workflowsBindings: Workflow[] = [];
|
|
1090
1132
|
const containersBindings: Container[] = [];
|
|
@@ -1219,8 +1261,13 @@ export const _Worker = Resource(
|
|
|
1219
1261
|
}),
|
|
1220
1262
|
);
|
|
1221
1263
|
putWorkerResult = await promise.value;
|
|
1222
|
-
|
|
1223
|
-
|
|
1264
|
+
await createTail(api, id, workerName)
|
|
1265
|
+
.then((tail) => {
|
|
1266
|
+
cleanups.push(() => tail.close());
|
|
1267
|
+
})
|
|
1268
|
+
.catch((error) => {
|
|
1269
|
+
logger.error(`Failed to create tail for ${workerName}`, error);
|
|
1270
|
+
});
|
|
1224
1271
|
} else {
|
|
1225
1272
|
putWorkerResult = await putWorkerWithAssets(props, await bundle.create());
|
|
1226
1273
|
}
|
|
@@ -1424,13 +1471,13 @@ const normalizeExportBindings = (
|
|
|
1424
1471
|
Object.entries(bindings).map(([bindingName, binding]) => [
|
|
1425
1472
|
bindingName,
|
|
1426
1473
|
isDurableObjectNamespace(binding) && binding.scriptName === undefined
|
|
1427
|
-
?
|
|
1474
|
+
? DurableObjectNamespace(binding.id, {
|
|
1428
1475
|
...binding,
|
|
1429
1476
|
// re-export this binding mapping to the host worker (this worker)
|
|
1430
1477
|
scriptName,
|
|
1431
1478
|
})
|
|
1432
1479
|
: isWorkflow(binding) && binding.scriptName === undefined
|
|
1433
|
-
?
|
|
1480
|
+
? Workflow(binding.id, {
|
|
1434
1481
|
...binding,
|
|
1435
1482
|
// re-export this binding mapping to the host worker (this worker)
|
|
1436
1483
|
scriptName,
|
|
@@ -1824,21 +1871,20 @@ function createDevCommand(props: {
|
|
|
1824
1871
|
}
|
|
1825
1872
|
}
|
|
1826
1873
|
|
|
1827
|
-
type PutWorkerOptions = WorkerProps & {
|
|
1874
|
+
type PutWorkerOptions = Omit<WorkerProps, "entrypoint"> & {
|
|
1828
1875
|
dispatchNamespace?: string;
|
|
1829
1876
|
migrationTag?: string;
|
|
1830
1877
|
workerName: string;
|
|
1831
1878
|
scriptBundle: WorkerBundle;
|
|
1832
|
-
version
|
|
1879
|
+
version?: string;
|
|
1833
1880
|
compatibilityDate: string;
|
|
1834
1881
|
compatibilityFlags: string[];
|
|
1835
|
-
assetUploadResult
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
| undefined;
|
|
1882
|
+
assetUploadResult?: {
|
|
1883
|
+
completionToken?: string;
|
|
1884
|
+
keepAssets?: boolean;
|
|
1885
|
+
assetConfig?: AssetsConfig;
|
|
1886
|
+
};
|
|
1887
|
+
tags?: string[];
|
|
1842
1888
|
unstable_cacheWorkerSettings?: boolean;
|
|
1843
1889
|
};
|
|
1844
1890
|
|
|
@@ -34,31 +34,50 @@ export interface WorkflowProps {
|
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
export
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export class Workflow<PARAMS = unknown> {
|
|
42
|
-
public readonly type = "workflow";
|
|
37
|
+
export type Workflow<PARAMS = unknown> = {
|
|
38
|
+
type: "workflow";
|
|
43
39
|
/**
|
|
44
40
|
* Phantom property to preserve workflow params at the type level.
|
|
45
|
-
*
|
|
46
41
|
* No value exists.
|
|
47
42
|
*/
|
|
48
|
-
|
|
43
|
+
_PARAMS: PARAMS;
|
|
44
|
+
id: string;
|
|
45
|
+
workflowName: string;
|
|
46
|
+
className: string;
|
|
47
|
+
scriptName?: string;
|
|
48
|
+
};
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
export function isWorkflow(binding: Binding): binding is Workflow {
|
|
51
|
+
return typeof binding === "object" && binding.type === "workflow";
|
|
52
|
+
}
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Creates a workflow binding for orchestrating and automating tasks.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* // Create a basic workflow
|
|
60
|
+
* const workflow = Workflow("my-workflow", {
|
|
61
|
+
* workflowName: "my-workflow",
|
|
62
|
+
* className: "MyWorkflow"
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export function Workflow<PARAMS = unknown>(
|
|
67
|
+
id: string,
|
|
68
|
+
props: WorkflowProps = {},
|
|
69
|
+
): Workflow<PARAMS> {
|
|
70
|
+
const workflowName = props.workflowName ?? props.className ?? id;
|
|
71
|
+
const className = props.className ?? workflowName;
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
type: "workflow",
|
|
75
|
+
_PARAMS: undefined!,
|
|
76
|
+
id,
|
|
77
|
+
workflowName,
|
|
78
|
+
className,
|
|
79
|
+
scriptName: props.scriptName,
|
|
80
|
+
};
|
|
62
81
|
}
|
|
63
82
|
|
|
64
83
|
export interface WorkflowMetadata {
|
package/src/context.ts
CHANGED
|
@@ -57,7 +57,7 @@ export interface BaseContext<Out extends Resource> {
|
|
|
57
57
|
* Indicate that this resource is being replaced.
|
|
58
58
|
* This will cause the resource to be deleted at the end of the stack's CREATE phase.
|
|
59
59
|
*/
|
|
60
|
-
replace(): never
|
|
60
|
+
replace(force?: boolean): Promise<never>;
|
|
61
61
|
/**
|
|
62
62
|
* Terminate the resource lifecycle handler and destroy the resource.
|
|
63
63
|
*
|
|
@@ -102,7 +102,7 @@ export function context<
|
|
|
102
102
|
seq: number;
|
|
103
103
|
props: Props;
|
|
104
104
|
state: State<Kind, Props, Out>;
|
|
105
|
-
replace: () => never
|
|
105
|
+
replace: (force?: boolean) => Promise<never>;
|
|
106
106
|
isReplacement?: boolean;
|
|
107
107
|
}): Context<Out> {
|
|
108
108
|
type InternalSymbols =
|
package/src/docker/api.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
1
2
|
import { Buffer } from "node:buffer";
|
|
2
3
|
import { spawn } from "node:child_process";
|
|
3
4
|
import fs from "node:fs/promises";
|
|
4
5
|
import path from "node:path";
|
|
5
|
-
import { exec } from "../os/exec.ts";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Options for Docker API requests
|
|
@@ -66,14 +66,39 @@ export class DockerApi {
|
|
|
66
66
|
? { ...process.env, DOCKER_CONFIG: this.configDir }
|
|
67
67
|
: process.env;
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
shell: true,
|
|
73
|
-
env,
|
|
74
|
-
})) as { stdout: string; stderr: string };
|
|
69
|
+
// Buffers to capture output
|
|
70
|
+
let stdout = "";
|
|
71
|
+
let stderr = "";
|
|
75
72
|
|
|
76
|
-
|
|
73
|
+
// Create the subprocess
|
|
74
|
+
const subprocess = execa(this.dockerPath, args, {
|
|
75
|
+
env: env,
|
|
76
|
+
// Don't buffer - we'll handle streams manually
|
|
77
|
+
buffer: false,
|
|
78
|
+
encoding: "utf8",
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Stream stdout in real-time
|
|
82
|
+
subprocess.stdout?.on("data", (chunk: string) => {
|
|
83
|
+
process.stdout.write(chunk);
|
|
84
|
+
stdout += chunk;
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Stream stderr in real-time
|
|
88
|
+
subprocess.stderr?.on("data", (chunk: string) => {
|
|
89
|
+
process.stderr.write(chunk);
|
|
90
|
+
stderr += chunk;
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Wait for the process to complete
|
|
94
|
+
try {
|
|
95
|
+
await subprocess;
|
|
96
|
+
} catch (error: any) {
|
|
97
|
+
// Process failed, but we still have the output
|
|
98
|
+
throw new Error(stderr || error.message || "Command failed");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return { stdout, stderr };
|
|
77
102
|
}
|
|
78
103
|
|
|
79
104
|
/**
|
|
@@ -1,149 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { ResourceScope } from "../resource.ts";
|
|
4
|
-
import type { Scope } from "../scope.ts";
|
|
5
|
-
import { deserialize, serialize } from "../serde.ts";
|
|
6
|
-
import type { State, StateStore } from "../state.ts";
|
|
7
|
-
import { ignore } from "../util/ignore.ts";
|
|
1
|
+
import * as state from "../state/file-system-state-store.ts";
|
|
8
2
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export
|
|
13
|
-
public readonly dir: string;
|
|
14
|
-
private initialized = false;
|
|
15
|
-
constructor(
|
|
16
|
-
public readonly scope: Scope,
|
|
17
|
-
options?: {
|
|
18
|
-
rootDir?: string;
|
|
19
|
-
},
|
|
20
|
-
) {
|
|
21
|
-
this.dir = path.join(options?.rootDir ?? stateRootDir, ...scope.chain);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async init(): Promise<void> {
|
|
25
|
-
if (this.initialized) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
this.initialized = true;
|
|
29
|
-
await fs.promises.mkdir(this.dir, { recursive: true });
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async deinit(): Promise<void> {
|
|
33
|
-
await ignore("ENOENT", async () => {
|
|
34
|
-
const entries = await fs.promises.readdir(this.dir, {
|
|
35
|
-
withFileTypes: true,
|
|
36
|
-
});
|
|
37
|
-
const files = entries.filter((entry) => entry.isFile());
|
|
38
|
-
if (files.length > 0) {
|
|
39
|
-
throw new Error(
|
|
40
|
-
`Cannot deinit: directory "${this.dir}" contains files and cannot be deleted.`,
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
// Only folders (or empty), delete recursively
|
|
44
|
-
await fs.promises.rm(this.dir, { recursive: true, force: true });
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async count(): Promise<number> {
|
|
49
|
-
return Object.keys(await this.list()).length;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async list(): Promise<string[]> {
|
|
53
|
-
try {
|
|
54
|
-
const files = await fs.promises.readdir(this.dir, {
|
|
55
|
-
withFileTypes: true,
|
|
56
|
-
});
|
|
57
|
-
return files
|
|
58
|
-
.filter((dirent) => dirent.isFile() && dirent.name.endsWith(".json"))
|
|
59
|
-
.map((dirent) => dirent.name.replace(/\.json$/, ""))
|
|
60
|
-
.map((key) => key.replaceAll(":", "/"));
|
|
61
|
-
} catch (error: any) {
|
|
62
|
-
if (error.code === "ENOENT") {
|
|
63
|
-
return [];
|
|
64
|
-
}
|
|
65
|
-
throw error;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async get(key: string): Promise<State | undefined> {
|
|
70
|
-
try {
|
|
71
|
-
const content = await fs.promises.readFile(this.getPath(key), "utf8");
|
|
72
|
-
const state = (await deserialize(
|
|
73
|
-
this.scope,
|
|
74
|
-
JSON.parse(content),
|
|
75
|
-
)) as State;
|
|
76
|
-
if (state.output === undefined) {
|
|
77
|
-
state.output = {} as any;
|
|
78
|
-
}
|
|
79
|
-
state.output[ResourceScope] = this.scope;
|
|
80
|
-
return state;
|
|
81
|
-
} catch (error: any) {
|
|
82
|
-
if (error.code === "ENOENT") {
|
|
83
|
-
return undefined;
|
|
84
|
-
}
|
|
85
|
-
throw error;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
async set(key: string, value: State): Promise<void> {
|
|
90
|
-
await this.init();
|
|
91
|
-
const file = this.getPath(key);
|
|
92
|
-
await fs.promises.mkdir(path.dirname(file), { recursive: true });
|
|
93
|
-
await fs.promises.writeFile(
|
|
94
|
-
file,
|
|
95
|
-
JSON.stringify(await serialize(this.scope, value), null, 2),
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
async delete(key: string): Promise<void> {
|
|
100
|
-
try {
|
|
101
|
-
return await fs.promises.unlink(this.getPath(key));
|
|
102
|
-
} catch (error: any) {
|
|
103
|
-
if (error.code === "ENOENT") {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
throw error;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
async all(): Promise<Record<string, State>> {
|
|
111
|
-
return this.getBatch(await this.list());
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
async getBatch(ids: string[]): Promise<Record<string, State>> {
|
|
115
|
-
return Object.fromEntries(
|
|
116
|
-
(
|
|
117
|
-
await Promise.all(
|
|
118
|
-
Array.from(ids).flatMap(async (id) => {
|
|
119
|
-
const s = await this.get(id);
|
|
120
|
-
if (s === undefined) {
|
|
121
|
-
return [] as const;
|
|
122
|
-
}
|
|
123
|
-
return [[id, s]] as const;
|
|
124
|
-
}),
|
|
125
|
-
)
|
|
126
|
-
).flat(),
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
private getPath(key: string): string {
|
|
131
|
-
if (key.includes(":")) {
|
|
132
|
-
throw new Error(`ID cannot include colons: ${key}`);
|
|
133
|
-
}
|
|
134
|
-
if (key.includes("/")) {
|
|
135
|
-
//todo(michael): remove this next time we do a breaking change
|
|
136
|
-
//* windows doesn't support ":" in file paths, but we already use ":"
|
|
137
|
-
//* so now we use both to prevent breaking changes
|
|
138
|
-
key = key.replaceAll("/", ALCHEMY_SEPERATOR_CHAR);
|
|
139
|
-
}
|
|
140
|
-
//todo(michael): remove this next time we do a breaking change
|
|
141
|
-
//* windows doesn't support "*" in file paths, but we already use "*"
|
|
142
|
-
//* when making cloudflare routes containing "*"
|
|
143
|
-
//* so now we use "+" on windows but "*" on mac/linux to prevent breaking changes
|
|
144
|
-
if (process.platform === "win32") {
|
|
145
|
-
key = key.replaceAll("*", "+");
|
|
146
|
-
}
|
|
147
|
-
return path.join(this.dir, `${key}.json`);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
3
|
+
/**
|
|
4
|
+
* @deprecated Use `FileSystemStateStore` from `alchemy/state` instead.
|
|
5
|
+
*/
|
|
6
|
+
export const FileSystemStateStore = state.FileSystemStateStore;
|
package/src/fs/index.ts
CHANGED
package/src/llms.cloudflare.txt
CHANGED
|
@@ -41,8 +41,9 @@ ALCHEMY_STATE_STORE=cloudflare
|
|
|
41
41
|
|
|
42
42
|
### Commands
|
|
43
43
|
```bash
|
|
44
|
-
bun
|
|
45
|
-
bun
|
|
44
|
+
bun alchemy deploy # Deploy
|
|
45
|
+
bun alchemy dev # Local development
|
|
46
|
+
bun alchemy destroy # Destroy all resources
|
|
46
47
|
```
|
|
47
48
|
|
|
48
49
|
## Workers
|
|
@@ -107,7 +108,7 @@ declare module "cloudflare:workers" {
|
|
|
107
108
|
### Creating Durable Object Namespace
|
|
108
109
|
```typescript
|
|
109
110
|
// Use 'new' instead of 'await' for DurableObjectNamespace
|
|
110
|
-
const counter =
|
|
111
|
+
const counter = DurableObjectNamespace("counter", {
|
|
111
112
|
className: "Counter",
|
|
112
113
|
sqlite: true, // Enable SQLite storage
|
|
113
114
|
});
|
|
@@ -161,7 +162,7 @@ export default {
|
|
|
161
162
|
const sharedCounter = host.bindings.SHARED_COUNTER;
|
|
162
163
|
|
|
163
164
|
// Method 2: Reference by worker script name
|
|
164
|
-
const counter =
|
|
165
|
+
const counter = DurableObjectNamespace("counter", {
|
|
165
166
|
className: "Counter",
|
|
166
167
|
scriptName: "provider-worker"
|
|
167
168
|
});
|
|
@@ -353,7 +354,7 @@ describe("Worker Tests", () => {
|
|
|
353
354
|
## Common Issues
|
|
354
355
|
|
|
355
356
|
- **Missing finalize()**: Resources won't be cleaned up properly
|
|
356
|
-
- **Wrong DurableObject syntax**: Use `
|
|
357
|
+
- **Wrong DurableObject syntax**: Use `DurableObjectNamespace()` not `await`
|
|
357
358
|
- **Type errors**: Set up env.d.ts file for binding types
|
|
358
359
|
- **State conflicts**: Use different stages/prefixes for different environments
|
|
359
360
|
- **Resource adoption**: Use `adopt: true` when migrating existing resources
|