@alchemy.run/drizzle 0.0.0-stage → 2.0.0-beta.84

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.
@@ -0,0 +1,45 @@
1
+ import type { LibSQLConfig, LibSQLSource } from "@alchemy.run/sql/SQLite";
2
+ import type * as LibsqlClient from "@effect/sql-libsql/LibsqlClient";
3
+ import type { AnyRelations, EmptyRelations } from "drizzle-orm";
4
+ import type { EffectLibsqlDatabase } from "drizzle-orm/effect-libsql";
5
+ import type { EffectDrizzleSQLiteConfig } from "drizzle-orm/sqlite-core/effect/utils";
6
+ import * as Effect from "effect/Effect";
7
+ /**
8
+ * Open a Drizzle database over a libSQL database (e.g. Turso) using the
9
+ * `drizzle-orm/effect-libsql` integration.
10
+ *
11
+ * Accepts the client returned by `Turso.Connect(db)` — or any
12
+ * `{ url, authToken }` — and returns a chainable Proxy over
13
+ * `EffectLibsqlDatabase` (via `proxyChain`): every property read records a
14
+ * step, every call records args, and the chain is replayed against the
15
+ * resolved drizzle db when it's finally yielded as an Effect. Callers don't
16
+ * need a separate `yield* conn` step:
17
+ *
18
+ * ```typescript
19
+ * const conn = yield* Turso.Connect(Db);
20
+ * const db = yield* Drizzle.LibSQL(conn, { relations });
21
+ *
22
+ * fetch: Effect.gen(function* () {
23
+ * const rows = yield* db.select().from(users);
24
+ * });
25
+ * ```
26
+ *
27
+ * The client is built lazily on the first query and memoized on the
28
+ * current execution's `Scope` (via {@link makeExecutionMemo}), so it is
29
+ * created at most once per execution — a Worker `fetch`/`queue`/`scheduled`
30
+ * event, a Durable Object call, a Workflow run, or a Lambda invocation —
31
+ * and closed when that execution settles. Resolving the URL and token is
32
+ * likewise deferred, so deploy / plan-time invocations never connect.
33
+ *
34
+ * `@effect/sql-libsql` client options (e.g. `intMode`) are passed via
35
+ * `config.client`.
36
+ *
37
+ * @binding
38
+ */
39
+ export declare const LibSQL: <TRelations extends AnyRelations = EmptyRelations, E = never, R = never>(source: LibSQLSource<E, R>, config?: EffectDrizzleSQLiteConfig<TRelations> & {
40
+ /** Overrides for the underlying `@effect/sql-libsql` client. */
41
+ readonly client?: LibSQLConfig;
42
+ }) => Effect.Effect<EffectLibsqlDatabase<TRelations> & {
43
+ $client: LibsqlClient.LibsqlClient;
44
+ }, never, never>;
45
+ //# sourceMappingURL=LibSQL.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LibSQL.d.ts","sourceRoot":"","sources":["../src/LibSQL.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAI1E,OAAO,KAAK,KAAK,YAAY,MAAM,iCAAiC,CAAC;AAGrE,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACtF,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,MAAM,GAAI,UAAU,SAAS,YAAY,GAAG,cAAc,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,UACnF,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,WACjB,yBAAyB,CAAC,UAAU,CAAC,GAAG;IAC/C,gEAAgE;IAChE,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;CAChC;aAsB4D,YAAY,CAAC,YAAY;gBAKrF,CAAC"}
package/lib/LibSQL.js ADDED
@@ -0,0 +1,47 @@
1
+ import { makeExecutionMemo } from "alchemy/Runtime/ExecutionMemo";
2
+ import { proxyChain } from "alchemy/Util/proxy-chain";
3
+ import * as Effect from "effect/Effect";
4
+ import * as Layer from "effect/Layer";
5
+ /**
6
+ * Open a Drizzle database over a libSQL database (e.g. Turso) using the
7
+ * `drizzle-orm/effect-libsql` integration.
8
+ *
9
+ * Accepts the client returned by `Turso.Connect(db)` — or any
10
+ * `{ url, authToken }` — and returns a chainable Proxy over
11
+ * `EffectLibsqlDatabase` (via `proxyChain`): every property read records a
12
+ * step, every call records args, and the chain is replayed against the
13
+ * resolved drizzle db when it's finally yielded as an Effect. Callers don't
14
+ * need a separate `yield* conn` step:
15
+ *
16
+ * ```typescript
17
+ * const conn = yield* Turso.Connect(Db);
18
+ * const db = yield* Drizzle.LibSQL(conn, { relations });
19
+ *
20
+ * fetch: Effect.gen(function* () {
21
+ * const rows = yield* db.select().from(users);
22
+ * });
23
+ * ```
24
+ *
25
+ * The client is built lazily on the first query and memoized on the
26
+ * current execution's `Scope` (via {@link makeExecutionMemo}), so it is
27
+ * created at most once per execution — a Worker `fetch`/`queue`/`scheduled`
28
+ * event, a Durable Object call, a Workflow run, or a Lambda invocation —
29
+ * and closed when that execution settles. Resolving the URL and token is
30
+ * likewise deferred, so deploy / plan-time invocations never connect.
31
+ *
32
+ * `@effect/sql-libsql` client options (e.g. `intMode`) are passed via
33
+ * `config.client`.
34
+ *
35
+ * @binding
36
+ */
37
+ export const LibSQL = (source, config) => Effect.map(makeExecutionMemo(Effect.gen(function* () {
38
+ const [LibsqlClient, LibsqlDrizzle, { resolveLibSQLConfig }] = yield* Effect.promise(() => Promise.all([
39
+ import("@effect/sql-libsql/LibsqlClient"),
40
+ import("drizzle-orm/effect-libsql"),
41
+ import("@alchemy.run/sql/SQLite"),
42
+ ]));
43
+ const { client, ...drizzleConfig } = config ?? {};
44
+ const ctx = yield* Layer.build(LibsqlClient.layer(yield* resolveLibSQLConfig(source, client)));
45
+ return yield* LibsqlDrizzle.makeWithDefaults(drizzleConfig).pipe(Effect.provideContext(ctx));
46
+ })), (db) => proxyChain(db));
47
+ //# sourceMappingURL=LibSQL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LibSQL.js","sourceRoot":"","sources":["../src/LibSQL.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAItD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CACpB,MAA0B,EAC1B,MAGC,EACD,EAAE,CACF,MAAM,CAAC,GAAG,CACR,iBAAiB,CACf,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,CAAC,YAAY,EAAE,aAAa,EAAE,EAAE,mBAAmB,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CACxF,OAAO,CAAC,GAAG,CAAC;QACV,MAAM,CAAC,iCAAiC,CAAC;QACzC,MAAM,CAAC,2BAA2B,CAAC;QACnC,MAAM,CAAC,yBAAyB,CAAC;KAClC,CAAC,CACH,CAAC;IACF,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;IAClD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAC5B,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAC/D,CAAC;IACF,OAAO,KAAK,CAAC,CAAC,aAAa,CAAC,gBAAgB,CAC1C,aAAsD,CACvD,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;AACrC,CAAC,CAAC,CACH,EACD,CAAC,EAAE,EAAE,EAAE,CACL,UAAU,CACR,EAEC,CACF,CACJ,CAAC"}
package/lib/MySQL.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ import type { MySQLConfig } from "@alchemy.run/sql/MySQL";
2
+ import type * as MysqlClient from "@effect/sql-mysql2/MysqlClient";
3
+ import type { AnyRelations, EmptyRelations } from "drizzle-orm";
4
+ import type { EffectMysql2Database } from "drizzle-orm/effect-mysql2";
5
+ import type { EffectDrizzleMySqlConfig } from "drizzle-orm/mysql-core/effect/utils";
6
+ import * as Effect from "effect/Effect";
7
+ import type * as Redacted from "effect/Redacted";
8
+ /**
9
+ * Open a Drizzle/MySQL database from a connection URL using the
10
+ * `drizzle-orm/effect-mysql2` integration.
11
+ *
12
+ * ```typescript
13
+ * const conn = yield* Cloudflare.Hyperdrive.Connect(Hyperdrive);
14
+ * const db = yield* Drizzle.MySQL(conn.connectionString, { relations });
15
+ *
16
+ * fetch: Effect.gen(function* () {
17
+ * const rows = yield* db.select().from(users);
18
+ * });
19
+ * ```
20
+ *
21
+ * The pool opens on the first query of an execution, is reused for every
22
+ * query in it, and closes when the event settles (see
23
+ * {@link makeExecutionMemo}); plan/deploy never connect. Workers defaults
24
+ * ({@link resolveMySQLConfig}) are overridden via `config.client`:
25
+ *
26
+ * ```typescript
27
+ * const db = yield* Drizzle.MySQL(connectionString, {
28
+ * relations,
29
+ * client: { poolConfig: { ssl: { rejectUnauthorized: true } } },
30
+ * });
31
+ * ```
32
+ *
33
+ * @binding
34
+ */
35
+ export declare const MySQL: <TRelations extends AnyRelations = EmptyRelations, E = never, R = never>(connectionString: Effect.Effect<Redacted.Redacted<string>, E, R>, config?: EffectDrizzleMySqlConfig<TRelations> & {
36
+ /**
37
+ * Overrides for the underlying `@effect/sql-mysql2` client — pool
38
+ * options (e.g. `poolConfig.ssl` for a direct TLS connection),
39
+ * `disablePreparedStatements`, `maxConnections`, and friends.
40
+ */
41
+ readonly client?: Omit<MySQLConfig, "url">;
42
+ }) => Effect.Effect<EffectMysql2Database<TRelations> & {
43
+ $client: MysqlClient.MysqlClient;
44
+ }, never, never>;
45
+ //# sourceMappingURL=MySQL.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MySQL.d.ts","sourceRoot":"","sources":["../src/MySQL.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAI1D,OAAO,KAAK,KAAK,WAAW,MAAM,gCAAgC,CAAC;AAGnE,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AACpF,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,KAAK,GAAI,UAAU,SAAS,YAAY,GAAG,cAAc,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,oBACxE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,WACvD,wBAAwB,CAAC,UAAU,CAAC,GAAG;IAC9C;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;CAC5C;aAwBgB,WAAW,CAAC,WAAW;gBAWvC,CAAC"}
package/lib/MySQL.js ADDED
@@ -0,0 +1,42 @@
1
+ import { makeExecutionMemo } from "alchemy/Runtime/ExecutionMemo";
2
+ import { proxyChain } from "alchemy/Util/proxy-chain";
3
+ import * as Effect from "effect/Effect";
4
+ import * as Layer from "effect/Layer";
5
+ /**
6
+ * Open a Drizzle/MySQL database from a connection URL using the
7
+ * `drizzle-orm/effect-mysql2` integration.
8
+ *
9
+ * ```typescript
10
+ * const conn = yield* Cloudflare.Hyperdrive.Connect(Hyperdrive);
11
+ * const db = yield* Drizzle.MySQL(conn.connectionString, { relations });
12
+ *
13
+ * fetch: Effect.gen(function* () {
14
+ * const rows = yield* db.select().from(users);
15
+ * });
16
+ * ```
17
+ *
18
+ * The pool opens on the first query of an execution, is reused for every
19
+ * query in it, and closes when the event settles (see
20
+ * {@link makeExecutionMemo}); plan/deploy never connect. Workers defaults
21
+ * ({@link resolveMySQLConfig}) are overridden via `config.client`:
22
+ *
23
+ * ```typescript
24
+ * const db = yield* Drizzle.MySQL(connectionString, {
25
+ * relations,
26
+ * client: { poolConfig: { ssl: { rejectUnauthorized: true } } },
27
+ * });
28
+ * ```
29
+ *
30
+ * @binding
31
+ */
32
+ export const MySQL = (connectionString, config) => Effect.map(makeExecutionMemo(Effect.gen(function* () {
33
+ const [MysqlClient, MySqlDrizzle, { resolveMySQLConfig }] = yield* Effect.promise(() => Promise.all([
34
+ import("@effect/sql-mysql2/MysqlClient"),
35
+ import("drizzle-orm/effect-mysql2"),
36
+ import("@alchemy.run/sql/MySQL"),
37
+ ]));
38
+ const { client, ...drizzleConfig } = config ?? {};
39
+ const mysqlCtx = yield* Layer.build(MysqlClient.layer(yield* resolveMySQLConfig({ ...client, url: connectionString })));
40
+ return yield* MySqlDrizzle.makeWithDefaults(drizzleConfig).pipe(Effect.provideContext(mysqlCtx));
41
+ })), (db) => proxyChain(db));
42
+ //# sourceMappingURL=MySQL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MySQL.js","sourceRoot":"","sources":["../src/MySQL.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAItD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,gBAAgE,EAChE,MAOC,EACD,EAAE,CACF,MAAM,CAAC,GAAG,CACR,iBAAiB,CACf,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,CAAC,WAAW,EAAE,YAAY,EAAE,EAAE,kBAAkB,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CACrF,OAAO,CAAC,GAAG,CAAC;QACV,MAAM,CAAC,gCAAgC,CAAC;QACxC,MAAM,CAAC,2BAA2B,CAAC;QACnC,MAAM,CAAC,wBAAwB,CAAC;KACjC,CAAC,CACH,CAAC;IACF,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;IAClD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CACjC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,kBAAkB,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,gBAAgB,EAAE,CAAC,CAAC,CACnF,CAAC;IACF,OAAO,KAAK,CAAC,CAAC,YAAY,CAAC,gBAAgB,CACzC,aAAqD,CACtD,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC1C,CAAC,CAAC,CACH,EACD,CAAC,EAAE,EAAE,EAAE,CACL,UAAU,CAKR,EAMC,CACF,CACJ,CAAC"}
@@ -0,0 +1,62 @@
1
+ import type * as PgClient from "@effect/sql-pg/PgClient";
2
+ import type { AnyRelations, EmptyRelations } from "drizzle-orm";
3
+ import type { EffectPgDatabase } from "drizzle-orm/effect-postgres";
4
+ import type { EffectDrizzlePgConfig } from "drizzle-orm/pg-core/effect/utils";
5
+ import * as Effect from "effect/Effect";
6
+ import type * as Redacted from "effect/Redacted";
7
+ /**
8
+ * Open a Drizzle/Postgres database from a connection URL using the
9
+ * `drizzle-orm/effect-postgres` integration.
10
+ *
11
+ * Returns a chainable Proxy over `EffectPgDatabase` (via `proxyChain`) —
12
+ * every property read records a step, every call records args, and the
13
+ * chain is replayed against the resolved drizzle db when it's finally
14
+ * yielded as an Effect. Callers don't need a separate `yield* conn` step:
15
+ *
16
+ * ```typescript
17
+ * const db = yield* Drizzle.Postgres(hd.connectionString);
18
+ *
19
+ * fetch: Effect.gen(function* () {
20
+ * const rows = yield* db.select().from(users);
21
+ * });
22
+ * ```
23
+ *
24
+ * The connect work is deferred until the first query and memoized on the
25
+ * current execution's `Scope` (via {@link makeExecutionMemo}), so the pool
26
+ * is built at most once per execution — a Worker `fetch`/`queue`/`scheduled`
27
+ * event, a Durable Object call, a Workflow run, or a Lambda invocation — and
28
+ * reused across every query and `task` step in that execution. Yielding the
29
+ * connection string is likewise deferred, so deploy / plan-time invocations
30
+ * (where `WorkerEnvironment` isn't provided) never trigger a real connection
31
+ * attempt.
32
+ *
33
+ * The pool is built against that same execution scope, so its `end`
34
+ * finalizer fires when the scope closes — when the request / run settles,
35
+ * not when the Worker's isolate-lifetime init completes. Wrapping queries in
36
+ * a nested `Effect.scoped` narrows both the memo and the pool's lifetime to
37
+ * that block: memo key and finalizer target are always the same scope
38
+ * object, so they cannot disagree.
39
+ *
40
+ * `@effect/sql-pg` client options are passed via `config.client`. Behind a
41
+ * transaction-mode pooler such as Hyperdrive, turn off named prepared
42
+ * statements, since a later query can reach a backend session that never
43
+ * prepared them:
44
+ *
45
+ * ```typescript
46
+ * const db = yield* Drizzle.Postgres(hd.connectionString, {
47
+ * client: { prepare: false },
48
+ * });
49
+ * ```
50
+ *
51
+ * @binding
52
+ */
53
+ export declare const Postgres: <TRelations extends AnyRelations = EmptyRelations, E = never, R = never>(connectionString: Effect.Effect<Redacted.Redacted<string>, E, R>, config?: EffectDrizzlePgConfig<TRelations> & {
54
+ /**
55
+ * Overrides for the underlying `@effect/sql-pg` client — `prepare`,
56
+ * `ssl`, pool limits, and friends. The URL comes from `connectionString`.
57
+ */
58
+ readonly client?: Omit<PgClient.PgPoolConfig, "url">;
59
+ }) => Effect.Effect<EffectPgDatabase<TRelations> & {
60
+ $client: PgClient.PgClient;
61
+ }, never, never>;
62
+ //# sourceMappingURL=Postgres.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Postgres.d.ts","sourceRoot":"","sources":["../src/Postgres.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AAGzD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,eAAO,MAAM,QAAQ,GAAI,UAAU,SAAS,YAAY,GAAG,cAAc,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,oBAC3E,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,WACvD,qBAAqB,CAAC,UAAU,CAAC,GAAG;IAC3C;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;CACtD;aAmBgB,QAAQ,CAAC,QAAQ;gBAWjC,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { resolvePoolConfig } from "@alchemy.run/sql/PostgresTls";
2
+ import { makeExecutionMemo } from "alchemy/Runtime/ExecutionMemo";
3
+ import { proxyChain } from "alchemy/Util/proxy-chain";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Layer from "effect/Layer";
6
+ /**
7
+ * Open a Drizzle/Postgres database from a connection URL using the
8
+ * `drizzle-orm/effect-postgres` integration.
9
+ *
10
+ * Returns a chainable Proxy over `EffectPgDatabase` (via `proxyChain`) —
11
+ * every property read records a step, every call records args, and the
12
+ * chain is replayed against the resolved drizzle db when it's finally
13
+ * yielded as an Effect. Callers don't need a separate `yield* conn` step:
14
+ *
15
+ * ```typescript
16
+ * const db = yield* Drizzle.Postgres(hd.connectionString);
17
+ *
18
+ * fetch: Effect.gen(function* () {
19
+ * const rows = yield* db.select().from(users);
20
+ * });
21
+ * ```
22
+ *
23
+ * The connect work is deferred until the first query and memoized on the
24
+ * current execution's `Scope` (via {@link makeExecutionMemo}), so the pool
25
+ * is built at most once per execution — a Worker `fetch`/`queue`/`scheduled`
26
+ * event, a Durable Object call, a Workflow run, or a Lambda invocation — and
27
+ * reused across every query and `task` step in that execution. Yielding the
28
+ * connection string is likewise deferred, so deploy / plan-time invocations
29
+ * (where `WorkerEnvironment` isn't provided) never trigger a real connection
30
+ * attempt.
31
+ *
32
+ * The pool is built against that same execution scope, so its `end`
33
+ * finalizer fires when the scope closes — when the request / run settles,
34
+ * not when the Worker's isolate-lifetime init completes. Wrapping queries in
35
+ * a nested `Effect.scoped` narrows both the memo and the pool's lifetime to
36
+ * that block: memo key and finalizer target are always the same scope
37
+ * object, so they cannot disagree.
38
+ *
39
+ * `@effect/sql-pg` client options are passed via `config.client`. Behind a
40
+ * transaction-mode pooler such as Hyperdrive, turn off named prepared
41
+ * statements, since a later query can reach a backend session that never
42
+ * prepared them:
43
+ *
44
+ * ```typescript
45
+ * const db = yield* Drizzle.Postgres(hd.connectionString, {
46
+ * client: { prepare: false },
47
+ * });
48
+ * ```
49
+ *
50
+ * @binding
51
+ */
52
+ export const Postgres = (connectionString, config) => Effect.map(makeExecutionMemo(Effect.gen(function* () {
53
+ const [PgClient, PgDrizzle] = yield* Effect.promise(() => Promise.all([import("@effect/sql-pg/PgClient"), import("drizzle-orm/effect-postgres")]));
54
+ const url = yield* connectionString;
55
+ const { client, ...drizzleConfig } = config ?? {};
56
+ const pgCtx = yield* Layer.build(PgClient.layer(resolvePoolConfig(url, client)));
57
+ return yield* PgDrizzle.makeWithDefaults(drizzleConfig).pipe(Effect.provideContext(pgCtx));
58
+ })), (db) => proxyChain(db));
59
+ //# sourceMappingURL=Postgres.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Postgres.js","sourceRoot":"","sources":["../src/Postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAKjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAItD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,gBAAgE,EAChE,MAMC,EACD,EAAE,CACF,MAAM,CAAC,GAAG,CACR,iBAAiB,CACf,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CACvD,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,yBAAyB,CAAC,EAAE,MAAM,CAAC,6BAA6B,CAAC,CAAC,CAAC,CACxF,CAAC;IACF,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,gBAAgB,CAAC;IACpC,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;IAClD,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACjF,OAAO,KAAK,CAAC,CAAC,SAAS,CAAC,gBAAgB,CACtC,aAAkD,CACnD,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;AACvC,CAAC,CAAC,CACH,EACD,CAAC,EAAE,EAAE,EAAE,CACL,UAAU,CAKR,EAMC,CACF,CACJ,CAAC"}
@@ -0,0 +1,47 @@
1
+ import * as Provider from "alchemy/Provider";
2
+ import * as Layer from "effect/Layer";
3
+ declare const Providers_base: Provider.ProviderCollection<Providers, "Drizzle">;
4
+ export declare class Providers extends Providers_base {
5
+ }
6
+ export type ProviderRequirements = Layer.Services<ReturnType<typeof providers>>;
7
+ /**
8
+ * Build-time providers for managing Drizzle schemas as Alchemy resources.
9
+ * Drizzle.Schema regenerates migration SQL via drizzle-kit's programmatic
10
+ * API on every deploy when the source schema changes.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import * as Alchemy from "alchemy";
15
+ * import * as Cloudflare from "@alchemy.run/cloudflare";
16
+ * import * as Drizzle from "@alchemy.run/drizzle";
17
+ * import * as Neon from "@alchemy.run/neon";
18
+ * import * as Effect from "effect/Effect";
19
+ * import * as Layer from "effect/Layer";
20
+ *
21
+ * export default Alchemy.Stack(
22
+ * "MyStack",
23
+ * {
24
+ * providers: Layer.mergeAll(
25
+ * Cloudflare.providers(),
26
+ * Drizzle.providers(),
27
+ * Neon.providers(),
28
+ * ),
29
+ * state: Alchemy.localState(),
30
+ * },
31
+ * Effect.gen(function* () {
32
+ * const schema = yield* Drizzle.Schema("app-schema", {
33
+ * schema: "./src/schema.ts",
34
+ * });
35
+ * const project = yield* Neon.Project("app-db");
36
+ * const branch = yield* Neon.Branch("app-branch", {
37
+ * project,
38
+ * migrationsDir: schema.out,
39
+ * });
40
+ * return { branchId: branch.branchId };
41
+ * }),
42
+ * );
43
+ * ```
44
+ */
45
+ export declare const providers: () => Layer.Layer<Providers, never, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | import("effect/FileSystem").FileSystem | import("effect/Path").Path | import("effect/Scope").Scope>;
46
+ export {};
47
+ //# sourceMappingURL=Providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Providers.d.ts","sourceRoot":"","sources":["../src/Providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;;AAGtC,qBAAa,SAAU,SAAQ,cAAmD;CAAG;AAErF,MAAM,MAAM,oBAAoB,GAAG,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,SAAS,4MAInB,CAAC"}
@@ -0,0 +1,45 @@
1
+ import * as Provider from "alchemy/Provider";
2
+ import * as Layer from "effect/Layer";
3
+ import { Schema, SchemaProvider } from "./Schema.js";
4
+ export class Providers extends Provider.ProviderCollection()("Drizzle") {
5
+ }
6
+ /**
7
+ * Build-time providers for managing Drizzle schemas as Alchemy resources.
8
+ * Drizzle.Schema regenerates migration SQL via drizzle-kit's programmatic
9
+ * API on every deploy when the source schema changes.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import * as Alchemy from "alchemy";
14
+ * import * as Cloudflare from "@alchemy.run/cloudflare";
15
+ * import * as Drizzle from "@alchemy.run/drizzle";
16
+ * import * as Neon from "@alchemy.run/neon";
17
+ * import * as Effect from "effect/Effect";
18
+ * import * as Layer from "effect/Layer";
19
+ *
20
+ * export default Alchemy.Stack(
21
+ * "MyStack",
22
+ * {
23
+ * providers: Layer.mergeAll(
24
+ * Cloudflare.providers(),
25
+ * Drizzle.providers(),
26
+ * Neon.providers(),
27
+ * ),
28
+ * state: Alchemy.localState(),
29
+ * },
30
+ * Effect.gen(function* () {
31
+ * const schema = yield* Drizzle.Schema("app-schema", {
32
+ * schema: "./src/schema.ts",
33
+ * });
34
+ * const project = yield* Neon.Project("app-db");
35
+ * const branch = yield* Neon.Branch("app-branch", {
36
+ * project,
37
+ * migrationsDir: schema.out,
38
+ * });
39
+ * return { branchId: branch.branchId };
40
+ * }),
41
+ * );
42
+ * ```
43
+ */
44
+ export const providers = () => Layer.effect(Providers, Provider.collection([Schema])).pipe(Layer.provide(SchemaProvider()), Layer.orDie);
45
+ //# sourceMappingURL=Providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Providers.js","sourceRoot":"","sources":["../src/Providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,OAAO,SAAU,SAAQ,QAAQ,CAAC,kBAAkB,EAAa,CAAC,SAAS,CAAC;CAAG;AAIrF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,EAAE,CAC5B,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CACzD,KAAK,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,EAC/B,KAAK,CAAC,KAAK,CACZ,CAAC"}
@@ -0,0 +1,85 @@
1
+ import * as Provider from "alchemy/Provider";
2
+ import { Resource } from "alchemy/Resource";
3
+ import * as FileSystem from "effect/FileSystem";
4
+ import * as Path from "effect/Path";
5
+ import type { Providers } from "./Providers.ts";
6
+ export type Dialect = "postgres" | "mysql" | "sqlite";
7
+ export type SchemaProps = {
8
+ /**
9
+ * Path to the schema module, relative to the current working directory.
10
+ * The module is loaded via dynamic `import()` so drizzle-kit can introspect
11
+ * the table definitions, then diffed against the latest snapshot under
12
+ * `out` to detect changes.
13
+ *
14
+ * @example "./src/schema.ts"
15
+ */
16
+ schema: string;
17
+ /**
18
+ * Output directory for generated migrations. Each migration is written as
19
+ * `{out}/{timestamp}_migration/{migration.sql, snapshot.json}`. Pass this
20
+ * through as a database resource's `migrations` prop (`Neon.Branch`,
21
+ * `Fly.Postgres`, `Cloudflare.D1.Database`, …) to apply pending
22
+ * migrations on deploy.
23
+ *
24
+ * @default "./migrations"
25
+ */
26
+ out?: string;
27
+ /**
28
+ * SQL dialect to generate migrations for. Selects which `drizzle-kit/api-*`
29
+ * module is loaded.
30
+ *
31
+ * @default "postgres"
32
+ */
33
+ dialect?: Dialect;
34
+ };
35
+ export type Schema = Resource<"Drizzle.Schema", SchemaProps, {
36
+ /** Path to the migrations directory, relative to the current working directory. */
37
+ out: string;
38
+ /**
39
+ * sha256 of the latest snapshot.json. Stable across deploys when the
40
+ * schema is unchanged; bumps trigger an update which regenerates pending
41
+ * migration SQL. Downstream `migrationsDir` consumers read this to
42
+ * detect drift and reapply.
43
+ */
44
+ snapshotHash: string;
45
+ /** Names of all migration directories under `out`, in order. */
46
+ migrations: string[];
47
+ }, never, Providers>;
48
+ /**
49
+ * A Drizzle schema managed as an Alchemy resource.
50
+ *
51
+ * Wraps drizzle-kit's programmatic API (`generateDrizzleJson` /
52
+ * `generateMigration`) so migration SQL is regenerated as part of `alchemy
53
+ * deploy` whenever the source schema changes. The output directory is
54
+ * intended to be passed straight to a database resource's `migrations`
55
+ * prop, giving you a single deploy-driven flow:
56
+ *
57
+ * ```typescript
58
+ * const schema = yield* Drizzle.Schema("app-schema", {
59
+ * schema: "./src/schema.ts",
60
+ * });
61
+ *
62
+ * const branch = yield* Neon.Branch("app-branch", {
63
+ * project,
64
+ * migrations: schema,
65
+ * });
66
+ *
67
+ * const db = yield* Fly.Postgres("Db", {
68
+ * region: "iad",
69
+ * migrations: schema,
70
+ * });
71
+ * ```
72
+ *
73
+ * `Drizzle.Schema` runs first (because the database resource depends
74
+ * on its `out` output), regenerates pending migration files, and the
75
+ * database resource then applies them.
76
+ *
77
+ * The resource is delete-safe: removing it from the stack does **not** wipe
78
+ * the migrations directory, since migration files are typically checked in
79
+ * and shared with other environments.
80
+ *
81
+ * @resource
82
+ */
83
+ export declare const Schema: import("alchemy/Resource").ResourceClass<Schema>;
84
+ export declare const SchemaProvider: () => import("effect/Layer").Layer<Provider.Provider<Schema>, never, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | FileSystem.FileSystem | Path.Path | import("effect/Scope").Scope>;
85
+ //# sourceMappingURL=Schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Schema.d.ts","sourceRoot":"","sources":["../src/Schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAI5C,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,IAAI,MAAM,aAAa,CAAC;AAGpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAgBtD,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;;;OAOG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;OAQG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,QAAQ,CAC3B,gBAAgB,EAChB,WAAW,EACX;IACE,mFAAmF;IACnF,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,EACD,KAAK,EACL,SAAS,CACV,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,MAAM,kDAAqC,CAAC;AAiBzD,eAAO,MAAM,cAAc,2MA4VxB,CAAC"}