@prisma-next/postgres 0.5.0-dev.46 → 0.5.0-dev.47

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 CHANGED
@@ -2,11 +2,18 @@
2
2
 
3
3
  One-package Postgres setup for Prisma Next. Install this single package to get config, runtime, and all transitive type dependencies.
4
4
 
5
+ Two runtime facades ship under different entrypoints:
6
+
7
+ - `@prisma-next/postgres/runtime` — long-lived Node process facade with closure-cached `runtime()`, `orm`, and `transaction()`.
8
+ - `@prisma-next/postgres/serverless` — per-request facade for serverless / edge runtimes (Cloudflare Workers + Hyperdrive, AWS Lambda, Vercel, Deno Deploy, Bun edge). Each `connect()` returns a fresh `Runtime & AsyncDisposable`.
9
+
10
+ Pick the facade that matches your deployment lifecycle. The asymmetry is intentional: closure caching is unsafe across `fetch` invocations (stale connections after isolate idle, concurrent-query races, no clean shutdown), so the serverless facade deliberately omits `orm`, `runtime()`, and `transaction()`. See `docs/architecture docs/subsystems/4. Runtime & Middleware Framework.md` and the deployment guide for the rationale.
11
+
5
12
  ## Package Classification
6
13
 
7
14
  - **Domain**: extensions
8
15
  - **Layer**: adapters
9
- - **Planes**: shared (config), runtime (runtime)
16
+ - **Planes**: shared (config), runtime (runtime, serverless)
10
17
 
11
18
  ## Quick Start
12
19
 
@@ -20,6 +27,8 @@ export default defineConfig({
20
27
  });
21
28
  ```
22
29
 
30
+ ### Node (long-lived process)
31
+
23
32
  ```typescript
24
33
  // db.ts
25
34
  import postgres from '@prisma-next/postgres/runtime';
@@ -29,6 +38,28 @@ import contractJson from './contract.json' with { type: 'json' };
29
38
  export const db = postgres<Contract>({ contractJson });
30
39
  ```
31
40
 
41
+ ### Serverless / per-request runtimes
42
+
43
+ ```typescript
44
+ // db.ts — module scope: only the static authoring surface is built here.
45
+ import postgresServerless from '@prisma-next/postgres/serverless';
46
+ import type { Contract } from './contract.d';
47
+ import contractJson from './contract.json' with { type: 'json' };
48
+
49
+ export const db = postgresServerless<Contract>({ contractJson });
50
+
51
+ // worker.ts — per-request: acquire a fresh Runtime, dispose with `await using`.
52
+ export default {
53
+ async fetch(_req: Request, env: Env): Promise<Response> {
54
+ await using runtime = await db.connect({ url: env.HYPERDRIVE.connectionString });
55
+ const rows = await runtime.execute(db.sql.from(/* ... */).build());
56
+ return Response.json(rows);
57
+ },
58
+ };
59
+ ```
60
+
61
+ The returned client exposes `sql`, `context`, `stack`, `contract`, and `connect()` — and intentionally nothing else. Construct ORM clients (or invoke `withTransaction` from `@prisma-next/sql-runtime`) against the runtime returned by `connect()` instead of caching one on the closure.
62
+
32
63
  ## Exports
33
64
 
34
65
  ### `@prisma-next/postgres/config`
@@ -40,14 +71,10 @@ Simplified `defineConfig` that pre-wires all Postgres internals (family, target,
40
71
  `@prisma-next/postgres/runtime` exposes a single `postgres(...)` helper that composes the Postgres execution stack and returns query/runtime roots:
41
72
 
42
73
  - `db.sql`
43
- - `db.kysely` (lane-owned build-only authoring surface: `build(query)` + `whereExpr(query)`)
44
- - `db.schema`
45
74
  - `db.orm`
46
75
  - `db.context`
47
76
  - `db.stack`
48
77
 
49
- `db.kysely` is produced by `@prisma-next/sql-kysely-lane` and intentionally exposes lane behavior, not raw Kysely execution APIs. `build(query)` infers plan row type from `query.compile()`, and `whereExpr(query)` produces `ToWhereExpr` payloads for ORM `.where(...)` interop.
50
-
51
78
  Runtime resources are deferred until `db.runtime()` or `db.connect(...)` is called.
52
79
  Connection binding can be provided up front (`url`, `pg`, `binding`) or deferred via `db.connect(...)`.
53
80
 
@@ -56,11 +83,23 @@ When URL binding is used, pool timeouts are configurable via `poolOptions`:
56
83
  - `poolOptions.connectionTimeoutMillis` (default `20_000`)
57
84
  - `poolOptions.idleTimeoutMillis` (default `30_000`)
58
85
 
86
+ ### `@prisma-next/postgres/serverless`
87
+
88
+ `@prisma-next/postgres/serverless` exposes `postgresServerless(...)` for per-request runtimes. The returned client exposes only:
89
+
90
+ - `db.sql`
91
+ - `db.context`
92
+ - `db.stack`
93
+ - `db.contract`
94
+ - `db.connect({ url })` — returns `Promise<Runtime & AsyncDisposable>`
95
+
96
+ Each `connect()` call constructs a fresh `pg.Client` and a fresh `Runtime`. No `pg.Pool` is allocated. `[Symbol.asyncDispose]` calls `runtime.close()`, which closes the underlying client. `pg-cursor` is enabled by default; opt out via `cursor: { disabled: true }`.
97
+
59
98
  ## Responsibilities
60
99
 
61
100
  - Build a static Postgres execution stack from target, adapter, and driver descriptors
62
- - Build typed SQL and a build-only Kysely authoring surface from the same execution context
63
- - Build static schema and ORM roots from the execution context
101
+ - Build a typed SQL authoring surface from the execution context
102
+ - Build a static ORM root from the execution context
64
103
  - Normalize runtime binding input (`binding`, `url`, `pg`)
65
104
  - Lazily instantiate runtime resources on first `db.runtime()` or `db.connect(...)` call
66
105
  - Connect the internal Postgres driver through `db.connect(...)` or from initial binding options
@@ -73,19 +112,17 @@ When URL binding is used, pool timeouts are configurable via `poolOptions`:
73
112
  - `@prisma-next/target-postgres` for target descriptor
74
113
  - `@prisma-next/adapter-postgres` for adapter descriptor
75
114
  - `@prisma-next/driver-postgres` for driver descriptor
76
- - `@prisma-next/sql-lane` for `sql(...)`
77
- - `@prisma-next/sql-kysely-lane` for contract-to-Kysely typing and build-only Kysely plan assembly
78
- - `@prisma-next/sql-relational-core` for `schema(...)`
115
+ - `@prisma-next/sql-builder` for `sql(...)`
79
116
  - `@prisma-next/sql-orm-client` for `orm(...)`
80
117
  - `@prisma-next/sql-contract` for `validateContract(...)` and contract types
81
- - `pg` for lazy `Pool` construction when using URL binding
118
+ - `pg` for `Pool` construction (URL / `pgPool` binding on the Node factory) and `Client` construction (`pgClient` binding on the Node factory; per-`connect()` on the serverless facade)
82
119
 
83
120
  ## Architecture
84
121
 
85
122
  ```mermaid
86
123
  flowchart TD
87
124
  App[App Code] --> Client[postgres(...)]
88
- Client --> Static[Roots: sql kysely(build-only) schema orm context stack]
125
+ Client --> Static[Roots: sql orm context stack]
89
126
  Client --> Lazy[runtime()]
90
127
 
91
128
  Lazy --> Instantiate[instantiateExecutionStack]
@@ -0,0 +1,84 @@
1
+ import { orm } from "@prisma-next/sql-orm-client";
2
+ import { ExecutionContext, Runtime, RuntimeVerifyOptions, SqlExecutionStackWithDriver, SqlMiddleware, SqlRuntimeExtensionDescriptor, TransactionContext } from "@prisma-next/sql-runtime";
3
+ import { Client, Pool } from "pg";
4
+ import { Contract } from "@prisma-next/contract/types";
5
+ import { Db } from "@prisma-next/sql-builder/types";
6
+ import { SqlStorage } from "@prisma-next/sql-contract/types";
7
+
8
+ //#region src/runtime/binding.d.ts
9
+ type PostgresBinding = {
10
+ readonly kind: 'url';
11
+ readonly url: string;
12
+ } | {
13
+ readonly kind: 'pgPool';
14
+ readonly pool: Pool;
15
+ } | {
16
+ readonly kind: 'pgClient';
17
+ readonly client: Client;
18
+ };
19
+ type PostgresBindingInput = {
20
+ readonly binding: PostgresBinding;
21
+ readonly url?: never;
22
+ readonly pg?: never;
23
+ } | {
24
+ readonly url: string;
25
+ readonly binding?: never;
26
+ readonly pg?: never;
27
+ } | {
28
+ readonly pg: Pool | Client;
29
+ readonly binding?: never;
30
+ readonly url?: never;
31
+ };
32
+ //#endregion
33
+ //#region src/runtime/postgres.d.ts
34
+ type PostgresTargetId = 'postgres';
35
+ type OrmClient<TContract extends Contract<SqlStorage>> = ReturnType<typeof orm<TContract>>;
36
+ interface PostgresTransactionContext<TContract extends Contract<SqlStorage>> extends TransactionContext {
37
+ readonly sql: Db<TContract>;
38
+ readonly orm: OrmClient<TContract>;
39
+ }
40
+ interface PostgresClient<TContract extends Contract<SqlStorage>> {
41
+ readonly sql: Db<TContract>;
42
+ readonly orm: OrmClient<TContract>;
43
+ readonly context: ExecutionContext<TContract>;
44
+ readonly stack: SqlExecutionStackWithDriver<PostgresTargetId>;
45
+ connect(bindingInput?: PostgresBindingInput): Promise<Runtime>;
46
+ runtime(): Runtime;
47
+ transaction<R>(fn: (tx: PostgresTransactionContext<TContract>) => PromiseLike<R>): Promise<R>;
48
+ }
49
+ interface PostgresOptionsBase {
50
+ readonly extensions?: readonly SqlRuntimeExtensionDescriptor<PostgresTargetId>[];
51
+ readonly middleware?: readonly SqlMiddleware[];
52
+ readonly verify?: RuntimeVerifyOptions;
53
+ readonly poolOptions?: {
54
+ readonly connectionTimeoutMillis?: number;
55
+ readonly idleTimeoutMillis?: number;
56
+ };
57
+ }
58
+ interface PostgresBindingOptions {
59
+ readonly binding?: PostgresBinding;
60
+ readonly url?: string;
61
+ readonly pg?: Pool | Client;
62
+ }
63
+ type PostgresOptionsWithContract<TContract extends Contract<SqlStorage>> = PostgresBindingOptions & PostgresOptionsBase & {
64
+ readonly contract: TContract;
65
+ readonly contractJson?: never;
66
+ };
67
+ type PostgresOptionsWithContractJson<TContract extends Contract<SqlStorage>> = PostgresBindingOptions & PostgresOptionsBase & {
68
+ readonly contractJson: unknown;
69
+ readonly contract?: never;
70
+ readonly _contract?: TContract;
71
+ };
72
+ type PostgresOptions<TContract extends Contract<SqlStorage>> = PostgresOptionsWithContract<TContract> | PostgresOptionsWithContractJson<TContract>;
73
+ /**
74
+ * Creates a lazy Postgres client from either `contractJson` or a TypeScript-authored `contract`.
75
+ * Static query surfaces are available immediately, while `runtime()` instantiates the driver/pool on first call.
76
+ *
77
+ * - No-emit: pass a TypeScript-authored contract. Example: postgres({ contract })
78
+ * - Emitted: pass Contract type explicitly. Example: postgres<Contract>({ contractJson, url })
79
+ */
80
+ declare function postgres<TContract extends Contract<SqlStorage>>(options: PostgresOptionsWithContract<TContract>): PostgresClient<TContract>;
81
+ declare function postgres<TContract extends Contract<SqlStorage>>(options: PostgresOptionsWithContractJson<TContract>): PostgresClient<TContract>;
82
+ //#endregion
83
+ export { PostgresOptionsWithContractJson as a, PostgresBinding as c, PostgresOptionsWithContract as i, PostgresOptions as n, PostgresTargetId as o, PostgresOptionsBase as r, postgres as s, PostgresClient as t };
84
+ //# sourceMappingURL=postgres-Cr7DL_TS.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-Cr7DL_TS.d.mts","names":[],"sources":["../src/runtime/binding.ts","../src/runtime/postgres.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1,84 +1,2 @@
1
- import { orm } from "@prisma-next/sql-orm-client";
2
- import { ExecutionContext, Runtime, RuntimeVerifyOptions, SqlExecutionStackWithDriver, SqlMiddleware, SqlRuntimeExtensionDescriptor, TransactionContext } from "@prisma-next/sql-runtime";
3
- import { Client, Pool } from "pg";
4
- import { Contract } from "@prisma-next/contract/types";
5
- import { Db } from "@prisma-next/sql-builder/types";
6
- import { SqlStorage } from "@prisma-next/sql-contract/types";
7
-
8
- //#region src/runtime/binding.d.ts
9
- type PostgresBinding = {
10
- readonly kind: 'url';
11
- readonly url: string;
12
- } | {
13
- readonly kind: 'pgPool';
14
- readonly pool: Pool;
15
- } | {
16
- readonly kind: 'pgClient';
17
- readonly client: Client;
18
- };
19
- type PostgresBindingInput = {
20
- readonly binding: PostgresBinding;
21
- readonly url?: never;
22
- readonly pg?: never;
23
- } | {
24
- readonly url: string;
25
- readonly binding?: never;
26
- readonly pg?: never;
27
- } | {
28
- readonly pg: Pool | Client;
29
- readonly binding?: never;
30
- readonly url?: never;
31
- };
32
- //#endregion
33
- //#region src/runtime/postgres.d.ts
34
- type PostgresTargetId = 'postgres';
35
- type OrmClient<TContract extends Contract<SqlStorage>> = ReturnType<typeof orm<TContract>>;
36
- interface PostgresTransactionContext<TContract extends Contract<SqlStorage>> extends TransactionContext {
37
- readonly sql: Db<TContract>;
38
- readonly orm: OrmClient<TContract>;
39
- }
40
- interface PostgresClient<TContract extends Contract<SqlStorage>> {
41
- readonly sql: Db<TContract>;
42
- readonly orm: OrmClient<TContract>;
43
- readonly context: ExecutionContext<TContract>;
44
- readonly stack: SqlExecutionStackWithDriver<PostgresTargetId>;
45
- connect(bindingInput?: PostgresBindingInput): Promise<Runtime>;
46
- runtime(): Runtime;
47
- transaction<R>(fn: (tx: PostgresTransactionContext<TContract>) => PromiseLike<R>): Promise<R>;
48
- }
49
- interface PostgresOptionsBase {
50
- readonly extensions?: readonly SqlRuntimeExtensionDescriptor<PostgresTargetId>[];
51
- readonly middleware?: readonly SqlMiddleware[];
52
- readonly verify?: RuntimeVerifyOptions;
53
- readonly poolOptions?: {
54
- readonly connectionTimeoutMillis?: number;
55
- readonly idleTimeoutMillis?: number;
56
- };
57
- }
58
- interface PostgresBindingOptions {
59
- readonly binding?: PostgresBinding;
60
- readonly url?: string;
61
- readonly pg?: Pool | Client;
62
- }
63
- type PostgresOptionsWithContract<TContract extends Contract<SqlStorage>> = PostgresBindingOptions & PostgresOptionsBase & {
64
- readonly contract: TContract;
65
- readonly contractJson?: never;
66
- };
67
- type PostgresOptionsWithContractJson<TContract extends Contract<SqlStorage>> = PostgresBindingOptions & PostgresOptionsBase & {
68
- readonly contractJson: unknown;
69
- readonly contract?: never;
70
- readonly _contract?: TContract;
71
- };
72
- type PostgresOptions<TContract extends Contract<SqlStorage>> = PostgresOptionsWithContract<TContract> | PostgresOptionsWithContractJson<TContract>;
73
- /**
74
- * Creates a lazy Postgres client from either `contractJson` or a TypeScript-authored `contract`.
75
- * Static query surfaces are available immediately, while `runtime()` instantiates the driver/pool on first call.
76
- *
77
- * - No-emit: pass a TypeScript-authored contract. Example: postgres({ contract })
78
- * - Emitted: pass Contract type explicitly. Example: postgres<Contract>({ contractJson, url })
79
- */
80
- declare function postgres<TContract extends Contract<SqlStorage>>(options: PostgresOptionsWithContract<TContract>): PostgresClient<TContract>;
81
- declare function postgres<TContract extends Contract<SqlStorage>>(options: PostgresOptionsWithContractJson<TContract>): PostgresClient<TContract>;
82
- //#endregion
83
- export { type PostgresBinding, type PostgresClient, type PostgresOptions, type PostgresOptionsBase, type PostgresOptionsWithContract, type PostgresOptionsWithContractJson, postgres as default };
84
- //# sourceMappingURL=runtime.d.mts.map
1
+ import { a as PostgresOptionsWithContractJson, c as PostgresBinding, i as PostgresOptionsWithContract, n as PostgresOptions, r as PostgresOptionsBase, s as postgres, t as PostgresClient } from "./postgres-Cr7DL_TS.mjs";
2
+ export { type PostgresBinding, type PostgresClient, type PostgresOptions, type PostgresOptionsBase, type PostgresOptionsWithContract, type PostgresOptionsWithContractJson, postgres as default };
@@ -0,0 +1,62 @@
1
+ import { o as PostgresTargetId } from "./postgres-Cr7DL_TS.mjs";
2
+ import { PostgresDriverCreateOptions } from "@prisma-next/driver-postgres/runtime";
3
+ import { ExecutionContext, Runtime, RuntimeVerifyOptions, SqlExecutionStackWithDriver, SqlMiddleware, SqlRuntimeExtensionDescriptor } from "@prisma-next/sql-runtime";
4
+ import { Contract } from "@prisma-next/contract/types";
5
+ import { Db } from "@prisma-next/sql-builder/types";
6
+ import { SqlStorage } from "@prisma-next/sql-contract/types";
7
+
8
+ //#region src/runtime/postgres-serverless.d.ts
9
+ type PostgresServerlessCursorOptions = NonNullable<PostgresDriverCreateOptions['cursor']>;
10
+ interface PostgresServerlessClient<TContract extends Contract<SqlStorage>> {
11
+ readonly sql: Db<TContract>;
12
+ readonly context: ExecutionContext<TContract>;
13
+ readonly stack: SqlExecutionStackWithDriver<PostgresTargetId>;
14
+ readonly contract: TContract;
15
+ connect(binding: {
16
+ readonly url: string;
17
+ }): Promise<Runtime & AsyncDisposable>;
18
+ }
19
+ interface PostgresServerlessOptionsBase {
20
+ readonly extensions?: readonly SqlRuntimeExtensionDescriptor<PostgresTargetId>[];
21
+ readonly middleware?: readonly SqlMiddleware[];
22
+ readonly verify?: RuntimeVerifyOptions;
23
+ readonly cursor?: PostgresServerlessCursorOptions;
24
+ }
25
+ type PostgresServerlessOptionsWithContract<TContract extends Contract<SqlStorage>> = PostgresServerlessOptionsBase & {
26
+ readonly contract: TContract;
27
+ readonly contractJson?: never;
28
+ };
29
+ type PostgresServerlessOptionsWithContractJson<TContract extends Contract<SqlStorage>> = PostgresServerlessOptionsBase & {
30
+ readonly contractJson: unknown;
31
+ readonly contract?: never;
32
+ readonly _contract?: TContract;
33
+ };
34
+ type PostgresServerlessOptions<TContract extends Contract<SqlStorage>> = PostgresServerlessOptionsWithContract<TContract> | PostgresServerlessOptionsWithContractJson<TContract>;
35
+ /**
36
+ * Per-request Postgres facade for serverless / edge runtimes (Cloudflare Workers + Hyperdrive,
37
+ * AWS Lambda, Vercel, Deno Deploy, Bun edge, etc.).
38
+ *
39
+ * Construction shape mirrors the Node `postgres()` factory but the returned client deliberately
40
+ * omits `orm`, `runtime()`, and `transaction()`. Closure-cached convenience surfaces are unsafe
41
+ * across `fetch` invocations: stale connections after isolate idle, concurrent-query races on a
42
+ * shared `pg.Client`, no clean shutdown. Per-request callers acquire a fresh `Runtime` via
43
+ * `db.connect({ url })` and dispose it via `await using` on scope exit.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * const db = postgresServerless<Contract>({ contractJson });
48
+ *
49
+ * export default {
50
+ * async fetch(_req: Request, env: Env): Promise<Response> {
51
+ * await using runtime = await db.connect({ url: env.HYPERDRIVE.connectionString });
52
+ * const rows = await runtime.execute(db.sql.from(t).select(...).build());
53
+ * return Response.json(rows);
54
+ * },
55
+ * };
56
+ * ```
57
+ */
58
+ declare function postgresServerless<TContract extends Contract<SqlStorage>>(options: PostgresServerlessOptionsWithContract<TContract>): PostgresServerlessClient<TContract>;
59
+ declare function postgresServerless<TContract extends Contract<SqlStorage>>(options: PostgresServerlessOptionsWithContractJson<TContract>): PostgresServerlessClient<TContract>;
60
+ //#endregion
61
+ export { type PostgresServerlessClient, type PostgresServerlessCursorOptions, type PostgresServerlessOptions, type PostgresServerlessOptionsBase, type PostgresServerlessOptionsWithContract, type PostgresServerlessOptionsWithContractJson, postgresServerless as default };
62
+ //# sourceMappingURL=serverless.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverless.d.mts","names":[],"sources":["../src/runtime/postgres-serverless.ts"],"sourcesContent":[],"mappings":";;;;;;;;KA8BY,+BAAA,GAAkC,YAAY;UAEzC,2CAA2C,SAAS;EAFzD,SAAA,GAAA,EAGI,EAHJ,CAGO,SAHP,CAAA;EAEK,SAAA,OAAA,EAEG,gBAFqB,CAEJ,SAFI,CAAA;EAA4B,SAAA,KAAA,EAGnD,2BAHmD,CAGvB,gBAHuB,CAAA;EAAT,SAAA,QAAA,EAIvC,SAJuC;EACzC,OAAA,CAAA,OAAA,EAAA;IAAH,SAAA,GAAA,EAAA,MAAA;EACqB,CAAA,CAAA,EAGS,OAHT,CAGiB,OAHjB,GAG2B,eAH3B,CAAA;;AACS,UAK7B,6BAAA,CAL6B;EAA5B,SAAA,UAAA,CAAA,EAAA,SAMe,6BANf,CAM6C,gBAN7C,CAAA,EAAA;EACG,SAAA,UAAA,CAAA,EAAA,SAMY,aANZ,EAAA;EACiC,SAAA,MAAA,CAAA,EAMlC,oBANkC;EAAU,SAAA,MAAA,CAAA,EAO5C,+BAP4C;;AAAX,KAUzC,qCAVyC,CAAA,kBAUe,QAVf,CAUwB,UAVxB,CAAA,CAAA,GAWnD,6BAXmD,GAAA;EAGpC,SAAA,QAAA,EASM,SATN;EAC8C,SAAA,YAAA,CAAA,EAAA,KAAA;CAA9B;AACA,KAWrB,yCAXqB,CAAA,kBAWuC,QAXvC,CAWgD,UAXhD,CAAA,CAAA,GAY/B,6BAZ+B,GAAA;EACb,SAAA,YAAA,EAAA,OAAA;EACA,SAAA,QAAA,CAAA,EAAA,KAAA;EAA+B,SAAA,SAAA,CAAA,EAa1B,SAb0B;AAGnD,CAAA;AAA6E,KAajE,yBAbiE,CAAA,kBAarB,QAbqB,CAaZ,UAbY,CAAA,CAAA,GAczE,qCAdyE,CAcnC,SAdmC,CAAA,GAezE,yCAfyE,CAe/B,SAf+B,CAAA;;;;;AAM7E;;;;;;AAOA;;;;;;;;AAEyD;;;;;AAgD7B,iBAFJ,kBAEI,CAAA,kBAFiC,QAEjC,CAF0C,UAE1C,CAAA,CAAA,CAAA,OAAA,EADjB,qCACiB,CADqB,SACrB,CAAA,CAAA,EAAzB,wBAAyB,CAAA,SAAA,CAAA;AAAzB,iBACqB,kBADrB,CAAA,kBAC0D,QAD1D,CACmE,UADnE,CAAA,CAAA,CAAA,OAAA,EAEQ,yCAFR,CAEkD,SAFlD,CAAA,CAAA,EAGA,wBAHA,CAGyB,SAHzB,CAAA"}
@@ -0,0 +1,81 @@
1
+ import { ifDefined } from "@prisma-next/utils/defined";
2
+ import postgresAdapter from "@prisma-next/adapter-postgres/runtime";
3
+ import postgresDriver from "@prisma-next/driver-postgres/runtime";
4
+ import { emptyCodecLookup } from "@prisma-next/framework-components/codec";
5
+ import { instantiateExecutionStack } from "@prisma-next/framework-components/execution";
6
+ import { sql } from "@prisma-next/sql-builder/runtime";
7
+ import { validateContract } from "@prisma-next/sql-contract/validate";
8
+ import { createExecutionContext, createRuntime, createSqlExecutionStack } from "@prisma-next/sql-runtime";
9
+ import postgresTarget from "@prisma-next/target-postgres/runtime";
10
+ import { Client } from "pg";
11
+
12
+ //#region src/runtime/postgres-serverless.ts
13
+ function hasContractJson(options) {
14
+ return "contractJson" in options;
15
+ }
16
+ function resolveContract(options) {
17
+ return validateContract(hasContractJson(options) ? options.contractJson : options.contract, emptyCodecLookup);
18
+ }
19
+ function validateConnectionString(url) {
20
+ const trimmed = url.trim();
21
+ if (trimmed.length === 0) throw new Error("Postgres URL must be a non-empty string");
22
+ return trimmed;
23
+ }
24
+ function postgresServerless(options) {
25
+ const contract = resolveContract(options);
26
+ const stack = createSqlExecutionStack({
27
+ target: postgresTarget,
28
+ adapter: postgresAdapter,
29
+ driver: postgresDriver,
30
+ extensionPacks: options.extensions ?? []
31
+ });
32
+ const context = createExecutionContext({
33
+ contract,
34
+ stack
35
+ });
36
+ return {
37
+ sql: sql({ context }),
38
+ context,
39
+ stack,
40
+ contract,
41
+ async connect(binding) {
42
+ const url = validateConnectionString(binding.url);
43
+ const driverDescriptor = stack.driver;
44
+ if (!driverDescriptor) throw new Error("Driver descriptor missing from execution stack");
45
+ const stackInstance = instantiateExecutionStack(stack);
46
+ const driver = driverDescriptor.create({ ...ifDefined("cursor", options.cursor) });
47
+ const client = new Client({ connectionString: url });
48
+ await driver.connect({
49
+ kind: "pgClient",
50
+ client
51
+ });
52
+ let runtime;
53
+ try {
54
+ runtime = createRuntime({
55
+ stackInstance,
56
+ context,
57
+ driver,
58
+ verify: options.verify ?? {
59
+ mode: "onFirstUse",
60
+ requireMarker: false
61
+ },
62
+ ...ifDefined("middleware", options.middleware)
63
+ });
64
+ } catch (err) {
65
+ await driver.close().catch(() => void 0);
66
+ throw err;
67
+ }
68
+ Object.defineProperty(runtime, Symbol.asyncDispose, {
69
+ value: () => runtime.close(),
70
+ configurable: true,
71
+ writable: false,
72
+ enumerable: false
73
+ });
74
+ return runtime;
75
+ }
76
+ };
77
+ }
78
+
79
+ //#endregion
80
+ export { postgresServerless as default };
81
+ //# sourceMappingURL=serverless.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverless.mjs","names":["sqlBuilder","runtime: Runtime"],"sources":["../src/runtime/postgres-serverless.ts"],"sourcesContent":["import postgresAdapter from '@prisma-next/adapter-postgres/runtime';\nimport type { Contract } from '@prisma-next/contract/types';\nimport postgresDriver, {\n type PostgresDriverCreateOptions,\n} from '@prisma-next/driver-postgres/runtime';\nimport { emptyCodecLookup } from '@prisma-next/framework-components/codec';\nimport { instantiateExecutionStack } from '@prisma-next/framework-components/execution';\nimport { sql as sqlBuilder } from '@prisma-next/sql-builder/runtime';\nimport type { Db } from '@prisma-next/sql-builder/types';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport { validateContract } from '@prisma-next/sql-contract/validate';\nimport type {\n ExecutionContext,\n Runtime,\n RuntimeVerifyOptions,\n SqlExecutionStackWithDriver,\n SqlMiddleware,\n SqlRuntimeExtensionDescriptor,\n} from '@prisma-next/sql-runtime';\nimport {\n createExecutionContext,\n createRuntime,\n createSqlExecutionStack,\n} from '@prisma-next/sql-runtime';\nimport postgresTarget from '@prisma-next/target-postgres/runtime';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { Client } from 'pg';\n\nimport type { PostgresTargetId } from './postgres';\n\nexport type PostgresServerlessCursorOptions = NonNullable<PostgresDriverCreateOptions['cursor']>;\n\nexport interface PostgresServerlessClient<TContract extends Contract<SqlStorage>> {\n readonly sql: Db<TContract>;\n readonly context: ExecutionContext<TContract>;\n readonly stack: SqlExecutionStackWithDriver<PostgresTargetId>;\n readonly contract: TContract;\n connect(binding: { readonly url: string }): Promise<Runtime & AsyncDisposable>;\n}\n\nexport interface PostgresServerlessOptionsBase {\n readonly extensions?: readonly SqlRuntimeExtensionDescriptor<PostgresTargetId>[];\n readonly middleware?: readonly SqlMiddleware[];\n readonly verify?: RuntimeVerifyOptions;\n readonly cursor?: PostgresServerlessCursorOptions;\n}\n\nexport type PostgresServerlessOptionsWithContract<TContract extends Contract<SqlStorage>> =\n PostgresServerlessOptionsBase & {\n readonly contract: TContract;\n readonly contractJson?: never;\n };\n\nexport type PostgresServerlessOptionsWithContractJson<TContract extends Contract<SqlStorage>> =\n PostgresServerlessOptionsBase & {\n readonly contractJson: unknown;\n readonly contract?: never;\n readonly _contract?: TContract;\n };\n\nexport type PostgresServerlessOptions<TContract extends Contract<SqlStorage>> =\n | PostgresServerlessOptionsWithContract<TContract>\n | PostgresServerlessOptionsWithContractJson<TContract>;\n\nfunction hasContractJson<TContract extends Contract<SqlStorage>>(\n options: PostgresServerlessOptions<TContract>,\n): options is PostgresServerlessOptionsWithContractJson<TContract> {\n return 'contractJson' in options;\n}\n\nfunction resolveContract<TContract extends Contract<SqlStorage>>(\n options: PostgresServerlessOptions<TContract>,\n): TContract {\n const contractInput = hasContractJson(options) ? options.contractJson : options.contract;\n return validateContract<TContract>(contractInput, emptyCodecLookup);\n}\n\nfunction validateConnectionString(url: string): string {\n const trimmed = url.trim();\n if (trimmed.length === 0) {\n throw new Error('Postgres URL must be a non-empty string');\n }\n return trimmed;\n}\n\n/**\n * Per-request Postgres facade for serverless / edge runtimes (Cloudflare Workers + Hyperdrive,\n * AWS Lambda, Vercel, Deno Deploy, Bun edge, etc.).\n *\n * Construction shape mirrors the Node `postgres()` factory but the returned client deliberately\n * omits `orm`, `runtime()`, and `transaction()`. Closure-cached convenience surfaces are unsafe\n * across `fetch` invocations: stale connections after isolate idle, concurrent-query races on a\n * shared `pg.Client`, no clean shutdown. Per-request callers acquire a fresh `Runtime` via\n * `db.connect({ url })` and dispose it via `await using` on scope exit.\n *\n * @example\n * ```ts\n * const db = postgresServerless<Contract>({ contractJson });\n *\n * export default {\n * async fetch(_req: Request, env: Env): Promise<Response> {\n * await using runtime = await db.connect({ url: env.HYPERDRIVE.connectionString });\n * const rows = await runtime.execute(db.sql.from(t).select(...).build());\n * return Response.json(rows);\n * },\n * };\n * ```\n */\nexport default function postgresServerless<TContract extends Contract<SqlStorage>>(\n options: PostgresServerlessOptionsWithContract<TContract>,\n): PostgresServerlessClient<TContract>;\nexport default function postgresServerless<TContract extends Contract<SqlStorage>>(\n options: PostgresServerlessOptionsWithContractJson<TContract>,\n): PostgresServerlessClient<TContract>;\nexport default function postgresServerless<TContract extends Contract<SqlStorage>>(\n options: PostgresServerlessOptions<TContract>,\n): PostgresServerlessClient<TContract> {\n const contract = resolveContract(options);\n const stack = createSqlExecutionStack({\n target: postgresTarget,\n adapter: postgresAdapter,\n driver: postgresDriver,\n extensionPacks: options.extensions ?? [],\n });\n\n const context = createExecutionContext({\n contract,\n stack,\n });\n\n const sql: Db<TContract> = sqlBuilder<TContract>({ context });\n\n return {\n sql,\n context,\n stack,\n contract,\n\n async connect(binding) {\n const url = validateConnectionString(binding.url);\n\n const driverDescriptor = stack.driver;\n if (!driverDescriptor) {\n throw new Error('Driver descriptor missing from execution stack');\n }\n\n const stackInstance = instantiateExecutionStack(stack);\n const driver = driverDescriptor.create({\n ...ifDefined('cursor', options.cursor),\n });\n\n const client = new Client({ connectionString: url });\n await driver.connect({ kind: 'pgClient', client });\n\n let runtime: Runtime;\n try {\n runtime = createRuntime({\n stackInstance,\n context,\n driver,\n verify: options.verify ?? { mode: 'onFirstUse', requireMarker: false },\n ...ifDefined('middleware', options.middleware),\n });\n } catch (err) {\n // The driver is bound to the pg.Client at this point; without a runtime\n // to wrap it, the caller has no handle to dispose. Close the driver so\n // the underlying pg.Client is released even if its TCP socket has not\n // yet opened (lazy connect): keeps cleanup symmetric with successful\n // construction and prevents real socket leaks if pg ever changes its\n // connect semantics.\n await driver.close().catch(() => undefined);\n throw err;\n }\n\n Object.defineProperty(runtime, Symbol.asyncDispose, {\n value: () => runtime.close(),\n configurable: true,\n writable: false,\n enumerable: false,\n });\n\n return runtime as Runtime & AsyncDisposable;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;AAgEA,SAAS,gBACP,SACiE;AACjE,QAAO,kBAAkB;;AAG3B,SAAS,gBACP,SACW;AAEX,QAAO,iBADe,gBAAgB,QAAQ,GAAG,QAAQ,eAAe,QAAQ,UAC9B,iBAAiB;;AAGrE,SAAS,yBAAyB,KAAqB;CACrD,MAAM,UAAU,IAAI,MAAM;AAC1B,KAAI,QAAQ,WAAW,EACrB,OAAM,IAAI,MAAM,0CAA0C;AAE5D,QAAO;;AAgCT,SAAwB,mBACtB,SACqC;CACrC,MAAM,WAAW,gBAAgB,QAAQ;CACzC,MAAM,QAAQ,wBAAwB;EACpC,QAAQ;EACR,SAAS;EACT,QAAQ;EACR,gBAAgB,QAAQ,cAAc,EAAE;EACzC,CAAC;CAEF,MAAM,UAAU,uBAAuB;EACrC;EACA;EACD,CAAC;AAIF,QAAO;EACL,KAHyBA,IAAsB,EAAE,SAAS,CAAC;EAI3D;EACA;EACA;EAEA,MAAM,QAAQ,SAAS;GACrB,MAAM,MAAM,yBAAyB,QAAQ,IAAI;GAEjD,MAAM,mBAAmB,MAAM;AAC/B,OAAI,CAAC,iBACH,OAAM,IAAI,MAAM,iDAAiD;GAGnE,MAAM,gBAAgB,0BAA0B,MAAM;GACtD,MAAM,SAAS,iBAAiB,OAAO,EACrC,GAAG,UAAU,UAAU,QAAQ,OAAO,EACvC,CAAC;GAEF,MAAM,SAAS,IAAI,OAAO,EAAE,kBAAkB,KAAK,CAAC;AACpD,SAAM,OAAO,QAAQ;IAAE,MAAM;IAAY;IAAQ,CAAC;GAElD,IAAIC;AACJ,OAAI;AACF,cAAU,cAAc;KACtB;KACA;KACA;KACA,QAAQ,QAAQ,UAAU;MAAE,MAAM;MAAc,eAAe;MAAO;KACtE,GAAG,UAAU,cAAc,QAAQ,WAAW;KAC/C,CAAC;YACK,KAAK;AAOZ,UAAM,OAAO,OAAO,CAAC,YAAY,OAAU;AAC3C,UAAM;;AAGR,UAAO,eAAe,SAAS,OAAO,cAAc;IAClD,aAAa,QAAQ,OAAO;IAC5B,cAAc;IACd,UAAU;IACV,YAAY;IACb,CAAC;AAEF,UAAO;;EAEV"}
package/package.json CHANGED
@@ -1,27 +1,27 @@
1
1
  {
2
2
  "name": "@prisma-next/postgres",
3
- "version": "0.5.0-dev.46",
3
+ "version": "0.5.0-dev.47",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "One-liner lazy Postgres client composition for Prisma Next",
7
7
  "dependencies": {
8
8
  "pathe": "^2.0.3",
9
9
  "pg": "8.16.3",
10
- "@prisma-next/adapter-postgres": "0.5.0-dev.46",
11
- "@prisma-next/config": "0.5.0-dev.46",
12
- "@prisma-next/contract": "0.5.0-dev.46",
13
- "@prisma-next/family-sql": "0.5.0-dev.46",
14
- "@prisma-next/framework-components": "0.5.0-dev.46",
15
- "@prisma-next/sql-contract": "0.5.0-dev.46",
16
- "@prisma-next/driver-postgres": "0.5.0-dev.46",
17
- "@prisma-next/sql-contract-psl": "0.5.0-dev.46",
18
- "@prisma-next/sql-contract-ts": "0.5.0-dev.46",
19
- "@prisma-next/sql-builder": "0.5.0-dev.46",
20
- "@prisma-next/sql-orm-client": "0.5.0-dev.46",
21
- "@prisma-next/target-postgres": "0.5.0-dev.46",
22
- "@prisma-next/sql-runtime": "0.5.0-dev.46",
23
- "@prisma-next/sql-relational-core": "0.5.0-dev.46",
24
- "@prisma-next/utils": "0.5.0-dev.46"
10
+ "@prisma-next/adapter-postgres": "0.5.0-dev.47",
11
+ "@prisma-next/config": "0.5.0-dev.47",
12
+ "@prisma-next/contract": "0.5.0-dev.47",
13
+ "@prisma-next/family-sql": "0.5.0-dev.47",
14
+ "@prisma-next/sql-contract": "0.5.0-dev.47",
15
+ "@prisma-next/driver-postgres": "0.5.0-dev.47",
16
+ "@prisma-next/framework-components": "0.5.0-dev.47",
17
+ "@prisma-next/sql-contract-psl": "0.5.0-dev.47",
18
+ "@prisma-next/sql-builder": "0.5.0-dev.47",
19
+ "@prisma-next/sql-contract-ts": "0.5.0-dev.47",
20
+ "@prisma-next/sql-relational-core": "0.5.0-dev.47",
21
+ "@prisma-next/target-postgres": "0.5.0-dev.47",
22
+ "@prisma-next/sql-runtime": "0.5.0-dev.47",
23
+ "@prisma-next/utils": "0.5.0-dev.47",
24
+ "@prisma-next/sql-orm-client": "0.5.0-dev.47"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/pg": "8.16.0",
@@ -47,6 +47,7 @@
47
47
  "exports": {
48
48
  "./config": "./dist/config.mjs",
49
49
  "./runtime": "./dist/runtime.mjs",
50
+ "./serverless": "./dist/serverless.mjs",
50
51
  "./package.json": "./package.json"
51
52
  },
52
53
  "main": "./dist/runtime.mjs",
@@ -0,0 +1,9 @@
1
+ export type {
2
+ PostgresServerlessClient,
3
+ PostgresServerlessCursorOptions,
4
+ PostgresServerlessOptions,
5
+ PostgresServerlessOptionsBase,
6
+ PostgresServerlessOptionsWithContract,
7
+ PostgresServerlessOptionsWithContractJson,
8
+ } from '../runtime/postgres-serverless';
9
+ export { default } from '../runtime/postgres-serverless';
@@ -0,0 +1,185 @@
1
+ import postgresAdapter from '@prisma-next/adapter-postgres/runtime';
2
+ import type { Contract } from '@prisma-next/contract/types';
3
+ import postgresDriver, {
4
+ type PostgresDriverCreateOptions,
5
+ } from '@prisma-next/driver-postgres/runtime';
6
+ import { emptyCodecLookup } from '@prisma-next/framework-components/codec';
7
+ import { instantiateExecutionStack } from '@prisma-next/framework-components/execution';
8
+ import { sql as sqlBuilder } from '@prisma-next/sql-builder/runtime';
9
+ import type { Db } from '@prisma-next/sql-builder/types';
10
+ import type { SqlStorage } from '@prisma-next/sql-contract/types';
11
+ import { validateContract } from '@prisma-next/sql-contract/validate';
12
+ import type {
13
+ ExecutionContext,
14
+ Runtime,
15
+ RuntimeVerifyOptions,
16
+ SqlExecutionStackWithDriver,
17
+ SqlMiddleware,
18
+ SqlRuntimeExtensionDescriptor,
19
+ } from '@prisma-next/sql-runtime';
20
+ import {
21
+ createExecutionContext,
22
+ createRuntime,
23
+ createSqlExecutionStack,
24
+ } from '@prisma-next/sql-runtime';
25
+ import postgresTarget from '@prisma-next/target-postgres/runtime';
26
+ import { ifDefined } from '@prisma-next/utils/defined';
27
+ import { Client } from 'pg';
28
+
29
+ import type { PostgresTargetId } from './postgres';
30
+
31
+ export type PostgresServerlessCursorOptions = NonNullable<PostgresDriverCreateOptions['cursor']>;
32
+
33
+ export interface PostgresServerlessClient<TContract extends Contract<SqlStorage>> {
34
+ readonly sql: Db<TContract>;
35
+ readonly context: ExecutionContext<TContract>;
36
+ readonly stack: SqlExecutionStackWithDriver<PostgresTargetId>;
37
+ readonly contract: TContract;
38
+ connect(binding: { readonly url: string }): Promise<Runtime & AsyncDisposable>;
39
+ }
40
+
41
+ export interface PostgresServerlessOptionsBase {
42
+ readonly extensions?: readonly SqlRuntimeExtensionDescriptor<PostgresTargetId>[];
43
+ readonly middleware?: readonly SqlMiddleware[];
44
+ readonly verify?: RuntimeVerifyOptions;
45
+ readonly cursor?: PostgresServerlessCursorOptions;
46
+ }
47
+
48
+ export type PostgresServerlessOptionsWithContract<TContract extends Contract<SqlStorage>> =
49
+ PostgresServerlessOptionsBase & {
50
+ readonly contract: TContract;
51
+ readonly contractJson?: never;
52
+ };
53
+
54
+ export type PostgresServerlessOptionsWithContractJson<TContract extends Contract<SqlStorage>> =
55
+ PostgresServerlessOptionsBase & {
56
+ readonly contractJson: unknown;
57
+ readonly contract?: never;
58
+ readonly _contract?: TContract;
59
+ };
60
+
61
+ export type PostgresServerlessOptions<TContract extends Contract<SqlStorage>> =
62
+ | PostgresServerlessOptionsWithContract<TContract>
63
+ | PostgresServerlessOptionsWithContractJson<TContract>;
64
+
65
+ function hasContractJson<TContract extends Contract<SqlStorage>>(
66
+ options: PostgresServerlessOptions<TContract>,
67
+ ): options is PostgresServerlessOptionsWithContractJson<TContract> {
68
+ return 'contractJson' in options;
69
+ }
70
+
71
+ function resolveContract<TContract extends Contract<SqlStorage>>(
72
+ options: PostgresServerlessOptions<TContract>,
73
+ ): TContract {
74
+ const contractInput = hasContractJson(options) ? options.contractJson : options.contract;
75
+ return validateContract<TContract>(contractInput, emptyCodecLookup);
76
+ }
77
+
78
+ function validateConnectionString(url: string): string {
79
+ const trimmed = url.trim();
80
+ if (trimmed.length === 0) {
81
+ throw new Error('Postgres URL must be a non-empty string');
82
+ }
83
+ return trimmed;
84
+ }
85
+
86
+ /**
87
+ * Per-request Postgres facade for serverless / edge runtimes (Cloudflare Workers + Hyperdrive,
88
+ * AWS Lambda, Vercel, Deno Deploy, Bun edge, etc.).
89
+ *
90
+ * Construction shape mirrors the Node `postgres()` factory but the returned client deliberately
91
+ * omits `orm`, `runtime()`, and `transaction()`. Closure-cached convenience surfaces are unsafe
92
+ * across `fetch` invocations: stale connections after isolate idle, concurrent-query races on a
93
+ * shared `pg.Client`, no clean shutdown. Per-request callers acquire a fresh `Runtime` via
94
+ * `db.connect({ url })` and dispose it via `await using` on scope exit.
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * const db = postgresServerless<Contract>({ contractJson });
99
+ *
100
+ * export default {
101
+ * async fetch(_req: Request, env: Env): Promise<Response> {
102
+ * await using runtime = await db.connect({ url: env.HYPERDRIVE.connectionString });
103
+ * const rows = await runtime.execute(db.sql.from(t).select(...).build());
104
+ * return Response.json(rows);
105
+ * },
106
+ * };
107
+ * ```
108
+ */
109
+ export default function postgresServerless<TContract extends Contract<SqlStorage>>(
110
+ options: PostgresServerlessOptionsWithContract<TContract>,
111
+ ): PostgresServerlessClient<TContract>;
112
+ export default function postgresServerless<TContract extends Contract<SqlStorage>>(
113
+ options: PostgresServerlessOptionsWithContractJson<TContract>,
114
+ ): PostgresServerlessClient<TContract>;
115
+ export default function postgresServerless<TContract extends Contract<SqlStorage>>(
116
+ options: PostgresServerlessOptions<TContract>,
117
+ ): PostgresServerlessClient<TContract> {
118
+ const contract = resolveContract(options);
119
+ const stack = createSqlExecutionStack({
120
+ target: postgresTarget,
121
+ adapter: postgresAdapter,
122
+ driver: postgresDriver,
123
+ extensionPacks: options.extensions ?? [],
124
+ });
125
+
126
+ const context = createExecutionContext({
127
+ contract,
128
+ stack,
129
+ });
130
+
131
+ const sql: Db<TContract> = sqlBuilder<TContract>({ context });
132
+
133
+ return {
134
+ sql,
135
+ context,
136
+ stack,
137
+ contract,
138
+
139
+ async connect(binding) {
140
+ const url = validateConnectionString(binding.url);
141
+
142
+ const driverDescriptor = stack.driver;
143
+ if (!driverDescriptor) {
144
+ throw new Error('Driver descriptor missing from execution stack');
145
+ }
146
+
147
+ const stackInstance = instantiateExecutionStack(stack);
148
+ const driver = driverDescriptor.create({
149
+ ...ifDefined('cursor', options.cursor),
150
+ });
151
+
152
+ const client = new Client({ connectionString: url });
153
+ await driver.connect({ kind: 'pgClient', client });
154
+
155
+ let runtime: Runtime;
156
+ try {
157
+ runtime = createRuntime({
158
+ stackInstance,
159
+ context,
160
+ driver,
161
+ verify: options.verify ?? { mode: 'onFirstUse', requireMarker: false },
162
+ ...ifDefined('middleware', options.middleware),
163
+ });
164
+ } catch (err) {
165
+ // The driver is bound to the pg.Client at this point; without a runtime
166
+ // to wrap it, the caller has no handle to dispose. Close the driver so
167
+ // the underlying pg.Client is released even if its TCP socket has not
168
+ // yet opened (lazy connect): keeps cleanup symmetric with successful
169
+ // construction and prevents real socket leaks if pg ever changes its
170
+ // connect semantics.
171
+ await driver.close().catch(() => undefined);
172
+ throw err;
173
+ }
174
+
175
+ Object.defineProperty(runtime, Symbol.asyncDispose, {
176
+ value: () => runtime.close(),
177
+ configurable: true,
178
+ writable: false,
179
+ enumerable: false,
180
+ });
181
+
182
+ return runtime as Runtime & AsyncDisposable;
183
+ },
184
+ };
185
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/runtime/binding.ts","../src/runtime/postgres.ts"],"sourcesContent":[],"mappings":"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"}