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,152 @@
|
|
|
1
|
+
import { and, eq, getTableColumns, inArray } from "drizzle-orm";
|
|
2
|
+
import type { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core";
|
|
3
|
+
import type { State, StateStore } from "../state.ts";
|
|
4
|
+
import { assertNever } from "../util/assert-never.ts";
|
|
5
|
+
import type { StateStoreProxy } from "./proxy.ts";
|
|
6
|
+
import * as schema from "./schema.ts";
|
|
7
|
+
|
|
8
|
+
const { scope: _, ...columns } = getTableColumns(schema.resources);
|
|
9
|
+
|
|
10
|
+
type Database = BaseSQLiteDatabase<any, any, typeof schema>;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Represents the SQL operations for a SQLite-backed state store.
|
|
14
|
+
* DOES NOT include serialization/deserialization — that is handled by the `StateStoreProxy` class.
|
|
15
|
+
*/
|
|
16
|
+
export class SQLiteStateStoreOperations implements StateStore {
|
|
17
|
+
constructor(
|
|
18
|
+
private readonly db: Database,
|
|
19
|
+
private readonly context: { chain: string[] },
|
|
20
|
+
) {}
|
|
21
|
+
|
|
22
|
+
async dispatch<TMethod extends StateStoreProxy.Method>(
|
|
23
|
+
method: TMethod,
|
|
24
|
+
params: StateStoreProxy.API[TMethod]["params"],
|
|
25
|
+
): Promise<StateStoreProxy.API[TMethod]["result"]> {
|
|
26
|
+
switch (method) {
|
|
27
|
+
case "init":
|
|
28
|
+
return;
|
|
29
|
+
case "deinit":
|
|
30
|
+
return;
|
|
31
|
+
case "list":
|
|
32
|
+
return this.list();
|
|
33
|
+
case "count":
|
|
34
|
+
return this.count();
|
|
35
|
+
case "get": {
|
|
36
|
+
const [key] = params as StateStoreProxy.API["get"]["params"];
|
|
37
|
+
return this.get(key);
|
|
38
|
+
}
|
|
39
|
+
case "getBatch": {
|
|
40
|
+
const [keys] = params as StateStoreProxy.API["getBatch"]["params"];
|
|
41
|
+
return this.getBatch(keys);
|
|
42
|
+
}
|
|
43
|
+
case "all":
|
|
44
|
+
return this.all();
|
|
45
|
+
case "set": {
|
|
46
|
+
const [key, state] = params as StateStoreProxy.API["set"]["params"];
|
|
47
|
+
return this.set(key, state);
|
|
48
|
+
}
|
|
49
|
+
case "delete": {
|
|
50
|
+
const [key] = params as StateStoreProxy.API["delete"]["params"];
|
|
51
|
+
return this.delete(key);
|
|
52
|
+
}
|
|
53
|
+
default:
|
|
54
|
+
assertNever(method);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async list() {
|
|
59
|
+
const result = await this.db
|
|
60
|
+
.select({ id: schema.resources.id })
|
|
61
|
+
.from(schema.resources)
|
|
62
|
+
.where(eq(schema.resources.scope, this.context.chain));
|
|
63
|
+
return result.map((r) => r.id);
|
|
64
|
+
}
|
|
65
|
+
async count() {
|
|
66
|
+
const result = await this.db.$count(
|
|
67
|
+
this.db
|
|
68
|
+
.select()
|
|
69
|
+
.from(schema.resources)
|
|
70
|
+
.where(eq(schema.resources.scope, this.context.chain)),
|
|
71
|
+
);
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
async get(key: string) {
|
|
75
|
+
const [result] = await this.db
|
|
76
|
+
.select(columns)
|
|
77
|
+
.from(schema.resources)
|
|
78
|
+
.where(
|
|
79
|
+
and(
|
|
80
|
+
eq(schema.resources.scope, this.context.chain),
|
|
81
|
+
eq(schema.resources.id, key),
|
|
82
|
+
),
|
|
83
|
+
);
|
|
84
|
+
if (!result) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
...result,
|
|
89
|
+
props: result.props ?? undefined,
|
|
90
|
+
oldProps: result.oldProps ?? undefined,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
async all() {
|
|
94
|
+
const result = await this.db
|
|
95
|
+
.select(columns)
|
|
96
|
+
.from(schema.resources)
|
|
97
|
+
.where(eq(schema.resources.scope, this.context.chain));
|
|
98
|
+
const record: Record<string, State> = {};
|
|
99
|
+
for (const r of result) {
|
|
100
|
+
record[r.id] = {
|
|
101
|
+
...r,
|
|
102
|
+
props: r.props ?? undefined,
|
|
103
|
+
oldProps: r.oldProps ?? undefined,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return record;
|
|
107
|
+
}
|
|
108
|
+
async set(_key: string, state: State) {
|
|
109
|
+
await this.db
|
|
110
|
+
.insert(schema.resources)
|
|
111
|
+
.values({
|
|
112
|
+
...state,
|
|
113
|
+
scope: this.context.chain,
|
|
114
|
+
})
|
|
115
|
+
.onConflictDoUpdate({
|
|
116
|
+
target: [schema.resources.id, schema.resources.scope],
|
|
117
|
+
set: {
|
|
118
|
+
...state,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
async delete(key: string) {
|
|
123
|
+
await this.db
|
|
124
|
+
.delete(schema.resources)
|
|
125
|
+
.where(
|
|
126
|
+
and(
|
|
127
|
+
eq(schema.resources.scope, this.context.chain),
|
|
128
|
+
eq(schema.resources.id, key),
|
|
129
|
+
),
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
async getBatch(keys: string[]) {
|
|
133
|
+
const result = await this.db
|
|
134
|
+
.select(columns)
|
|
135
|
+
.from(schema.resources)
|
|
136
|
+
.where(
|
|
137
|
+
and(
|
|
138
|
+
eq(schema.resources.scope, this.context.chain),
|
|
139
|
+
inArray(schema.resources.id, keys),
|
|
140
|
+
),
|
|
141
|
+
);
|
|
142
|
+
const record: Record<string, State> = {};
|
|
143
|
+
for (const r of result) {
|
|
144
|
+
record[r.id] = {
|
|
145
|
+
...r,
|
|
146
|
+
props: r.props ?? undefined,
|
|
147
|
+
oldProps: r.oldProps ?? undefined,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return record;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { Scope } from "../scope.ts";
|
|
2
|
+
import type { State, StateStore } from "../state.ts";
|
|
3
|
+
import { withExponentialBackoff } from "../util/retry.ts";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Wraps a local or remote state store implementation
|
|
7
|
+
* and handles serialization/deserialization.
|
|
8
|
+
*/
|
|
9
|
+
export abstract class StateStoreProxy implements StateStore {
|
|
10
|
+
private dispatch?: Promise<StateStoreProxy.Dispatch>;
|
|
11
|
+
|
|
12
|
+
constructor(readonly scope: Scope) {}
|
|
13
|
+
|
|
14
|
+
abstract provision(): Promise<StateStoreProxy.Dispatch>;
|
|
15
|
+
|
|
16
|
+
private async run<TMethod extends StateStoreProxy.Method>(
|
|
17
|
+
method: TMethod,
|
|
18
|
+
params: StateStoreProxy.API[TMethod]["params"],
|
|
19
|
+
): Promise<StateStoreProxy.API[TMethod]["result"]> {
|
|
20
|
+
this.dispatch ??= this.provision();
|
|
21
|
+
return this.dispatch.then(async (dispatch) => {
|
|
22
|
+
const result = await withExponentialBackoff(
|
|
23
|
+
() => dispatch(method, params),
|
|
24
|
+
() => true,
|
|
25
|
+
);
|
|
26
|
+
return result;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
init(): Promise<void> {
|
|
31
|
+
return this.run("init", []);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
deinit(): Promise<void> {
|
|
35
|
+
return this.run("deinit", []);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
list(): Promise<string[]> {
|
|
39
|
+
return this.run("list", []);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
count(): Promise<number> {
|
|
43
|
+
return this.run("count", []);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async get(key: string): Promise<State | undefined> {
|
|
47
|
+
const result = await this.run("get", [key]);
|
|
48
|
+
if (result === undefined) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
return await this.deserialize(result);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async getBatch(ids: string[]): Promise<Record<string, State>> {
|
|
55
|
+
return this.deserializeMany(await this.run("getBatch", [ids]));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async all(): Promise<Record<string, State>> {
|
|
59
|
+
return this.deserializeMany(await this.run("all", []));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async set(key: string, value: State): Promise<void> {
|
|
63
|
+
return this.run("set", [key, await this.serialize(value)]);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async delete(key: string): Promise<void> {
|
|
67
|
+
return this.run("delete", [key]);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private async deserialize(state: State): Promise<State> {
|
|
71
|
+
const { deserialize } = await import("../serde.ts"); // dynamic import to avoid circular dependency
|
|
72
|
+
return await deserialize(this.scope, state);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private async serialize(state: State) {
|
|
76
|
+
const { serialize } = await import("../serde.ts");
|
|
77
|
+
return await serialize(this.scope, state);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private async deserializeMany(states: Record<string, State>) {
|
|
81
|
+
return Object.fromEntries(
|
|
82
|
+
await Promise.all(
|
|
83
|
+
Object.entries(states).map(async ([key, value]) => [
|
|
84
|
+
key,
|
|
85
|
+
await this.deserialize(value),
|
|
86
|
+
]),
|
|
87
|
+
),
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export declare namespace StateStoreProxy {
|
|
93
|
+
export type API = {
|
|
94
|
+
[K in keyof Required<StateStore>]: NonNullable<StateStore[K]> extends (
|
|
95
|
+
...args: infer Args
|
|
96
|
+
) => Promise<infer Return>
|
|
97
|
+
? {
|
|
98
|
+
method: K;
|
|
99
|
+
params: Args;
|
|
100
|
+
result: Return;
|
|
101
|
+
}
|
|
102
|
+
: never;
|
|
103
|
+
};
|
|
104
|
+
export type Method = keyof API;
|
|
105
|
+
|
|
106
|
+
export type Dispatch = <TMethod extends Method>(
|
|
107
|
+
method: TMethod,
|
|
108
|
+
params: API[TMethod]["params"],
|
|
109
|
+
) => Promise<API[TMethod]["result"]>;
|
|
110
|
+
|
|
111
|
+
export type Request<TMethod extends Method, TContext = unknown> = {
|
|
112
|
+
method: TMethod;
|
|
113
|
+
params: API[TMethod]["params"];
|
|
114
|
+
context: TContext;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export type SuccessResponse<TMethod extends Method> = {
|
|
118
|
+
success: true;
|
|
119
|
+
status: number;
|
|
120
|
+
result: API[TMethod]["result"];
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export type ErrorResponse = {
|
|
124
|
+
success: false;
|
|
125
|
+
status: number;
|
|
126
|
+
error: string;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export type Response<TMethod extends Method> =
|
|
130
|
+
| SuccessResponse<TMethod>
|
|
131
|
+
| ErrorResponse;
|
|
132
|
+
}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { Scope } from "../scope.ts";
|
|
3
|
-
import { serialize, deserialize } from "../serde.ts";
|
|
4
|
-
import type { State, StateStore } from "../state.ts";
|
|
5
|
-
import { withExponentialBackoff } from "../util/retry.ts";
|
|
6
|
-
import { CloudflareApiError, handleApiError } from "./api-error.ts";
|
|
1
|
+
import { CloudflareApiError, handleApiError } from "../cloudflare/api-error.ts";
|
|
7
2
|
import {
|
|
8
3
|
type CloudflareApi,
|
|
9
4
|
type CloudflareApiOptions,
|
|
10
5
|
createCloudflareApi,
|
|
11
|
-
} from "
|
|
12
|
-
import {
|
|
6
|
+
} from "../cloudflare/api.ts";
|
|
7
|
+
import { ResourceScope } from "../resource.ts";
|
|
8
|
+
import type { Scope } from "../scope.ts";
|
|
9
|
+
import { deserialize, serialize } from "../serde.ts";
|
|
10
|
+
import type { State, StateStore } from "../state.ts";
|
|
11
|
+
import { withExponentialBackoff } from "../util/retry.ts";
|
|
13
12
|
|
|
14
13
|
/**
|
|
15
14
|
* Options for CloudflareR2StateStore
|
|
@@ -31,6 +30,8 @@ export interface CloudflareR2StateStoreOptions extends CloudflareApiOptions {
|
|
|
31
30
|
/**
|
|
32
31
|
* State store implementation using Cloudflare R2 API
|
|
33
32
|
* Uses R2 for immediate consistency compared to KV's eventual consistency
|
|
33
|
+
*
|
|
34
|
+
* @deprecated Use `CloudflareStateStore` from `alchemy/state` instead.
|
|
34
35
|
*/
|
|
35
36
|
export class R2RestStateStore implements StateStore {
|
|
36
37
|
private api: CloudflareApi;
|
|
@@ -66,6 +67,8 @@ export class R2RestStateStore implements StateStore {
|
|
|
66
67
|
async init(): Promise<void> {
|
|
67
68
|
if (this.initialized) return;
|
|
68
69
|
|
|
70
|
+
const { createBucket, getBucket } = await import("../cloudflare/bucket.ts");
|
|
71
|
+
|
|
69
72
|
// Create Cloudflare API client with automatic account discovery
|
|
70
73
|
this.api = await createCloudflareApi(this.options);
|
|
71
74
|
|
|
@@ -3,10 +3,9 @@ import fs from "node:fs";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import type { Scope } from "../scope.ts";
|
|
5
5
|
import { memoize } from "../util/memoize.ts";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "./base-sqlite-state-store.ts";
|
|
6
|
+
import { MIGRATIONS_DIRECTORY } from "./migrations.ts";
|
|
7
|
+
import { SQLiteStateStoreOperations } from "./operations.ts";
|
|
8
|
+
import { StateStoreProxy } from "./proxy.ts";
|
|
10
9
|
import * as schema from "./schema.ts";
|
|
11
10
|
|
|
12
11
|
interface BunSQLiteStateStoreOptions {
|
|
@@ -73,11 +72,20 @@ type SQLiteStateStoreOptions =
|
|
|
73
72
|
| LibSQLStateStoreOptions
|
|
74
73
|
| AutoSQLiteStateStoreOptions;
|
|
75
74
|
|
|
76
|
-
export class SQLiteStateStore extends
|
|
77
|
-
constructor(
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
export class SQLiteStateStore extends StateStoreProxy {
|
|
76
|
+
constructor(
|
|
77
|
+
scope: Scope,
|
|
78
|
+
private options?: SQLiteStateStoreOptions,
|
|
79
|
+
) {
|
|
80
|
+
super(scope);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async provision(): Promise<StateStoreProxy.Dispatch> {
|
|
84
|
+
const db = await createDatabase(this.options);
|
|
85
|
+
const operations = new SQLiteStateStoreOperations(db, {
|
|
86
|
+
chain: this.scope.chain,
|
|
80
87
|
});
|
|
88
|
+
return operations.dispatch.bind(operations);
|
|
81
89
|
}
|
|
82
90
|
}
|
|
83
91
|
|
|
@@ -132,7 +140,7 @@ async function createBunSQLiteDatabase(
|
|
|
132
140
|
const db = drizzle(client, {
|
|
133
141
|
schema,
|
|
134
142
|
});
|
|
135
|
-
migrate(db, { migrationsFolder:
|
|
143
|
+
migrate(db, { migrationsFolder: MIGRATIONS_DIRECTORY });
|
|
136
144
|
return db;
|
|
137
145
|
}
|
|
138
146
|
|
|
@@ -162,7 +170,7 @@ async function createLibSQLDatabase(
|
|
|
162
170
|
const db = drizzle(client, {
|
|
163
171
|
schema,
|
|
164
172
|
});
|
|
165
|
-
await migrate(db, { migrationsFolder:
|
|
173
|
+
await migrate(db, { migrationsFolder: MIGRATIONS_DIRECTORY });
|
|
166
174
|
return db;
|
|
167
175
|
}
|
|
168
176
|
|
package/src/test/vitest.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { afterAll, beforeAll, it } from "vitest";
|
|
3
3
|
import { alchemy } from "../alchemy.ts";
|
|
4
|
-
import { D1StateStore } from "../cloudflare/d1-state-store.ts";
|
|
5
|
-
import { DOStateStore } from "../cloudflare/do-state-store/index.ts";
|
|
6
|
-
import { FileSystemStateStore } from "../fs/file-system-state-store.ts";
|
|
7
4
|
import { Scope } from "../scope.ts";
|
|
8
|
-
import { SQLiteStateStore } from "../sqlite/sqlite-state-store.ts";
|
|
9
5
|
import type { StateStoreType } from "../state.ts";
|
|
6
|
+
import {
|
|
7
|
+
CloudflareStateStore,
|
|
8
|
+
D1StateStore,
|
|
9
|
+
FileSystemStateStore,
|
|
10
|
+
SQLiteStateStore,
|
|
11
|
+
} from "../state/index.ts";
|
|
10
12
|
import { NoopTelemetryClient } from "../util/telemetry/client.ts";
|
|
11
13
|
|
|
12
14
|
/**
|
|
@@ -129,8 +131,8 @@ export function test(
|
|
|
129
131
|
defaultOptions.stateStore ??= (scope) => {
|
|
130
132
|
const storeType = process.env.ALCHEMY_STATE_STORE;
|
|
131
133
|
switch (storeType) {
|
|
132
|
-
case "
|
|
133
|
-
return new
|
|
134
|
+
case "do":
|
|
135
|
+
return new CloudflareStateStore(scope);
|
|
134
136
|
case "fs":
|
|
135
137
|
return new FileSystemStateStore(scope);
|
|
136
138
|
case "d1":
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare var Deno: any;
|
|
2
|
+
declare var Bun: any;
|
|
3
|
+
|
|
4
|
+
export type Runtime = "bun" | "deno" | "node";
|
|
5
|
+
|
|
6
|
+
export function detectRuntime(): Runtime {
|
|
7
|
+
if (typeof Bun !== "undefined" && Bun !== null) return "bun";
|
|
8
|
+
if (typeof Deno !== "undefined" && Deno !== null) return "deno";
|
|
9
|
+
if (typeof process !== "undefined" && process.release?.name === "node")
|
|
10
|
+
return "node";
|
|
11
|
+
return "node";
|
|
12
|
+
}
|
|
@@ -1,18 +1,31 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { exists } from "./exists.ts";
|
|
2
2
|
|
|
3
|
-
export type PackageManager = "bun" | "pnpm" | "yarn" | "npm";
|
|
3
|
+
export type PackageManager = "bun" | "pnpm" | "yarn" | "npm" | "deno";
|
|
4
4
|
|
|
5
|
-
export function detectPackageManager(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (
|
|
5
|
+
export async function detectPackageManager(
|
|
6
|
+
path: string = process.cwd(),
|
|
7
|
+
): Promise<PackageManager> {
|
|
8
|
+
if (await exists(`${path}/deno.lock`)) return "deno";
|
|
9
|
+
if (
|
|
10
|
+
(await exists(`${path}/deno.json`)) ||
|
|
11
|
+
(await exists(`${path}/deno.jsonc`))
|
|
12
|
+
)
|
|
13
|
+
return "deno";
|
|
14
|
+
if (await exists(`${path}/bun.lockb`)) return "bun";
|
|
15
|
+
if (await exists(`${path}/pnpm-lock.yaml`)) return "pnpm";
|
|
16
|
+
if (await exists(`${path}/yarn.lock`)) return "yarn";
|
|
9
17
|
|
|
10
18
|
if (process.env.npm_execpath?.includes("bun")) {
|
|
11
19
|
return "bun";
|
|
12
20
|
}
|
|
13
21
|
|
|
22
|
+
if (process.env.DENO) {
|
|
23
|
+
return "deno";
|
|
24
|
+
}
|
|
25
|
+
|
|
14
26
|
const userAgent = process.env.npm_config_user_agent;
|
|
15
27
|
if (userAgent) {
|
|
28
|
+
if (userAgent.startsWith("deno")) return "deno";
|
|
16
29
|
if (userAgent.startsWith("bun")) return "bun";
|
|
17
30
|
if (userAgent.startsWith("pnpm")) return "pnpm";
|
|
18
31
|
if (userAgent.startsWith("yarn")) return "yarn";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import http from "node:http";
|
|
2
2
|
import type { AddressInfo } from "node:net";
|
|
3
3
|
import { Readable } from "node:stream";
|
|
4
|
-
import { promiseWithResolvers } from "
|
|
4
|
+
import { promiseWithResolvers } from "./promise-with-resolvers.ts";
|
|
5
5
|
|
|
6
6
|
export class HTTPServer {
|
|
7
7
|
server: http.Server;
|
package/src/util/memoize.ts
CHANGED
|
@@ -24,12 +24,6 @@ export function memoize<F extends (...args: any[]) => Promise<any>>(
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const defaultKeyFn = (...args: any[]) => {
|
|
28
|
-
|
|
29
|
-
args.forEach((arg) => {
|
|
30
|
-
if (arg) {
|
|
31
|
-
hash.update(JSON.stringify(arg));
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
return hash.digest("hex");
|
|
27
|
+
export const defaultKeyFn = (...args: any[]) => {
|
|
28
|
+
return createHash("sha256").update(JSON.stringify(args)).digest("hex");
|
|
35
29
|
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { err, ok, ResultAsync, type Result } from "neverthrow";
|
|
2
|
+
import { promiseWithResolvers } from "./promise-with-resolvers.ts";
|
|
3
|
+
|
|
4
|
+
export const ensure = <T, E>(
|
|
5
|
+
result: ResultAsync<T, E>,
|
|
6
|
+
finalizer: () => any,
|
|
7
|
+
) => {
|
|
8
|
+
return result.andTee(finalizer).orTee(finalizer);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const detached = <T, E>() => {
|
|
12
|
+
const { promise, resolve } = promiseWithResolvers<Result<T, E>>();
|
|
13
|
+
return {
|
|
14
|
+
result: new ResultAsync(promise),
|
|
15
|
+
ok: (value: T) => resolve(ok(value)),
|
|
16
|
+
err: (error: E) => resolve(err(error)),
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const singleFlight = <Args extends any[], Value, Error>(
|
|
21
|
+
fn: (...args: Args) => ResultAsync<Value, Error>,
|
|
22
|
+
) => {
|
|
23
|
+
const results = new Map<string, ResultAsync<Value, Error>>();
|
|
24
|
+
return (...args: Args): ResultAsync<Value, Error> => {
|
|
25
|
+
const key = JSON.stringify(args ?? []);
|
|
26
|
+
const cached = results.get(key);
|
|
27
|
+
if (cached) {
|
|
28
|
+
return cached;
|
|
29
|
+
}
|
|
30
|
+
const result = fn(...args);
|
|
31
|
+
results.set(key, result);
|
|
32
|
+
return ensure(result, () => {
|
|
33
|
+
results.delete(key);
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export class HTTPError extends Error {
|
|
39
|
+
constructor(
|
|
40
|
+
message: string,
|
|
41
|
+
public readonly status: number,
|
|
42
|
+
) {
|
|
43
|
+
super(message);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// TODO: merge this with safe-fetch?
|
|
48
|
+
export const fetchResult = (url: string, init: RequestInit = {}) => {
|
|
49
|
+
return ResultAsync.fromPromise(
|
|
50
|
+
fetch(url, init),
|
|
51
|
+
() => new HTTPError(`Failed to ${init.method ?? "GET"} ${url}`, 0),
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const fetchJSON = <T, E>(url: string, init: RequestInit = {}) => {
|
|
56
|
+
return fetchResult(url, init).andThen(decodeJSON<T, E>);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const decodeJSON = <T, E>(response: Response) => {
|
|
60
|
+
return ResultAsync.fromPromise(
|
|
61
|
+
response.json(),
|
|
62
|
+
() => new HTTPError("Failed to decode JSON", response.status),
|
|
63
|
+
).andThen((json) => (response.ok ? ok(json as T) : err(json as E)));
|
|
64
|
+
};
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
"scripts": {
|
|
6
6
|
"astro": "astro",
|
|
7
7
|
"build": "astro check && astro build",
|
|
8
|
-
"deploy": "
|
|
9
|
-
"destroy": "
|
|
10
|
-
"dev": "
|
|
8
|
+
"deploy": "alchemy deploy",
|
|
9
|
+
"destroy": "alchemy destroy",
|
|
10
|
+
"dev": "alchemy dev",
|
|
11
11
|
"preview": "astro preview"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
"private": true,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "nuxt build",
|
|
7
|
-
"deploy": "
|
|
8
|
-
"destroy": "
|
|
9
|
-
"dev": "
|
|
7
|
+
"deploy": "alchemy deploy",
|
|
8
|
+
"destroy": "alchemy destroy",
|
|
9
|
+
"dev": "alchemy dev",
|
|
10
10
|
"generate": "nuxt generate",
|
|
11
11
|
"postinstall": "nuxt prepare",
|
|
12
12
|
"preview": "nuxt preview"
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
"private": true,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "vite build",
|
|
7
|
-
"deploy": "
|
|
8
|
-
"destroy": "
|
|
9
|
-
"dev": "
|
|
7
|
+
"deploy": "alchemy deploy",
|
|
8
|
+
"destroy": "alchemy destroy",
|
|
9
|
+
"dev": "alchemy dev",
|
|
10
10
|
"preview": "bun run build && vite preview",
|
|
11
11
|
"typecheck": "react-router typegen && tsc -b"
|
|
12
12
|
},
|
|
@@ -15,7 +15,7 @@ export const worker = await Redwood("website", {
|
|
|
15
15
|
bindings: {
|
|
16
16
|
AUTH_SECRET_KEY: alchemy.secret(process.env.AUTH_SECRET_KEY),
|
|
17
17
|
DB: database,
|
|
18
|
-
SESSION_DURABLE_OBJECT:
|
|
18
|
+
SESSION_DURABLE_OBJECT: DurableObjectNamespace("session", {
|
|
19
19
|
className: "SessionDurableObject",
|
|
20
20
|
}),
|
|
21
21
|
},
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
"check": "npm run generate && npm run types",
|
|
14
14
|
"clean": "npm run clean:vite",
|
|
15
15
|
"clean:vite": "rm -rf ./node_modules/.vite",
|
|
16
|
-
"deploy": "
|
|
17
|
-
"destroy": "
|
|
18
|
-
"dev": "
|
|
16
|
+
"deploy": "alchemy deploy",
|
|
17
|
+
"destroy": "alchemy destroy",
|
|
18
|
+
"dev": "alchemy dev",
|
|
19
19
|
"dev:init": "rw-scripts dev-init",
|
|
20
20
|
"generate": "rw-scripts ensure-env && prisma generate && wrangler types",
|
|
21
21
|
"migrate:dev": "prisma generate && wrangler d1 migrations apply DB --local",
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
"build": "vite build",
|
|
8
8
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
9
9
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
10
|
-
"deploy": "
|
|
11
|
-
"destroy": "
|
|
12
|
-
"dev": "
|
|
10
|
+
"deploy": "alchemy deploy",
|
|
11
|
+
"destroy": "alchemy destroy",
|
|
12
|
+
"dev": "alchemy dev",
|
|
13
13
|
"prepare": "svelte-kit sync || echo ''",
|
|
14
14
|
"preview": "vite preview"
|
|
15
15
|
},
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "vite build",
|
|
8
|
-
"deploy": "
|
|
9
|
-
"destroy": "
|
|
10
|
-
"dev": "
|
|
8
|
+
"deploy": "alchemy deploy",
|
|
9
|
+
"destroy": "alchemy destroy",
|
|
10
|
+
"dev": "alchemy dev",
|
|
11
11
|
"start": "node .output/server/index.mjs"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "tsc -b",
|
|
8
|
-
"deploy": "
|
|
9
|
-
"destroy": "
|
|
8
|
+
"deploy": "alchemy deploy",
|
|
9
|
+
"destroy": "alchemy destroy",
|
|
10
|
+
"dev": "alchemy dev"
|
|
10
11
|
},
|
|
11
12
|
"devDependencies": {
|
|
12
13
|
"alchemy": "workspace:*",
|