@prisma-next/postgres 0.0.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 ADDED
@@ -0,0 +1,73 @@
1
+ # @prisma-next/postgres
2
+
3
+ One-liner lazy Postgres client for Prisma Next runtime composition.
4
+
5
+ ## Package Classification
6
+
7
+ - **Domain**: targets
8
+ - **Layer**: clients
9
+ - **Plane**: runtime
10
+
11
+ ## Overview
12
+
13
+ `@prisma-next/postgres/runtime` exposes a single `postgres(...)` helper that composes the SQL execution stack for Postgres and returns static query roots immediately:
14
+
15
+ - `db.sql`
16
+ - `db.schema`
17
+ - `db.context`
18
+ - `db.stack`
19
+
20
+ Runtime and connection resources are deferred until `await db.runtime()` is called. The getter returns `Promise<Runtime>`.
21
+
22
+ When URL binding is used, pool timeouts are configurable via `poolOptions`:
23
+
24
+ - `poolOptions.connectionTimeoutMillis` (default `20_000`)
25
+ - `poolOptions.idleTimeoutMillis` (default `30_000`)
26
+
27
+ ## Responsibilities
28
+
29
+ - Build a static Postgres execution stack from target, adapter, and driver descriptors
30
+ - Build static query roots from the execution context
31
+ - Normalize runtime binding input (`binding`, `url`, `pg`)
32
+ - Lazily instantiate stack and driver on first `await db.runtime()` call
33
+ - Connect driver with resolved binding before creating runtime
34
+ - Memoize runtime so repeated `await db.runtime()` calls return one instance
35
+
36
+ ## Dependencies
37
+
38
+ - `@prisma-next/sql-runtime` for stack/context/runtime primitives
39
+ - `@prisma-next/core-execution-plane` for stack instantiation
40
+ - `@prisma-next/target-postgres` for target descriptor
41
+ - `@prisma-next/adapter-postgres` for adapter descriptor
42
+ - `@prisma-next/driver-postgres` for driver descriptor
43
+ - `@prisma-next/sql-lane` for `sql(...)`
44
+ - `@prisma-next/sql-relational-core` for `schema(...)`
45
+ - `@prisma-next/sql-contract` for `validateContract(...)` and contract types
46
+ - `pg` for binding validation when using `pg` (Pool or Client) input
47
+
48
+ ## Architecture
49
+
50
+ ```mermaid
51
+ flowchart TD
52
+ App[App Code] --> Client[postgres(...)]
53
+ Client --> Static[Static roots: sql schema context stack]
54
+ Client --> Lazy[runtime()]
55
+
56
+ Lazy --> Instantiate[instantiateExecutionStack]
57
+ Lazy --> Bind[Resolve binding: url or pg]
58
+ Bind --> Assert[Assert stackInstance.driver]
59
+ Assert --> Connect[driver.connect binding]
60
+ Connect --> Runtime[createRuntime]
61
+
62
+ Runtime --> Target[@prisma-next/target-postgres]
63
+ Runtime --> Adapter[@prisma-next/adapter-postgres]
64
+ Runtime --> Driver[@prisma-next/driver-postgres]
65
+ Runtime --> SqlRuntime[@prisma-next/sql-runtime]
66
+ Runtime --> ExecPlane[@prisma-next/core-execution-plane]
67
+ ```
68
+
69
+ ## Related Docs
70
+
71
+ - Spec: `agent-os/specs/2026-02-10-postgres-one-liner-lazy-client/spec.md`
72
+ - Architecture: `docs/Architecture Overview.md`
73
+ - Subsystem: `docs/architecture docs/subsystems/4. Runtime & Plugin Framework.md`
@@ -0,0 +1,58 @@
1
+ import { PostgresBinding, PostgresBinding as PostgresBinding$1, PostgresDriverCreateOptions } from "@prisma-next/driver-postgres/runtime";
2
+ import { SelectBuilder } from "@prisma-next/sql-lane";
3
+ import { SchemaHandle } from "@prisma-next/sql-relational-core/schema";
4
+ import { ExecutionContext, Plugin, Runtime, RuntimeVerifyOptions, SqlExecutionStackWithDriver, SqlRuntimeExtensionDescriptor } from "@prisma-next/sql-runtime";
5
+ import { Client, Pool } from "pg";
6
+ import { ExtractCodecTypes, ExtractOperationTypes, SqlContract, SqlStorage } from "@prisma-next/sql-contract/types";
7
+ import { OperationTypeSignature, OperationTypes } from "@prisma-next/sql-relational-core/types";
8
+
9
+ //#region src/runtime/binding.d.ts
10
+ type PostgresBindingInput = {
11
+ readonly binding: PostgresBinding$1;
12
+ readonly url?: never;
13
+ readonly pg?: never;
14
+ } | {
15
+ readonly url: string;
16
+ readonly binding?: never;
17
+ readonly pg?: never;
18
+ } | {
19
+ readonly pg: Pool | Client;
20
+ readonly binding?: never;
21
+ readonly url?: never;
22
+ };
23
+ //#endregion
24
+ //#region src/runtime/postgres.d.ts
25
+ type NormalizeOperationTypes<T> = { [TypeId in keyof T]: { [Method in keyof T[TypeId]]: T[TypeId][Method] extends OperationTypeSignature ? T[TypeId][Method] : OperationTypeSignature } };
26
+ type ToSchemaOperationTypes<T> = T extends OperationTypes ? T : NormalizeOperationTypes<T>;
27
+ type PostgresTargetId = 'postgres';
28
+ interface PostgresClient<TContract extends SqlContract<SqlStorage>> {
29
+ readonly sql: SelectBuilder<TContract, unknown, ExtractCodecTypes<TContract>, ExtractOperationTypes<TContract>>;
30
+ readonly schema: SchemaHandle<TContract, ExtractCodecTypes<TContract>, ToSchemaOperationTypes<ExtractOperationTypes<TContract>>>;
31
+ readonly context: ExecutionContext<TContract>;
32
+ readonly stack: SqlExecutionStackWithDriver<PostgresTargetId>;
33
+ runtime(): Promise<Runtime>;
34
+ }
35
+ interface PostgresOptionsBase<TContract extends SqlContract<SqlStorage>> {
36
+ readonly extensions?: readonly SqlRuntimeExtensionDescriptor<PostgresTargetId>[];
37
+ readonly plugins?: readonly Plugin<TContract>[];
38
+ readonly verify?: RuntimeVerifyOptions;
39
+ readonly cursor?: PostgresDriverCreateOptions['cursor'];
40
+ }
41
+ type PostgresOptionsWithContract<TContract extends SqlContract<SqlStorage>> = PostgresBindingInput & PostgresOptionsBase<TContract> & {
42
+ readonly contract: TContract;
43
+ readonly contractJson?: never;
44
+ };
45
+ type PostgresOptionsWithContractJson<TContract extends SqlContract<SqlStorage>> = PostgresBindingInput & PostgresOptionsBase<TContract> & {
46
+ readonly contractJson: unknown;
47
+ readonly contract?: never;
48
+ };
49
+ type PostgresOptions<TContract extends SqlContract<SqlStorage>> = PostgresOptionsWithContract<TContract> | PostgresOptionsWithContractJson<TContract>;
50
+ /**
51
+ * Creates a lazy Postgres client from either `contractJson` or a TypeScript-authored `contract`.
52
+ * Static query surfaces are available immediately, while `runtime()` instantiates the driver/pool on first call.
53
+ */
54
+ declare function postgres<TContract extends SqlContract<SqlStorage>>(options: PostgresOptionsWithContract<TContract>): PostgresClient<TContract>;
55
+ declare function postgres<TContract extends SqlContract<SqlStorage>>(options: PostgresOptionsWithContractJson<TContract>): PostgresClient<TContract>;
56
+ //#endregion
57
+ export { type PostgresBinding, type PostgresClient, type PostgresOptions, type PostgresOptionsBase, type PostgresOptionsWithContract, type PostgresOptionsWithContractJson, postgres as default };
58
+ //# sourceMappingURL=runtime.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/runtime/binding.ts","../src/runtime/postgres.ts"],"sourcesContent":[],"mappings":";;;;;;;;;KAIY,oBAAA;oBAEY;;;;;;EAFZ,SAAA,EAAA,CAAA,EAAA,KAAA;CAEY,GAAA;EAUL,SAAA,EAAA,EAAA,IAAA,GAAO,MAAP;EAAO,SAAA,OAAA,CAAA,EAAA,KAAA;EAAM,SAAA,GAAA,CAAA,EAAA,KAAA;;;;KCoB3B,gDACc,iBDjCP,MCkCS,CDlCT,CCkCW,MDlCS,CAAA,GCkCC,CDlCD,CCkCG,MDlCH,CAAA,CCkCW,MDlCX,CAAA,SCkC2B,sBDlC3B,GCmCxB,CDnCwB,CCmCtB,MDnCsB,CAAA,CCmCd,MDnCc,CAAA,GCoCxB,sBDpCwB,EAER,EAUL;KC4Bd,sBD5BqB,CAAA,CAAA,CAAA,GC4BO,CD5BP,SC4BiB,cD5BjB,GC4BkC,CD5BlC,GC4BsC,uBD5BtC,CC4B8D,CD5B9D,CAAA;AAAM,KC8BpB,gBAAA,GD9BoB,UAAA;UCgCf,iCAAiC,YAAY;gBAC9C,cACZ,oBAEA,kBAAkB,YAClB,sBAAsB;mBAEP,aACf,WACA,kBAAkB,YAClB,uBAAuB,sBAAsB;EAtB5C,SAAA,OAAA,EAwBe,gBAxBQ,CAwBS,SAxBT,CAAA;EACT,SAAA,KAAA,EAwBD,2BAxBC,CAwB2B,gBAxB3B,CAAA;EACE,OAAA,EAAA,EAwBR,OAxBQ,CAwBA,OAxBA,CAAA;;AAAY,UA2BhB,mBA3BgB,CAAA,kBA2BsB,WA3BtB,CA2BkC,UA3BlC,CAAA,CAAA,CAAA;EAAE,SAAA,UAAA,CAAA,EAAA,SA4BF,6BA5BE,CA4B4B,gBA5B5B,CAAA,EAAA;EAAQ,SAAA,OAAA,CAAA,EAAA,SA6Bb,MA7Ba,CA6BN,SA7BM,CAAA,EAAA;EAAgB,SAAA,MAAA,CAAA,EA8BvC,oBA9BuC;EACnD,SAAA,MAAA,CAAA,EA8BY,2BA9BZ,CAAA,QAAA,CAAA;;AAAU,KAiCN,2BAjCM,CAAA,kBAiCwC,WAjCxC,CAiCoD,UAjCpD,CAAA,CAAA,GAkChB,oBAlCgB,GAmCd,mBAnCc,CAmCM,SAnCN,CAAA,GAAA;EACV,SAAA,QAAA,EAmCiB,SAnCjB;EAAsB,SAAA,YAAA,CAAA,EAAA,KAAA;AAAA,CAAA;AAIG,KAmCrB,+BAnCqB,CAAA,kBAmC6B,WAnC7B,CAmCyC,UAnCzC,CAAA,CAAA,GAoC/B,oBApC+B,GAqC7B,mBArC6B,CAqCT,SArCS,CAAA,GAAA;EAAU,SAAA,YAAA,EAAA,OAAA;EAAiB,SAAA,QAAA,CAAA,EAAA,KAAA;CAA4B;AAAxB,KA0CpD,eA1CoD,CAAA,kBA0ClB,WA1CkB,CA0CN,UA1CM,CAAA,CAAA,GA2C5D,2BA3C4D,CA2ChC,SA3CgC,CAAA,GA4C5D,+BA5C4D,CA4C5B,SA5C4B,CAAA;;AAEhE;AAEA;;AAAkD,iBA2D1B,QA3D0B,CAAA,kBA2DC,WA3DD,CA2Da,UA3Db,CAAA,CAAA,CAAA,OAAA,EA4DvC,2BA5DuC,CA4DX,SA5DW,CAAA,CAAA,EA6D/C,cA7D+C,CA6DhC,SA7DgC,CAAA;AAE9C,iBA4DoB,QA5DpB,CAAA,kBA4D+C,WA5D/C,CA4D2D,UA5D3D,CAAA,CAAA,CAAA,OAAA,EA6DO,+BA7DP,CA6DuC,SA7DvC,CAAA,CAAA,EA8DD,cA9DC,CA8Dc,SA9Dd,CAAA"}
@@ -0,0 +1,137 @@
1
+ import postgresAdapter from "@prisma-next/adapter-postgres/runtime";
2
+ import { instantiateExecutionStack } from "@prisma-next/core-execution-plane/stack";
3
+ import postgresDriver from "@prisma-next/driver-postgres/runtime";
4
+ import { validateContract } from "@prisma-next/sql-contract/validate";
5
+ import { sql } from "@prisma-next/sql-lane";
6
+ import { schema } from "@prisma-next/sql-relational-core/schema";
7
+ import { createExecutionContext, createRuntime, createSqlExecutionStack } from "@prisma-next/sql-runtime";
8
+ import postgresTarget from "@prisma-next/target-postgres/runtime";
9
+ import { ifDefined } from "@prisma-next/utils/defined";
10
+ import { Client, Pool } from "pg";
11
+
12
+ //#region src/runtime/binding.ts
13
+ function bindingError(message, details) {
14
+ const error = new Error(message);
15
+ Object.defineProperty(error, "name", {
16
+ value: "RuntimeError",
17
+ configurable: true
18
+ });
19
+ return Object.assign(error, {
20
+ code: "DRIVER.BINDING_INVALID",
21
+ category: "RUNTIME",
22
+ severity: "error",
23
+ message,
24
+ details
25
+ });
26
+ }
27
+ function validatePostgresUrl(url) {
28
+ const trimmed = url.trim();
29
+ if (trimmed.length === 0) throw bindingError("Postgres URL must be a non-empty string", {
30
+ field: "url",
31
+ reason: "empty"
32
+ });
33
+ let parsed;
34
+ try {
35
+ parsed = new URL(trimmed);
36
+ } catch {
37
+ throw bindingError("Postgres URL must be a valid URL", {
38
+ field: "url",
39
+ reason: "invalid-url"
40
+ });
41
+ }
42
+ if (parsed.protocol !== "postgres:" && parsed.protocol !== "postgresql:") throw bindingError("Postgres URL must use postgres:// or postgresql://", {
43
+ field: "url",
44
+ reason: "invalid-protocol",
45
+ protocol: parsed.protocol
46
+ });
47
+ return trimmed;
48
+ }
49
+ function resolvePostgresBinding(options) {
50
+ const providedCount = Number(options.binding !== void 0) + Number(options.url !== void 0) + Number(options.pg !== void 0);
51
+ if (providedCount !== 1) throw bindingError("Provide one binding input: binding, url, or pg", { providedCount });
52
+ if (options.binding !== void 0) return options.binding;
53
+ if (options.url !== void 0) return {
54
+ kind: "url",
55
+ url: validatePostgresUrl(options.url)
56
+ };
57
+ const pgBinding = options.pg;
58
+ if (pgBinding === void 0) throw bindingError("Invariant violation: expected pg binding after validation", { reason: "missing-pg-binding" });
59
+ if (pgBinding instanceof Pool) return {
60
+ kind: "pgPool",
61
+ pool: pgBinding
62
+ };
63
+ if (pgBinding instanceof Client) return {
64
+ kind: "pgClient",
65
+ client: pgBinding
66
+ };
67
+ throw bindingError("Unable to determine pg binding type from pg input; use binding with explicit kind", { reason: "unknown-pg-instance" });
68
+ }
69
+
70
+ //#endregion
71
+ //#region src/runtime/postgres.ts
72
+ function hasContractJson(options) {
73
+ return "contractJson" in options;
74
+ }
75
+ function resolveContract(options) {
76
+ return validateContract(hasContractJson(options) ? options.contractJson : options.contract);
77
+ }
78
+ function postgres(options) {
79
+ const contract = resolveContract(options);
80
+ const binding = resolvePostgresBinding(options);
81
+ const stack = createSqlExecutionStack({
82
+ target: postgresTarget,
83
+ adapter: postgresAdapter,
84
+ driver: options.cursor === void 0 ? postgresDriver : {
85
+ ...postgresDriver,
86
+ create() {
87
+ return postgresDriver.create({ cursor: options.cursor });
88
+ }
89
+ },
90
+ extensionPacks: options.extensions ?? []
91
+ });
92
+ const context = createExecutionContext({
93
+ contract,
94
+ stack
95
+ });
96
+ const schema$1 = schema(context);
97
+ const sql$1 = sql({ context });
98
+ let runtimePromise;
99
+ return {
100
+ sql: sql$1,
101
+ schema: schema$1,
102
+ context,
103
+ stack,
104
+ async runtime() {
105
+ if (runtimePromise) return runtimePromise;
106
+ runtimePromise = (async () => {
107
+ const stackInstance = instantiateExecutionStack(stack);
108
+ const driver = stackInstance.driver;
109
+ if (driver === void 0) throw new Error("Relational runtime requires a driver descriptor on the execution stack");
110
+ try {
111
+ await driver.connect(binding);
112
+ return createRuntime({
113
+ stackInstance,
114
+ context,
115
+ driver,
116
+ verify: options.verify ?? {
117
+ mode: "onFirstUse",
118
+ requireMarker: false
119
+ },
120
+ ...ifDefined("plugins", options.plugins)
121
+ });
122
+ } catch (error) {
123
+ await driver.close().catch(() => void 0);
124
+ throw error;
125
+ }
126
+ })();
127
+ runtimePromise.catch(() => {
128
+ runtimePromise = void 0;
129
+ });
130
+ return runtimePromise;
131
+ }
132
+ };
133
+ }
134
+
135
+ //#endregion
136
+ export { postgres as default };
137
+ //# sourceMappingURL=runtime.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.mjs","names":["parsed: URL","PgPool","PgClient","schema: PostgresClient<TContract>['schema']","schemaBuilder","sql","sqlBuilder","runtimePromise: Promise<Runtime> | undefined"],"sources":["../src/runtime/binding.ts","../src/runtime/postgres.ts"],"sourcesContent":["import type { PostgresBinding } from '@prisma-next/driver-postgres/runtime';\nimport type { Client, Pool } from 'pg';\nimport { Client as PgClient, Pool as PgPool } from 'pg';\n\nexport type PostgresBindingInput =\n | {\n readonly binding: PostgresBinding;\n readonly url?: never;\n readonly pg?: never;\n }\n | {\n readonly url: string;\n readonly binding?: never;\n readonly pg?: never;\n }\n | {\n readonly pg: Pool | Client;\n readonly binding?: never;\n readonly url?: never;\n };\n\ninterface PostgresBindingError extends Error {\n readonly code: 'DRIVER.BINDING_INVALID';\n readonly category: 'RUNTIME';\n readonly severity: 'error';\n readonly details?: Record<string, unknown>;\n}\n\nfunction bindingError(message: string, details?: Record<string, unknown>): PostgresBindingError {\n const error = new Error(message) as PostgresBindingError;\n Object.defineProperty(error, 'name', {\n value: 'RuntimeError',\n configurable: true,\n });\n return Object.assign(error, {\n code: 'DRIVER.BINDING_INVALID' as const,\n category: 'RUNTIME' as const,\n severity: 'error' as const,\n message,\n details,\n });\n}\n\nfunction validatePostgresUrl(url: string): string {\n const trimmed = url.trim();\n if (trimmed.length === 0) {\n throw bindingError('Postgres URL must be a non-empty string', {\n field: 'url',\n reason: 'empty',\n });\n }\n\n let parsed: URL;\n try {\n parsed = new URL(trimmed);\n } catch {\n throw bindingError('Postgres URL must be a valid URL', {\n field: 'url',\n reason: 'invalid-url',\n });\n }\n\n if (parsed.protocol !== 'postgres:' && parsed.protocol !== 'postgresql:') {\n throw bindingError('Postgres URL must use postgres:// or postgresql://', {\n field: 'url',\n reason: 'invalid-protocol',\n protocol: parsed.protocol,\n });\n }\n\n return trimmed;\n}\n\nexport function resolvePostgresBinding(options: PostgresBindingInput): PostgresBinding {\n const providedCount =\n Number(options.binding !== undefined) +\n Number(options.url !== undefined) +\n Number(options.pg !== undefined);\n\n if (providedCount !== 1) {\n throw bindingError('Provide one binding input: binding, url, or pg', {\n providedCount,\n });\n }\n\n if (options.binding !== undefined) {\n return options.binding;\n }\n\n if (options.url !== undefined) {\n return { kind: 'url', url: validatePostgresUrl(options.url) };\n }\n\n const pgBinding = options.pg;\n if (pgBinding === undefined) {\n throw bindingError('Invariant violation: expected pg binding after validation', {\n reason: 'missing-pg-binding',\n });\n }\n\n if (pgBinding instanceof PgPool) {\n return { kind: 'pgPool', pool: pgBinding };\n }\n\n if (pgBinding instanceof PgClient) {\n return { kind: 'pgClient', client: pgBinding };\n }\n\n throw bindingError(\n 'Unable to determine pg binding type from pg input; use binding with explicit kind',\n {\n reason: 'unknown-pg-instance',\n },\n );\n}\n","import postgresAdapter from '@prisma-next/adapter-postgres/runtime';\nimport { instantiateExecutionStack } from '@prisma-next/core-execution-plane/stack';\nimport type { PostgresDriverCreateOptions } from '@prisma-next/driver-postgres/runtime';\nimport postgresDriver from '@prisma-next/driver-postgres/runtime';\nimport type {\n ExtractCodecTypes,\n ExtractOperationTypes,\n SqlContract,\n SqlStorage,\n} from '@prisma-next/sql-contract/types';\nimport { validateContract } from '@prisma-next/sql-contract/validate';\nimport type { SelectBuilder } from '@prisma-next/sql-lane';\nimport { sql as sqlBuilder } from '@prisma-next/sql-lane';\nimport type { SchemaHandle } from '@prisma-next/sql-relational-core/schema';\nimport { schema as schemaBuilder } from '@prisma-next/sql-relational-core/schema';\nimport type {\n OperationTypeSignature,\n OperationTypes,\n} from '@prisma-next/sql-relational-core/types';\nimport type {\n ExecutionContext,\n Plugin,\n Runtime,\n RuntimeVerifyOptions,\n SqlExecutionStackWithDriver,\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 { type PostgresBindingInput, resolvePostgresBinding } from './binding';\n\ntype NormalizeOperationTypes<T> = {\n [TypeId in keyof T]: {\n [Method in keyof T[TypeId]]: T[TypeId][Method] extends OperationTypeSignature\n ? T[TypeId][Method]\n : OperationTypeSignature;\n };\n};\n\ntype ToSchemaOperationTypes<T> = T extends OperationTypes ? T : NormalizeOperationTypes<T>;\n\nexport type PostgresTargetId = 'postgres';\n\nexport interface PostgresClient<TContract extends SqlContract<SqlStorage>> {\n readonly sql: SelectBuilder<\n TContract,\n unknown,\n ExtractCodecTypes<TContract>,\n ExtractOperationTypes<TContract>\n >;\n readonly schema: SchemaHandle<\n TContract,\n ExtractCodecTypes<TContract>,\n ToSchemaOperationTypes<ExtractOperationTypes<TContract>>\n >;\n readonly context: ExecutionContext<TContract>;\n readonly stack: SqlExecutionStackWithDriver<PostgresTargetId>;\n runtime(): Promise<Runtime>;\n}\n\nexport interface PostgresOptionsBase<TContract extends SqlContract<SqlStorage>> {\n readonly extensions?: readonly SqlRuntimeExtensionDescriptor<PostgresTargetId>[];\n readonly plugins?: readonly Plugin<TContract>[];\n readonly verify?: RuntimeVerifyOptions;\n readonly cursor?: PostgresDriverCreateOptions['cursor'];\n}\n\nexport type PostgresOptionsWithContract<TContract extends SqlContract<SqlStorage>> =\n PostgresBindingInput &\n PostgresOptionsBase<TContract> & {\n readonly contract: TContract;\n readonly contractJson?: never;\n };\n\nexport type PostgresOptionsWithContractJson<TContract extends SqlContract<SqlStorage>> =\n PostgresBindingInput &\n PostgresOptionsBase<TContract> & {\n readonly contractJson: unknown;\n readonly contract?: never;\n };\n\nexport type PostgresOptions<TContract extends SqlContract<SqlStorage>> =\n | PostgresOptionsWithContract<TContract>\n | PostgresOptionsWithContractJson<TContract>;\n\nfunction hasContractJson<TContract extends SqlContract<SqlStorage>>(\n options: PostgresOptions<TContract>,\n): options is PostgresOptionsWithContractJson<TContract> {\n return 'contractJson' in options;\n}\n\nfunction resolveContract<TContract extends SqlContract<SqlStorage>>(\n options: PostgresOptions<TContract>,\n): TContract {\n const contractInput = hasContractJson(options) ? options.contractJson : options.contract;\n return validateContract<TContract>(contractInput);\n}\n\n/**\n * Creates a lazy Postgres client from either `contractJson` or a TypeScript-authored `contract`.\n * Static query surfaces are available immediately, while `runtime()` instantiates the driver/pool on first call.\n */\nexport default function postgres<TContract extends SqlContract<SqlStorage>>(\n options: PostgresOptionsWithContract<TContract>,\n): PostgresClient<TContract>;\nexport default function postgres<TContract extends SqlContract<SqlStorage>>(\n options: PostgresOptionsWithContractJson<TContract>,\n): PostgresClient<TContract>;\nexport default function postgres<TContract extends SqlContract<SqlStorage>>(\n options: PostgresOptions<TContract>,\n): PostgresClient<TContract> {\n const contract = resolveContract(options);\n const binding = resolvePostgresBinding(options);\n const stack = createSqlExecutionStack({\n target: postgresTarget,\n adapter: postgresAdapter,\n driver:\n options.cursor === undefined\n ? postgresDriver\n : {\n ...postgresDriver,\n create() {\n return postgresDriver.create({ cursor: options.cursor });\n },\n },\n extensionPacks: options.extensions ?? [],\n });\n\n const context = createExecutionContext({\n contract,\n stack,\n });\n\n const schema: PostgresClient<TContract>['schema'] = schemaBuilder(context);\n const sql = sqlBuilder({ context });\n\n let runtimePromise: Promise<Runtime> | undefined;\n\n return {\n sql,\n schema,\n context,\n stack,\n async runtime() {\n if (runtimePromise) {\n return runtimePromise;\n }\n\n runtimePromise = (async () => {\n const stackInstance = instantiateExecutionStack(stack);\n const driver = stackInstance.driver;\n if (driver === undefined) {\n throw new Error('Relational runtime requires a driver descriptor on the execution stack');\n }\n\n try {\n // `binding` is normalized by resolvePostgresBinding(), so this call site remains\n // type-safe in practice while SqlRuntimeDriverInstance currently uses SqlDriver<unknown>.\n await driver.connect(binding);\n\n return createRuntime({\n stackInstance,\n context,\n driver,\n verify: options.verify ?? { mode: 'onFirstUse', requireMarker: false },\n ...ifDefined('plugins', options.plugins),\n });\n } catch (error) {\n await driver.close().catch(() => undefined);\n throw error;\n }\n })();\n\n runtimePromise.catch(() => {\n runtimePromise = undefined;\n });\n\n return runtimePromise;\n },\n };\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@prisma-next/postgres",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "sideEffects": false,
6
+ "description": "One-liner lazy Postgres client composition for Prisma Next",
7
+ "dependencies": {
8
+ "pg": "8.16.3",
9
+ "@prisma-next/adapter-postgres": "0.0.1",
10
+ "@prisma-next/core-execution-plane": "0.0.1",
11
+ "@prisma-next/sql-contract": "0.0.1",
12
+ "@prisma-next/driver-postgres": "0.0.1",
13
+ "@prisma-next/sql-relational-core": "0.0.1",
14
+ "@prisma-next/target-postgres": "0.0.1",
15
+ "@prisma-next/sql-runtime": "0.0.1",
16
+ "@prisma-next/sql-lane": "0.0.1",
17
+ "@prisma-next/utils": "0.0.1"
18
+ },
19
+ "devDependencies": {
20
+ "@types/pg": "8.16.0",
21
+ "tsdown": "0.18.4",
22
+ "typescript": "5.9.3",
23
+ "vitest": "4.0.17",
24
+ "@prisma-next/tsconfig": "0.0.0",
25
+ "@prisma-next/test-utils": "0.0.1",
26
+ "@prisma-next/tsdown": "0.0.0"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "src"
31
+ ],
32
+ "engines": {
33
+ "node": ">=20"
34
+ },
35
+ "exports": {
36
+ ".": {
37
+ "types": "./dist/runtime.d.mts",
38
+ "import": "./dist/runtime.mjs"
39
+ },
40
+ "./runtime": {
41
+ "types": "./dist/runtime.d.mts",
42
+ "import": "./dist/runtime.mjs"
43
+ },
44
+ "./package.json": "./package.json"
45
+ },
46
+ "main": "./dist/runtime.mjs",
47
+ "module": "./dist/runtime.mjs",
48
+ "types": "./dist/runtime.d.mts",
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "https://github.com/prisma/prisma-next.git",
52
+ "directory": "packages/3-targets/8-clients/postgres"
53
+ },
54
+ "scripts": {
55
+ "build": "tsdown",
56
+ "test": "vitest run",
57
+ "test:coverage": "vitest run --coverage",
58
+ "typecheck": "tsc --project tsconfig.json --noEmit",
59
+ "lint": "biome check . --error-on-warnings",
60
+ "lint:fix": "biome check --write .",
61
+ "lint:fix:unsafe": "biome check --write --unsafe .",
62
+ "clean": "rm -rf dist dist-tsc dist-tsc-prod coverage .tmp-output"
63
+ }
64
+ }
@@ -0,0 +1,9 @@
1
+ export type { PostgresBinding } from '@prisma-next/driver-postgres/runtime';
2
+ export type {
3
+ PostgresClient,
4
+ PostgresOptions,
5
+ PostgresOptionsBase,
6
+ PostgresOptionsWithContract,
7
+ PostgresOptionsWithContractJson,
8
+ } from '../runtime/postgres';
9
+ export { default } from '../runtime/postgres';
@@ -0,0 +1,115 @@
1
+ import type { PostgresBinding } from '@prisma-next/driver-postgres/runtime';
2
+ import type { Client, Pool } from 'pg';
3
+ import { Client as PgClient, Pool as PgPool } from 'pg';
4
+
5
+ export type PostgresBindingInput =
6
+ | {
7
+ readonly binding: PostgresBinding;
8
+ readonly url?: never;
9
+ readonly pg?: never;
10
+ }
11
+ | {
12
+ readonly url: string;
13
+ readonly binding?: never;
14
+ readonly pg?: never;
15
+ }
16
+ | {
17
+ readonly pg: Pool | Client;
18
+ readonly binding?: never;
19
+ readonly url?: never;
20
+ };
21
+
22
+ interface PostgresBindingError extends Error {
23
+ readonly code: 'DRIVER.BINDING_INVALID';
24
+ readonly category: 'RUNTIME';
25
+ readonly severity: 'error';
26
+ readonly details?: Record<string, unknown>;
27
+ }
28
+
29
+ function bindingError(message: string, details?: Record<string, unknown>): PostgresBindingError {
30
+ const error = new Error(message) as PostgresBindingError;
31
+ Object.defineProperty(error, 'name', {
32
+ value: 'RuntimeError',
33
+ configurable: true,
34
+ });
35
+ return Object.assign(error, {
36
+ code: 'DRIVER.BINDING_INVALID' as const,
37
+ category: 'RUNTIME' as const,
38
+ severity: 'error' as const,
39
+ message,
40
+ details,
41
+ });
42
+ }
43
+
44
+ function validatePostgresUrl(url: string): string {
45
+ const trimmed = url.trim();
46
+ if (trimmed.length === 0) {
47
+ throw bindingError('Postgres URL must be a non-empty string', {
48
+ field: 'url',
49
+ reason: 'empty',
50
+ });
51
+ }
52
+
53
+ let parsed: URL;
54
+ try {
55
+ parsed = new URL(trimmed);
56
+ } catch {
57
+ throw bindingError('Postgres URL must be a valid URL', {
58
+ field: 'url',
59
+ reason: 'invalid-url',
60
+ });
61
+ }
62
+
63
+ if (parsed.protocol !== 'postgres:' && parsed.protocol !== 'postgresql:') {
64
+ throw bindingError('Postgres URL must use postgres:// or postgresql://', {
65
+ field: 'url',
66
+ reason: 'invalid-protocol',
67
+ protocol: parsed.protocol,
68
+ });
69
+ }
70
+
71
+ return trimmed;
72
+ }
73
+
74
+ export function resolvePostgresBinding(options: PostgresBindingInput): PostgresBinding {
75
+ const providedCount =
76
+ Number(options.binding !== undefined) +
77
+ Number(options.url !== undefined) +
78
+ Number(options.pg !== undefined);
79
+
80
+ if (providedCount !== 1) {
81
+ throw bindingError('Provide one binding input: binding, url, or pg', {
82
+ providedCount,
83
+ });
84
+ }
85
+
86
+ if (options.binding !== undefined) {
87
+ return options.binding;
88
+ }
89
+
90
+ if (options.url !== undefined) {
91
+ return { kind: 'url', url: validatePostgresUrl(options.url) };
92
+ }
93
+
94
+ const pgBinding = options.pg;
95
+ if (pgBinding === undefined) {
96
+ throw bindingError('Invariant violation: expected pg binding after validation', {
97
+ reason: 'missing-pg-binding',
98
+ });
99
+ }
100
+
101
+ if (pgBinding instanceof PgPool) {
102
+ return { kind: 'pgPool', pool: pgBinding };
103
+ }
104
+
105
+ if (pgBinding instanceof PgClient) {
106
+ return { kind: 'pgClient', client: pgBinding };
107
+ }
108
+
109
+ throw bindingError(
110
+ 'Unable to determine pg binding type from pg input; use binding with explicit kind',
111
+ {
112
+ reason: 'unknown-pg-instance',
113
+ },
114
+ );
115
+ }
@@ -0,0 +1,186 @@
1
+ import postgresAdapter from '@prisma-next/adapter-postgres/runtime';
2
+ import { instantiateExecutionStack } from '@prisma-next/core-execution-plane/stack';
3
+ import type { PostgresDriverCreateOptions } from '@prisma-next/driver-postgres/runtime';
4
+ import postgresDriver from '@prisma-next/driver-postgres/runtime';
5
+ import type {
6
+ ExtractCodecTypes,
7
+ ExtractOperationTypes,
8
+ SqlContract,
9
+ SqlStorage,
10
+ } from '@prisma-next/sql-contract/types';
11
+ import { validateContract } from '@prisma-next/sql-contract/validate';
12
+ import type { SelectBuilder } from '@prisma-next/sql-lane';
13
+ import { sql as sqlBuilder } from '@prisma-next/sql-lane';
14
+ import type { SchemaHandle } from '@prisma-next/sql-relational-core/schema';
15
+ import { schema as schemaBuilder } from '@prisma-next/sql-relational-core/schema';
16
+ import type {
17
+ OperationTypeSignature,
18
+ OperationTypes,
19
+ } from '@prisma-next/sql-relational-core/types';
20
+ import type {
21
+ ExecutionContext,
22
+ Plugin,
23
+ Runtime,
24
+ RuntimeVerifyOptions,
25
+ SqlExecutionStackWithDriver,
26
+ SqlRuntimeExtensionDescriptor,
27
+ } from '@prisma-next/sql-runtime';
28
+ import {
29
+ createExecutionContext,
30
+ createRuntime,
31
+ createSqlExecutionStack,
32
+ } from '@prisma-next/sql-runtime';
33
+ import postgresTarget from '@prisma-next/target-postgres/runtime';
34
+ import { ifDefined } from '@prisma-next/utils/defined';
35
+ import { type PostgresBindingInput, resolvePostgresBinding } from './binding';
36
+
37
+ type NormalizeOperationTypes<T> = {
38
+ [TypeId in keyof T]: {
39
+ [Method in keyof T[TypeId]]: T[TypeId][Method] extends OperationTypeSignature
40
+ ? T[TypeId][Method]
41
+ : OperationTypeSignature;
42
+ };
43
+ };
44
+
45
+ type ToSchemaOperationTypes<T> = T extends OperationTypes ? T : NormalizeOperationTypes<T>;
46
+
47
+ export type PostgresTargetId = 'postgres';
48
+
49
+ export interface PostgresClient<TContract extends SqlContract<SqlStorage>> {
50
+ readonly sql: SelectBuilder<
51
+ TContract,
52
+ unknown,
53
+ ExtractCodecTypes<TContract>,
54
+ ExtractOperationTypes<TContract>
55
+ >;
56
+ readonly schema: SchemaHandle<
57
+ TContract,
58
+ ExtractCodecTypes<TContract>,
59
+ ToSchemaOperationTypes<ExtractOperationTypes<TContract>>
60
+ >;
61
+ readonly context: ExecutionContext<TContract>;
62
+ readonly stack: SqlExecutionStackWithDriver<PostgresTargetId>;
63
+ runtime(): Promise<Runtime>;
64
+ }
65
+
66
+ export interface PostgresOptionsBase<TContract extends SqlContract<SqlStorage>> {
67
+ readonly extensions?: readonly SqlRuntimeExtensionDescriptor<PostgresTargetId>[];
68
+ readonly plugins?: readonly Plugin<TContract>[];
69
+ readonly verify?: RuntimeVerifyOptions;
70
+ readonly cursor?: PostgresDriverCreateOptions['cursor'];
71
+ }
72
+
73
+ export type PostgresOptionsWithContract<TContract extends SqlContract<SqlStorage>> =
74
+ PostgresBindingInput &
75
+ PostgresOptionsBase<TContract> & {
76
+ readonly contract: TContract;
77
+ readonly contractJson?: never;
78
+ };
79
+
80
+ export type PostgresOptionsWithContractJson<TContract extends SqlContract<SqlStorage>> =
81
+ PostgresBindingInput &
82
+ PostgresOptionsBase<TContract> & {
83
+ readonly contractJson: unknown;
84
+ readonly contract?: never;
85
+ };
86
+
87
+ export type PostgresOptions<TContract extends SqlContract<SqlStorage>> =
88
+ | PostgresOptionsWithContract<TContract>
89
+ | PostgresOptionsWithContractJson<TContract>;
90
+
91
+ function hasContractJson<TContract extends SqlContract<SqlStorage>>(
92
+ options: PostgresOptions<TContract>,
93
+ ): options is PostgresOptionsWithContractJson<TContract> {
94
+ return 'contractJson' in options;
95
+ }
96
+
97
+ function resolveContract<TContract extends SqlContract<SqlStorage>>(
98
+ options: PostgresOptions<TContract>,
99
+ ): TContract {
100
+ const contractInput = hasContractJson(options) ? options.contractJson : options.contract;
101
+ return validateContract<TContract>(contractInput);
102
+ }
103
+
104
+ /**
105
+ * Creates a lazy Postgres client from either `contractJson` or a TypeScript-authored `contract`.
106
+ * Static query surfaces are available immediately, while `runtime()` instantiates the driver/pool on first call.
107
+ */
108
+ export default function postgres<TContract extends SqlContract<SqlStorage>>(
109
+ options: PostgresOptionsWithContract<TContract>,
110
+ ): PostgresClient<TContract>;
111
+ export default function postgres<TContract extends SqlContract<SqlStorage>>(
112
+ options: PostgresOptionsWithContractJson<TContract>,
113
+ ): PostgresClient<TContract>;
114
+ export default function postgres<TContract extends SqlContract<SqlStorage>>(
115
+ options: PostgresOptions<TContract>,
116
+ ): PostgresClient<TContract> {
117
+ const contract = resolveContract(options);
118
+ const binding = resolvePostgresBinding(options);
119
+ const stack = createSqlExecutionStack({
120
+ target: postgresTarget,
121
+ adapter: postgresAdapter,
122
+ driver:
123
+ options.cursor === undefined
124
+ ? postgresDriver
125
+ : {
126
+ ...postgresDriver,
127
+ create() {
128
+ return postgresDriver.create({ cursor: options.cursor });
129
+ },
130
+ },
131
+ extensionPacks: options.extensions ?? [],
132
+ });
133
+
134
+ const context = createExecutionContext({
135
+ contract,
136
+ stack,
137
+ });
138
+
139
+ const schema: PostgresClient<TContract>['schema'] = schemaBuilder(context);
140
+ const sql = sqlBuilder({ context });
141
+
142
+ let runtimePromise: Promise<Runtime> | undefined;
143
+
144
+ return {
145
+ sql,
146
+ schema,
147
+ context,
148
+ stack,
149
+ async runtime() {
150
+ if (runtimePromise) {
151
+ return runtimePromise;
152
+ }
153
+
154
+ runtimePromise = (async () => {
155
+ const stackInstance = instantiateExecutionStack(stack);
156
+ const driver = stackInstance.driver;
157
+ if (driver === undefined) {
158
+ throw new Error('Relational runtime requires a driver descriptor on the execution stack');
159
+ }
160
+
161
+ try {
162
+ // `binding` is normalized by resolvePostgresBinding(), so this call site remains
163
+ // type-safe in practice while SqlRuntimeDriverInstance currently uses SqlDriver<unknown>.
164
+ await driver.connect(binding);
165
+
166
+ return createRuntime({
167
+ stackInstance,
168
+ context,
169
+ driver,
170
+ verify: options.verify ?? { mode: 'onFirstUse', requireMarker: false },
171
+ ...ifDefined('plugins', options.plugins),
172
+ });
173
+ } catch (error) {
174
+ await driver.close().catch(() => undefined);
175
+ throw error;
176
+ }
177
+ })();
178
+
179
+ runtimePromise.catch(() => {
180
+ runtimePromise = undefined;
181
+ });
182
+
183
+ return runtimePromise;
184
+ },
185
+ };
186
+ }