@prisma-next/adapter-postgres 0.5.0-dev.4 → 0.5.0-dev.42

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.
Files changed (44) hide show
  1. package/README.md +21 -15
  2. package/dist/{adapter-hNElNHo4.mjs → adapter-_L4wXA4O.mjs} +9 -5
  3. package/dist/adapter-_L4wXA4O.mjs.map +1 -0
  4. package/dist/adapter.d.mts +2 -1
  5. package/dist/adapter.d.mts.map +1 -1
  6. package/dist/adapter.mjs +1 -1
  7. package/dist/column-types.d.mts +15 -23
  8. package/dist/column-types.d.mts.map +1 -1
  9. package/dist/column-types.mjs +14 -57
  10. package/dist/column-types.mjs.map +1 -1
  11. package/dist/control.d.mts +76 -3
  12. package/dist/control.d.mts.map +1 -1
  13. package/dist/control.mjs +44 -6
  14. package/dist/control.mjs.map +1 -1
  15. package/dist/{descriptor-meta-RTDzyrae.mjs → descriptor-meta-Dxnoq_rr.mjs} +22 -21
  16. package/dist/descriptor-meta-Dxnoq_rr.mjs.map +1 -0
  17. package/dist/operation-types.d.mts +11 -10
  18. package/dist/operation-types.d.mts.map +1 -1
  19. package/dist/runtime.d.mts +3 -11
  20. package/dist/runtime.d.mts.map +1 -1
  21. package/dist/runtime.mjs +22 -65
  22. package/dist/runtime.mjs.map +1 -1
  23. package/dist/{sql-renderer-pEaSP82_.mjs → sql-renderer-DLwYpnxz.mjs} +97 -36
  24. package/dist/sql-renderer-DLwYpnxz.mjs.map +1 -0
  25. package/dist/{types-CfRPdAk8.d.mts → types-tLtmYqCO.d.mts} +12 -1
  26. package/dist/types-tLtmYqCO.d.mts.map +1 -0
  27. package/dist/types.d.mts +1 -1
  28. package/package.json +21 -22
  29. package/src/core/adapter.ts +10 -2
  30. package/src/core/codec-lookup.ts +24 -0
  31. package/src/core/control-adapter.ts +68 -1
  32. package/src/core/descriptor-meta.ts +29 -11
  33. package/src/core/sql-renderer.ts +118 -50
  34. package/src/core/types.ts +11 -0
  35. package/src/exports/column-types.ts +13 -58
  36. package/src/exports/control.ts +3 -2
  37. package/src/exports/runtime.ts +28 -41
  38. package/src/types/operation-types.ts +19 -9
  39. package/dist/adapter-hNElNHo4.mjs.map +0 -1
  40. package/dist/descriptor-meta-RTDzyrae.mjs.map +0 -1
  41. package/dist/sql-renderer-pEaSP82_.mjs.map +0 -1
  42. package/dist/types-CfRPdAk8.d.mts.map +0 -1
  43. package/src/core/json-schema-validator.ts +0 -54
  44. package/src/core/standard-schema.ts +0 -71
@@ -1,5 +1,12 @@
1
1
  import type { CodecControlHooks, ExpandNativeTypeInput } from '@prisma-next/family-sql/control';
2
2
  import type { SqlOperationDescriptor } from '@prisma-next/sql-operations';
3
+ import {
4
+ buildOperation,
5
+ type CodecExpression,
6
+ type Expression,
7
+ type TraitExpression,
8
+ toExpr,
9
+ } from '@prisma-next/sql-relational-core/expression';
3
10
  import {
4
11
  PG_BIT_CODEC_ID,
5
12
  PG_BOOL_CODEC_ID,
@@ -128,17 +135,28 @@ const identityHooks: CodecControlHooks = { expandNativeType: ({ nativeType }) =>
128
135
  // Descriptor metadata
129
136
  // ============================================================================
130
137
 
131
- export const postgresQueryOperations: readonly SqlOperationDescriptor[] = [
132
- {
133
- method: 'ilike',
134
- args: [
135
- { traits: ['textual'], nullable: false },
136
- { codecId: PG_TEXT_CODEC_ID, nullable: false },
137
- ],
138
- returns: { codecId: PG_BOOL_CODEC_ID, nullable: false },
139
- lowering: { targetFamily: 'sql', strategy: 'infix', template: '{{self}} ILIKE {{arg0}}' },
140
- },
141
- ];
138
+ type CodecTypesBase = Record<string, { readonly input: unknown; readonly output: unknown }>;
139
+
140
+ export function postgresQueryOperations<
141
+ CT extends CodecTypesBase,
142
+ >(): readonly SqlOperationDescriptor[] {
143
+ return [
144
+ {
145
+ method: 'ilike',
146
+ self: { traits: ['textual'] },
147
+ impl: (
148
+ self: TraitExpression<readonly ['textual'], false, CT>,
149
+ pattern: CodecExpression<'pg/text@1', false, CT>,
150
+ ): Expression<{ codecId: 'pg/bool@1'; nullable: false }> =>
151
+ buildOperation({
152
+ method: 'ilike',
153
+ args: [toExpr(self), toExpr(pattern, PG_TEXT_CODEC_ID)],
154
+ returns: { codecId: PG_BOOL_CODEC_ID, nullable: false },
155
+ lowering: { targetFamily: 'sql', strategy: 'infix', template: '{{self}} ILIKE {{arg0}}' },
156
+ }),
157
+ },
158
+ ];
159
+ }
142
160
 
143
161
  export const postgresAdapterDescriptorMeta = {
144
162
  kind: 'adapter',
@@ -1,3 +1,4 @@
1
+ import type { CodecLookup } from '@prisma-next/framework-components/codec';
1
2
  import {
2
3
  type AggregateExpr,
3
4
  type AnyExpression,
@@ -5,6 +6,7 @@ import {
5
6
  type AnyQueryAst,
6
7
  type BinaryExpr,
7
8
  type ColumnRef,
9
+ collectOrderedParamRefs,
8
10
  type DeleteAst,
9
11
  type InsertAst,
10
12
  type InsertValue,
@@ -20,50 +22,97 @@ import {
20
22
  type ParamRef,
21
23
  type ProjectionItem,
22
24
  type SelectAst,
25
+ type Codec as SqlCodec,
23
26
  type SubqueryExpr,
24
27
  type UpdateAst,
25
28
  } from '@prisma-next/sql-relational-core/ast';
26
- import { PG_JSON_CODEC_ID, PG_JSONB_CODEC_ID } from '@prisma-next/target-postgres/codec-ids';
27
29
  import { escapeLiteral, quoteIdentifier } from '@prisma-next/target-postgres/sql-utils';
28
30
  import type { PostgresContract } from './types';
29
31
 
30
- // Mirrors `VECTOR_CODEC_ID` in `@prisma-next/extension-pgvector/core/constants`.
31
- // Duplicated here rather than imported because the canonical export is not
32
- // part of the extension's public subpath surface, and `@prisma-next/adapter-postgres`
33
- // does not (and should not) take a runtime dependency on the extension package
34
- // just for one constant. The whole `getCodecParamCast` switch is slated for
35
- // removal under TML-2310 ("Move SQL param-cast metadata onto codec descriptors"),
36
- // at which point this and the JSON/JSONB IDs below also disappear.
37
- const VECTOR_CODEC_ID = 'pg/vector@1' as const;
38
-
39
32
  /**
40
- * Map a codec ID to its `::cast` suffix, if Postgres requires one for
41
- * parameterized values (e.g. `$1::vector`, `$1::jsonb`).
33
+ * Postgres native types whose unknown-OID parameter inference is reliable in
34
+ * arbitrary expression positions. Parameters bound to a codec whose
35
+ * `meta.db.sql.postgres.nativeType` falls in this set are emitted as plain
36
+ * `$N`; everything else (including `json`, `jsonb`, extension types like
37
+ * `vector`, and unknown user types) is emitted as `$N::<nativeType>` so the
38
+ * planner picks an unambiguous overload.
39
+ *
40
+ * `json` / `jsonb` are intentionally excluded despite being Postgres builtins:
41
+ * their operator overloads make context inference unreliable in expression
42
+ * positions (e.g. `$1 -> 'key'` is ambiguous between the two).
42
43
  *
43
- * NOTE: hardcoded codec IDs here are a known wart, tracked separately by
44
- * TML-2310 ("Move SQL param-cast metadata onto codec descriptors").
45
- * Until that lands the cast lives on the renderer rather than the codec.
44
+ * Spellings match the on-disk `meta.db.sql.postgres.nativeType` values in
45
+ * `@prisma-next/target-postgres`'s codec definitions, not the `udt_name`
46
+ * abbreviations that ADR 205 used as illustrative shorthand. The lookup-based
47
+ * cast policy compares against these strings directly.
46
48
  */
47
- function getCodecParamCast(codecId: string | undefined): string | undefined {
48
- if (codecId === VECTOR_CODEC_ID) {
49
- return 'vector';
50
- }
51
- if (codecId === PG_JSON_CODEC_ID) {
52
- return 'json';
53
- }
54
- if (codecId === PG_JSONB_CODEC_ID) {
55
- return 'jsonb';
56
- }
57
- return undefined;
49
+ const POSTGRES_INFERRABLE_NATIVE_TYPES: ReadonlySet<string> = new Set([
50
+ // Numeric
51
+ 'integer',
52
+ 'smallint',
53
+ 'bigint',
54
+ 'real',
55
+ 'double precision',
56
+ 'numeric',
57
+ // Boolean
58
+ 'boolean',
59
+ // Strings
60
+ 'text',
61
+ 'character',
62
+ 'character varying',
63
+ // Temporal
64
+ 'timestamp',
65
+ 'timestamp without time zone',
66
+ 'timestamp with time zone',
67
+ 'time',
68
+ 'timetz',
69
+ 'interval',
70
+ // Bit strings
71
+ 'bit',
72
+ 'bit varying',
73
+ ]);
74
+
75
+ function renderTypedParam(
76
+ index: number,
77
+ codecId: string | undefined,
78
+ codecLookup: CodecLookup,
79
+ ): string {
80
+ if (codecId === undefined) {
81
+ return `$${index}`;
82
+ }
83
+ // SQL codecs extend the framework `Codec` base with an optional
84
+ // `meta: CodecMeta`; the framework `CodecLookup.get` returns the base type,
85
+ // so we narrow to `SqlCodec` to read `meta`. Every codec actually
86
+ // registered into a SQL codec lookup conforms to `SqlCodec`.
87
+ const codec = codecLookup.get(codecId) as SqlCodec | undefined;
88
+ if (codec === undefined) {
89
+ throw new Error(
90
+ `Postgres lowering: ParamRef carries codecId "${codecId}" but the ` +
91
+ 'assembled codec lookup has no entry for it. This usually indicates ' +
92
+ 'a missing extension pack in the runtime stack — register the pack ' +
93
+ 'that contributes this codec (e.g. `extensionPacks: [pgvectorRuntime]`), ' +
94
+ 'or use the codec directly from `@prisma-next/target-postgres/codecs` ' +
95
+ "if it's a builtin.",
96
+ );
97
+ }
98
+ const nativeType = codec.meta?.db?.sql?.postgres?.nativeType;
99
+ if (nativeType !== undefined && !POSTGRES_INFERRABLE_NATIVE_TYPES.has(nativeType)) {
100
+ return `$${index}::${nativeType}`;
101
+ }
102
+ return `$${index}`;
58
103
  }
59
104
 
60
- function renderTypedParam(index: number, codecId: string | undefined): string {
61
- const cast = getCodecParamCast(codecId);
62
- return cast ? `$${index}::${cast}` : `$${index}`;
105
+ /**
106
+ * Per-render carrier threaded through every helper. Bundles the param-index
107
+ * map (for `$N` numbering) and the assembled-stack `codecLookup` (for
108
+ * cast policy at the `renderTypedParam` chokepoint). Carrying both on a
109
+ * single value keeps helper signatures stable.
110
+ */
111
+ interface ParamIndexMap {
112
+ readonly indexMap: Map<ParamRef, number>;
113
+ readonly codecLookup: CodecLookup;
63
114
  }
64
115
 
65
- type ParamIndexMap = Map<ParamRef, number>;
66
-
67
116
  /**
68
117
  * Render a SQL query AST to a Postgres-flavored `{ sql, params }` payload.
69
118
  *
@@ -74,32 +123,30 @@ type ParamIndexMap = Map<ParamRef, number>;
74
123
  export function renderLoweredSql(
75
124
  ast: AnyQueryAst,
76
125
  contract: PostgresContract,
126
+ codecLookup: CodecLookup,
77
127
  ): { readonly sql: string; readonly params: readonly unknown[] } {
78
- const collectedParamRefs = ast.collectParamRefs();
79
- const paramIndexMap: ParamIndexMap = new Map();
80
- const params: unknown[] = [];
81
- for (const ref of collectedParamRefs) {
82
- if (paramIndexMap.has(ref)) {
83
- continue;
84
- }
85
- paramIndexMap.set(ref, params.length + 1);
86
- params.push(ref.value);
87
- }
128
+ const orderedRefs = collectOrderedParamRefs(ast);
129
+ const indexMap = new Map<ParamRef, number>();
130
+ const params: unknown[] = orderedRefs.map((ref, i) => {
131
+ indexMap.set(ref, i + 1);
132
+ return ref.value;
133
+ });
134
+ const pim: ParamIndexMap = { indexMap, codecLookup };
88
135
 
89
136
  const node = ast;
90
137
  let sql: string;
91
138
  switch (node.kind) {
92
139
  case 'select':
93
- sql = renderSelect(node, contract, paramIndexMap);
140
+ sql = renderSelect(node, contract, pim);
94
141
  break;
95
142
  case 'insert':
96
- sql = renderInsert(node, contract, paramIndexMap);
143
+ sql = renderInsert(node, contract, pim);
97
144
  break;
98
145
  case 'update':
99
- sql = renderUpdate(node, contract, paramIndexMap);
146
+ sql = renderUpdate(node, contract, pim);
100
147
  break;
101
148
  case 'delete':
102
- sql = renderDelete(node, contract, paramIndexMap);
149
+ sql = renderDelete(node, contract, pim);
103
150
  break;
104
151
  // v8 ignore next 4
105
152
  default:
@@ -171,6 +218,27 @@ function renderProjection(
171
218
  .join(', ');
172
219
  }
173
220
 
221
+ function renderReturning(
222
+ items: ReadonlyArray<ProjectionItem>,
223
+ contract: PostgresContract,
224
+ pim: ParamIndexMap,
225
+ ): string {
226
+ return items
227
+ .map((item) => {
228
+ if (item.expr.kind === 'column-ref') {
229
+ const rendered = renderColumn(item.expr);
230
+ return item.expr.column === item.alias
231
+ ? rendered
232
+ : `${rendered} AS ${quoteIdentifier(item.alias)}`;
233
+ }
234
+ if (item.expr.kind === 'literal') {
235
+ return `${renderLiteral(item.expr)} AS ${quoteIdentifier(item.alias)}`;
236
+ }
237
+ return `${renderExpr(item.expr, contract, pim)} AS ${quoteIdentifier(item.alias)}`;
238
+ })
239
+ .join(', ');
240
+ }
241
+
174
242
  function renderDistinctPrefix(
175
243
  distinct: true | undefined,
176
244
  distinctOn: ReadonlyArray<AnyExpression> | undefined,
@@ -457,11 +525,11 @@ function renderExpr(expr: AnyExpression, contract: PostgresContract, pim: ParamI
457
525
  }
458
526
 
459
527
  function renderParamRef(ref: ParamRef, pim: ParamIndexMap): string {
460
- const index = pim.get(ref);
528
+ const index = pim.indexMap.get(ref);
461
529
  if (index === undefined) {
462
530
  throw new Error('ParamRef not found in index map');
463
531
  }
464
- return renderTypedParam(index, ref.codecId);
532
+ return renderTypedParam(index, ref.codecId, pim.codecLookup);
465
533
  }
466
534
 
467
535
  function renderLiteral(expr: LiteralExpr): string {
@@ -660,7 +728,7 @@ function renderInsert(ast: InsertAst, contract: PostgresContract, pim: ParamInde
660
728
  })()
661
729
  : '';
662
730
  const returningClause = ast.returning?.length
663
- ? ` RETURNING ${ast.returning.map((col) => `${quoteIdentifier(col.table)}.${quoteIdentifier(col.column)}`).join(', ')}`
731
+ ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}`
664
732
  : '';
665
733
 
666
734
  return `${insertClause}${onConflictClause}${returningClause}`;
@@ -693,7 +761,7 @@ function renderUpdate(ast: UpdateAst, contract: PostgresContract, pim: ParamInde
693
761
 
694
762
  const whereClause = ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : '';
695
763
  const returningClause = ast.returning?.length
696
- ? ` RETURNING ${ast.returning.map((col) => `${quoteIdentifier(col.table)}.${quoteIdentifier(col.column)}`).join(', ')}`
764
+ ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}`
697
765
  : '';
698
766
 
699
767
  return `UPDATE ${table} SET ${setClauses.join(', ')}${whereClause}${returningClause}`;
@@ -703,7 +771,7 @@ function renderDelete(ast: DeleteAst, contract: PostgresContract, pim: ParamInde
703
771
  const table = quoteIdentifier(ast.table.name);
704
772
  const whereClause = ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : '';
705
773
  const returningClause = ast.returning?.length
706
- ? ` RETURNING ${ast.returning.map((col) => `${quoteIdentifier(col.table)}.${quoteIdentifier(col.column)}`).join(', ')}`
774
+ ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}`
707
775
  : '';
708
776
 
709
777
  return `DELETE FROM ${table}${whereClause}${returningClause}`;
package/src/core/types.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { Contract } from '@prisma-next/contract/types';
2
+ import type { CodecLookup } from '@prisma-next/framework-components/codec';
2
3
  import type { SqlStorage, StorageColumn, StorageTable } from '@prisma-next/sql-contract/types';
3
4
  import type {
4
5
  AnyQueryAst,
@@ -19,6 +20,16 @@ import type {
19
20
 
20
21
  export interface PostgresAdapterOptions {
21
22
  readonly profileId?: string;
23
+ /**
24
+ * Codec lookup used by the SQL renderer to resolve per-codec metadata at
25
+ * lower-time. Defaults to a Postgres-builtins-only lookup when omitted —
26
+ * see {@link createPostgresBuiltinCodecLookup} in `./codec-lookup`.
27
+ *
28
+ * Stack-aware callers (`SqlRuntimeAdapterDescriptor.create(stack)` /
29
+ * `SqlControlAdapterDescriptor.create(stack)`) supply the assembled stack
30
+ * lookup so extension codecs are visible to the renderer.
31
+ */
32
+ readonly codecLookup?: CodecLookup;
22
33
  }
23
34
 
24
35
  export type PostgresContract = Contract<SqlStorage> & { readonly target: 'postgres' };
@@ -29,12 +29,6 @@ import {
29
29
  SQL_CHAR_CODEC_ID,
30
30
  SQL_VARCHAR_CODEC_ID,
31
31
  } from '@prisma-next/target-postgres/codec-ids';
32
- import {
33
- extractStandardSchemaOutputJsonSchema,
34
- extractStandardSchemaTypeExpression,
35
- isStandardSchemaLike,
36
- type StandardSchemaLike,
37
- } from '../core/standard-schema';
38
32
 
39
33
  export const textColumn = {
40
34
  codecId: PG_TEXT_CODEC_ID,
@@ -164,68 +158,29 @@ export function intervalColumn(precision?: number): ColumnTypeDescriptor & {
164
158
  } as const;
165
159
  }
166
160
 
161
+ /**
162
+ * Postgres `json` column descriptor — untyped raw JSON.
163
+ *
164
+ * For schema-typed JSON columns, use the per-library extension package
165
+ * (`@prisma-next/extension-arktype-json` ships `arktypeJson(schema)` for
166
+ * arktype). The schema-accepting `json(schema)` / `jsonb(schema)`
167
+ * overloads previously shipped from this module retired in Phase C of
168
+ * the codec-registry-unification project — see spec § AC-7.
169
+ */
167
170
  export const jsonColumn = {
168
171
  codecId: PG_JSON_CODEC_ID,
169
172
  nativeType: 'json',
170
173
  } as const satisfies ColumnTypeDescriptor;
171
174
 
175
+ /**
176
+ * Postgres `jsonb` column descriptor — untyped raw JSONB. Same retirement
177
+ * note as {@link jsonColumn}.
178
+ */
172
179
  export const jsonbColumn = {
173
180
  codecId: PG_JSONB_CODEC_ID,
174
181
  nativeType: 'jsonb',
175
182
  } as const satisfies ColumnTypeDescriptor;
176
183
 
177
- type JsonSchemaTypeParams = {
178
- readonly schemaJson: Record<string, unknown>;
179
- readonly type?: string;
180
- };
181
-
182
- function createJsonTypeParams(schema: StandardSchemaLike): JsonSchemaTypeParams {
183
- const outputSchema = extractStandardSchemaOutputJsonSchema(schema);
184
- if (!outputSchema) {
185
- throw new Error('JSON schema must expose ~standard.jsonSchema.output()');
186
- }
187
-
188
- const expression = extractStandardSchemaTypeExpression(schema);
189
- if (expression) {
190
- return { schemaJson: outputSchema, type: expression };
191
- }
192
-
193
- return { schemaJson: outputSchema };
194
- }
195
-
196
- function createJsonColumnFactory(
197
- codecId: string,
198
- nativeType: string,
199
- staticDescriptor: ColumnTypeDescriptor,
200
- ) {
201
- return (schema?: StandardSchemaLike): ColumnTypeDescriptor => {
202
- if (!schema) {
203
- return staticDescriptor;
204
- }
205
-
206
- if (!isStandardSchemaLike(schema)) {
207
- throw new Error(`${nativeType}(schema) expects a Standard Schema value`);
208
- }
209
-
210
- return {
211
- codecId,
212
- nativeType,
213
- typeParams: createJsonTypeParams(schema),
214
- };
215
- };
216
- }
217
-
218
- const _json = createJsonColumnFactory(PG_JSON_CODEC_ID, 'json', jsonColumn);
219
- const _jsonb = createJsonColumnFactory(PG_JSONB_CODEC_ID, 'jsonb', jsonbColumn);
220
-
221
- export function json(schema?: StandardSchemaLike): ColumnTypeDescriptor {
222
- return _json(schema);
223
- }
224
-
225
- export function jsonb(schema?: StandardSchemaLike): ColumnTypeDescriptor {
226
- return _jsonb(schema);
227
- }
228
-
229
184
  export function enumType<const Values extends readonly string[]>(
230
185
  name: string,
231
186
  values: Values,
@@ -21,8 +21,8 @@ const postgresAdapterDescriptor: SqlControlAdapterDescriptor<'postgres'> = {
21
21
  defaultFunctionRegistry: createPostgresDefaultFunctionRegistry(),
22
22
  generatorDescriptors: createPostgresMutationDefaultGeneratorDescriptors(),
23
23
  },
24
- create(_stack): SqlControlAdapter<'postgres'> {
25
- return new PostgresControlAdapter();
24
+ create(stack): SqlControlAdapter<'postgres'> {
25
+ return new PostgresControlAdapter(stack.codecLookup);
26
26
  },
27
27
  };
28
28
 
@@ -31,3 +31,4 @@ export default postgresAdapterDescriptor;
31
31
  export { parsePostgresDefault } from '@prisma-next/target-postgres/default-normalizer';
32
32
  export { normalizeSchemaNativeType } from '@prisma-next/target-postgres/native-type-normalizer';
33
33
  export { escapeLiteral, qualifyName, quoteIdentifier, SqlEscapeError };
34
+ export { PostgresControlAdapter } from '../core/control-adapter';
@@ -1,4 +1,5 @@
1
1
  import type { GeneratedValueSpec } from '@prisma-next/contract/types';
2
+ import { extractCodecLookup } from '@prisma-next/framework-components/control';
2
3
  import type { RuntimeAdapterInstance } from '@prisma-next/framework-components/execution';
3
4
  import { builtinGeneratorIds } from '@prisma-next/ids';
4
5
  import { generateId } from '@prisma-next/ids/runtime';
@@ -8,15 +9,9 @@ import type {
8
9
  RuntimeParameterizedCodecDescriptor,
9
10
  SqlRuntimeAdapterDescriptor,
10
11
  } from '@prisma-next/sql-runtime';
11
- import { PG_JSON_CODEC_ID, PG_JSONB_CODEC_ID } from '@prisma-next/target-postgres/codec-ids';
12
12
  import { codecDefinitions } from '@prisma-next/target-postgres/codecs';
13
- import { type as arktype } from 'arktype';
14
13
  import { createPostgresAdapter } from '../core/adapter';
15
14
  import { postgresAdapterDescriptorMeta, postgresQueryOperations } from '../core/descriptor-meta';
16
- import {
17
- compileJsonSchemaValidator,
18
- type JsonSchemaValidateFn,
19
- } from '../core/json-schema-validator';
20
15
  import type { PostgresContract, PostgresLoweredStatement } from '../core/types';
21
16
 
22
17
  export interface SqlRuntimeAdapter
@@ -31,20 +26,6 @@ function createPostgresCodecRegistry(): CodecRegistry {
31
26
  return registry;
32
27
  }
33
28
 
34
- const jsonTypeParamsSchema = arktype({
35
- schemaJson: 'object',
36
- 'type?': 'string',
37
- });
38
-
39
- /** The inferred type params shape from the arktype schema. */
40
- type JsonTypeParams = typeof jsonTypeParamsSchema.infer;
41
-
42
- /**
43
- * Helper returned by the JSON/JSONB `init` hook.
44
- * Contains a compiled JSON Schema validate function for runtime conformance checks.
45
- */
46
- export type JsonCodecHelper = { readonly validate: JsonSchemaValidateFn };
47
-
48
29
  function createPostgresMutationDefaultGenerators() {
49
30
  return builtinGeneratorIds.map((id) => ({
50
31
  id,
@@ -55,34 +36,40 @@ function createPostgresMutationDefaultGenerators() {
55
36
  }));
56
37
  }
57
38
 
58
- function initJsonCodecHelper(params: JsonTypeParams): JsonCodecHelper {
59
- return { validate: compileJsonSchemaValidator(params.schemaJson as Record<string, unknown>) };
60
- }
61
-
62
- const parameterizedCodecDescriptors = [
63
- {
64
- codecId: PG_JSON_CODEC_ID,
65
- paramsSchema: jsonTypeParamsSchema,
66
- init: initJsonCodecHelper,
67
- },
68
- {
69
- codecId: PG_JSONB_CODEC_ID,
70
- paramsSchema: jsonTypeParamsSchema,
71
- init: initJsonCodecHelper,
72
- },
73
- ] as const satisfies ReadonlyArray<
74
- RuntimeParameterizedCodecDescriptor<JsonTypeParams, JsonCodecHelper>
75
- >;
39
+ /**
40
+ * Phase C of codec-registry-unification: the postgres adapter retains
41
+ * only static raw-JSON / raw-JSONB column descriptors. Schema-typed JSON
42
+ * columns ship from per-library extension packages now —
43
+ * `@prisma-next/extension-arktype-json` for arktype, future zod / valibot
44
+ * extensions when each lands. The previously-shipped
45
+ * `parameterizedCodecDescriptors` for `pg/json@1` / `pg/jsonb@1` retired
46
+ * with the schema-typed surface; the unified descriptor map auto-lifts
47
+ * the raw json/jsonb codecs from `codecs:` via the synthesis bridge for
48
+ * codec-id-keyed metadata reads.
49
+ */
50
+ const parameterizedCodecDescriptors: ReadonlyArray<RuntimeParameterizedCodecDescriptor> = [];
76
51
 
77
52
  const postgresRuntimeAdapterDescriptor: SqlRuntimeAdapterDescriptor<'postgres', SqlRuntimeAdapter> =
78
53
  {
79
54
  ...postgresAdapterDescriptorMeta,
80
55
  codecs: createPostgresCodecRegistry,
81
56
  parameterizedCodecs: () => parameterizedCodecDescriptors,
82
- queryOperations: () => postgresQueryOperations,
57
+ queryOperations: () => postgresQueryOperations(),
83
58
  mutationDefaultGenerators: createPostgresMutationDefaultGenerators,
84
- create(_stack): SqlRuntimeAdapter {
85
- return createPostgresAdapter();
59
+ create(stack): SqlRuntimeAdapter {
60
+ // The runtime `ExecutionStack` does not (yet) carry a pre-assembled
61
+ // `codecLookup` field the way the control `ControlStack` does, so we
62
+ // derive an equivalent lookup here from the stack's component metadata
63
+ // (target + adapter + extension packs) using the same assembly helper
64
+ // that `createControlStack` uses. This keeps the renderer fed with the
65
+ // same codec set on both planes — including extension-contributed
66
+ // codecs like `pg/vector@1` from `@prisma-next/extension-pgvector`.
67
+ const codecLookup = extractCodecLookup([
68
+ stack.target,
69
+ stack.adapter,
70
+ ...stack.extensionPacks,
71
+ ]);
72
+ return createPostgresAdapter({ codecLookup });
86
73
  },
87
74
  };
88
75
 
@@ -1,11 +1,21 @@
1
1
  import type { SqlQueryOperationTypes } from '@prisma-next/sql-contract/types';
2
+ import type {
3
+ CodecExpression,
4
+ Expression,
5
+ TraitExpression,
6
+ } from '@prisma-next/sql-relational-core/expression';
2
7
 
3
- export type QueryOperationTypes = SqlQueryOperationTypes<{
4
- readonly ilike: {
5
- readonly args: readonly [
6
- { readonly traits: readonly ['textual']; readonly nullable: false },
7
- { readonly codecId: 'pg/text@1'; readonly nullable: false },
8
- ];
9
- readonly returns: { readonly codecId: 'pg/bool@1'; readonly nullable: false };
10
- };
11
- }>;
8
+ type CodecTypesBase = Record<string, { readonly input: unknown; readonly output: unknown }>;
9
+
10
+ export type QueryOperationTypes<CT extends CodecTypesBase> = SqlQueryOperationTypes<
11
+ CT,
12
+ {
13
+ readonly ilike: {
14
+ readonly self: { readonly traits: readonly ['textual'] };
15
+ readonly impl: (
16
+ self: TraitExpression<readonly ['textual'], false, CT>,
17
+ pattern: CodecExpression<'pg/text@1', false, CT>,
18
+ ) => Expression<{ codecId: 'pg/bool@1'; nullable: false }>;
19
+ };
20
+ }
21
+ >;
@@ -1 +0,0 @@
1
- {"version":3,"file":"adapter-hNElNHo4.mjs","names":["parameterizedCodecs: ReadonlyArray<CodecParamsDescriptor>"],"sources":["../src/core/adapter.ts"],"sourcesContent":["import {\n type Adapter,\n type AdapterProfile,\n type AnyQueryAst,\n type CodecParamsDescriptor,\n createCodecRegistry,\n type LowererContext,\n} from '@prisma-next/sql-relational-core/ast';\nimport { codecDefinitions } from '@prisma-next/target-postgres/codecs';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { renderLoweredSql } from './sql-renderer';\nimport type { PostgresAdapterOptions, PostgresContract, PostgresLoweredStatement } from './types';\n\nconst defaultCapabilities = Object.freeze({\n postgres: {\n orderBy: true,\n limit: true,\n lateral: true,\n jsonAgg: true,\n returning: true,\n },\n sql: {\n enums: true,\n returning: true,\n defaultInInsert: true,\n },\n});\n\ntype AdapterCodec = (typeof codecDefinitions)[keyof typeof codecDefinitions]['codec'];\ntype ParameterizedCodec = AdapterCodec & {\n readonly paramsSchema: NonNullable<AdapterCodec['paramsSchema']>;\n};\n\nconst parameterizedCodecs: ReadonlyArray<CodecParamsDescriptor> = Object.values(codecDefinitions)\n .map((definition) => definition.codec)\n .filter((codec): codec is ParameterizedCodec => codec.paramsSchema !== undefined)\n .map((codec) =>\n Object.freeze({\n codecId: codec.id,\n paramsSchema: codec.paramsSchema,\n ...ifDefined('init', codec.init),\n }),\n );\n\nclass PostgresAdapterImpl\n implements Adapter<AnyQueryAst, PostgresContract, PostgresLoweredStatement>\n{\n // These fields make the adapter instance structurally compatible with\n // RuntimeAdapterInstance<'sql', 'postgres'> without introducing a runtime-plane dependency.\n readonly familyId = 'sql' as const;\n readonly targetId = 'postgres' as const;\n\n readonly profile: AdapterProfile<'postgres'>;\n private readonly codecRegistry = (() => {\n const registry = createCodecRegistry();\n for (const definition of Object.values(codecDefinitions)) {\n registry.register(definition.codec);\n }\n return registry;\n })();\n\n constructor(options?: PostgresAdapterOptions) {\n this.profile = Object.freeze({\n id: options?.profileId ?? 'postgres/default@1',\n target: 'postgres',\n capabilities: defaultCapabilities,\n codecs: () => this.codecRegistry,\n readMarkerStatement: () => ({\n sql: 'select core_hash, profile_hash, contract_json, canonical_version, updated_at, app_tag, meta from prisma_contract.marker where id = $1',\n params: [1],\n }),\n });\n }\n\n parameterizedCodecs(): ReadonlyArray<CodecParamsDescriptor> {\n return parameterizedCodecs;\n }\n\n lower(ast: AnyQueryAst, context: LowererContext<PostgresContract>): PostgresLoweredStatement {\n return renderLoweredSql(ast, context.contract);\n }\n}\n\nexport function createPostgresAdapter(options?: PostgresAdapterOptions) {\n return Object.freeze(new PostgresAdapterImpl(options));\n}\n"],"mappings":";;;;;;AAaA,MAAM,sBAAsB,OAAO,OAAO;CACxC,UAAU;EACR,SAAS;EACT,OAAO;EACP,SAAS;EACT,SAAS;EACT,WAAW;EACZ;CACD,KAAK;EACH,OAAO;EACP,WAAW;EACX,iBAAiB;EAClB;CACF,CAAC;AAOF,MAAMA,sBAA4D,OAAO,OAAO,iBAAiB,CAC9F,KAAK,eAAe,WAAW,MAAM,CACrC,QAAQ,UAAuC,MAAM,iBAAiB,OAAU,CAChF,KAAK,UACJ,OAAO,OAAO;CACZ,SAAS,MAAM;CACf,cAAc,MAAM;CACpB,GAAG,UAAU,QAAQ,MAAM,KAAK;CACjC,CAAC,CACH;AAEH,IAAM,sBAAN,MAEA;CAGE,AAAS,WAAW;CACpB,AAAS,WAAW;CAEpB,AAAS;CACT,AAAiB,uBAAuB;EACtC,MAAM,WAAW,qBAAqB;AACtC,OAAK,MAAM,cAAc,OAAO,OAAO,iBAAiB,CACtD,UAAS,SAAS,WAAW,MAAM;AAErC,SAAO;KACL;CAEJ,YAAY,SAAkC;AAC5C,OAAK,UAAU,OAAO,OAAO;GAC3B,IAAI,SAAS,aAAa;GAC1B,QAAQ;GACR,cAAc;GACd,cAAc,KAAK;GACnB,4BAA4B;IAC1B,KAAK;IACL,QAAQ,CAAC,EAAE;IACZ;GACF,CAAC;;CAGJ,sBAA4D;AAC1D,SAAO;;CAGT,MAAM,KAAkB,SAAqE;AAC3F,SAAO,iBAAiB,KAAK,QAAQ,SAAS;;;AAIlD,SAAgB,sBAAsB,SAAkC;AACtE,QAAO,OAAO,OAAO,IAAI,oBAAoB,QAAQ,CAAC"}