@prisma-next/adapter-postgres 0.5.0-dev.81 → 0.5.0-dev.83

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.
@@ -1 +1 @@
1
- {"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/control-adapter.ts","../src/exports/control.ts"],"mappings":";;;;;;;;;;;;;;;;cAiCa,sBAAA,YAAkC,iBAAA;EAAA,SACpC,QAAA;EAAA,SACA,QAAA;EAAA,iBAEQ,WAAA;EAiBQ;;;;;;;cARb,WAAA,GAAc,WAAA;EAuFhB;;;;EAAA,SA/ED,gBAAA,SAAgB,sBAAA;EA4Id;;;;;EAAA,SArIF,mBAAA,SAAmB,2BAAA;EA3BnB;;;;;;;;EAqCT,KAAA,CAAM,GAAA,EAAK,WAAA,EAAa,OAAA,EAAS,cAAA,YAA0B,gBAAA;EAV/B;;;;;;;;EAsBtB,UAAA,CACJ,MAAA,EAAQ,qBAAA,qBACR,KAAA,WACC,OAAA,CAAQ,oBAAA;EAFT;;;;;;EAgDI,cAAA,CACJ,MAAA,EAAQ,qBAAA,sBACP,OAAA,CAAQ,WAAA,SAAoB,oBAAA;EAA5B;;;;;;;;;;;;;;EAwDG,UAAA,CACJ,MAAA,EAAQ,qBAAA,qBACR,SAAA,YACA,MAAA,YACC,OAAA,CAAQ,WAAA;;AC3LmC;;UD+jBhC,kBAAA;AAAA;;;cCtjBV,yBAAA,EAA2B,2BAAA"}
1
+ {"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/control-adapter.ts","../src/exports/control.ts"],"mappings":";;;;;;;;;;;;;;;;cAiCa,sBAAA,YAAkC,iBAAA;EAAA,SACpC,QAAA;EAAA,SACA,QAAA;EAAA,iBAEQ,WAAA;EAiBQ;;;;;;;cARb,WAAA,GAAc,WAAA;EAuFhB;;;;EAAA,SA/ED,gBAAA,SAAgB,sBAAA;EA4Id;;;;;EAAA,SArIF,mBAAA,SAAmB,2BAAA;EA3BnB;;;;;;;;EAqCT,KAAA,CAAM,GAAA,EAAK,WAAA,EAAa,OAAA,EAAS,cAAA,YAA0B,gBAAA;EAV/B;;;;;;;;EAsBtB,UAAA,CACJ,MAAA,EAAQ,qBAAA,qBACR,KAAA,WACC,OAAA,CAAQ,oBAAA;EAFT;;;;;;EAgDI,cAAA,CACJ,MAAA,EAAQ,qBAAA,sBACP,OAAA,CAAQ,WAAA,SAAoB,oBAAA;EAA5B;;;;;;;;;;;;;;EAwDG,UAAA,CACJ,MAAA,EAAQ,qBAAA,qBACR,SAAA,YACA,MAAA,YACC,OAAA,CAAQ,WAAA;;AC3LmC;;UDslBhC,kBAAA;AAAA;;;cC7kBV,yBAAA,EAA2B,2BAAA"}
package/dist/control.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { n as createPostgresBuiltinCodecLookup, t as renderLoweredSql } from "./sql-renderer-wTVSEy5H.mjs";
2
- import { r as pgEnumControlHooks, t as postgresAdapterDescriptorMeta } from "./descriptor-meta-C2VasIft.mjs";
2
+ import { r as pgEnumControlHooks, t as postgresAdapterDescriptorMeta } from "./descriptor-meta-CyjnYUWG.mjs";
3
3
  import { SqlEscapeError, escapeLiteral, qualifyName, quoteIdentifier } from "@prisma-next/target-postgres/sql-utils";
4
4
  import { parseContractMarkerRow } from "@prisma-next/family-sql/verify";
5
5
  import { parsePostgresDefault, parsePostgresDefault as parsePostgresDefault$1 } from "@prisma-next/target-postgres/default-normalizer";
@@ -208,11 +208,14 @@ var PostgresControlAdapter = class {
208
208
  i.indexname,
209
209
  ix.indisunique,
210
210
  a.attname,
211
- a.attnum
211
+ a.attnum,
212
+ am.amname,
213
+ ic.reloptions
212
214
  FROM pg_indexes i
213
215
  JOIN pg_class ic ON ic.relname = i.indexname
214
216
  JOIN pg_namespace ins ON ins.oid = ic.relnamespace AND ins.nspname = $1
215
217
  JOIN pg_index ix ON ix.indexrelid = ic.oid
218
+ JOIN pg_am am ON am.oid = ic.relam
216
219
  JOIN pg_class t ON t.oid = ix.indrelid
217
220
  JOIN pg_namespace tn ON tn.oid = t.relnamespace AND tn.nspname = $1
218
221
  LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey) AND a.attnum > 0
@@ -313,16 +316,24 @@ var PostgresControlAdapter = class {
313
316
  if (!idxRow.attname) continue;
314
317
  const existing = indexesMap.get(idxRow.indexname);
315
318
  if (existing) existing.columns.push(idxRow.attname);
316
- else indexesMap.set(idxRow.indexname, {
317
- columns: [idxRow.attname],
318
- name: idxRow.indexname,
319
- unique: idxRow.indisunique
320
- });
319
+ else {
320
+ const indexType = idxRow.amname === "btree" ? void 0 : idxRow.amname;
321
+ const indexOptions = parsePgReloptions(idxRow.reloptions, idxRow.indexname);
322
+ indexesMap.set(idxRow.indexname, {
323
+ columns: [idxRow.attname],
324
+ name: idxRow.indexname,
325
+ unique: idxRow.indisunique,
326
+ type: indexType,
327
+ options: indexOptions
328
+ });
329
+ }
321
330
  }
322
331
  const indexes = Array.from(indexesMap.values()).map((idx) => ({
323
332
  columns: Object.freeze([...idx.columns]),
324
333
  name: idx.name,
325
- unique: idx.unique
334
+ unique: idx.unique,
335
+ ...idx.type !== void 0 && { type: idx.type },
336
+ ...idx.options !== void 0 && { options: idx.options }
326
337
  }));
327
338
  tables[tableName] = {
328
339
  name: tableName,
@@ -394,6 +405,28 @@ function mapReferentialAction(rule) {
394
405
  * Groups an array of objects by a specified key.
395
406
  * Returns a Map for O(1) lookup by group key.
396
407
  */
408
+ /**
409
+ * Parses a `pg_class.reloptions` array into a `Record<string, string>`.
410
+ *
411
+ * Postgres returns reloptions as a `text[]` whose entries are `key=value`
412
+ * strings; the value side is always a string regardless of the underlying
413
+ * scalar type. The verifier compares contract options to introspected
414
+ * options after coercing both sides to strings, so keeping the raw text
415
+ * here is correct.
416
+ *
417
+ * Returns `undefined` when the input is null/empty (no WITH clause).
418
+ */
419
+ function parsePgReloptions(reloptions, indexName) {
420
+ if (!reloptions || reloptions.length === 0) return;
421
+ const result = {};
422
+ for (const entry of reloptions) {
423
+ const eq = entry.indexOf("=");
424
+ if (eq === -1) throw new Error(`Postgres introspection: malformed reloption entry "${entry}" on index "${indexName}" (expected "key=value")`);
425
+ const key = entry.slice(0, eq);
426
+ result[key] = entry.slice(eq + 1);
427
+ }
428
+ return Object.keys(result).length > 0 ? result : void 0;
429
+ }
397
430
  function groupBy(items, key) {
398
431
  const map = /* @__PURE__ */ new Map();
399
432
  for (const item of items) {
@@ -1 +1 @@
1
- {"version":3,"file":"control.mjs","names":["parsePostgresDefault","normalizeSchemaNativeType"],"sources":["../src/core/control-adapter.ts","../src/core/control-mutation-defaults.ts","../src/exports/control.ts"],"sourcesContent":["import type { ContractMarkerRecord } from '@prisma-next/contract/types';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport { parseContractMarkerRow } from '@prisma-next/family-sql/verify';\nimport type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport type { ControlDriverInstance } from '@prisma-next/framework-components/control';\nimport type {\n AnyQueryAst,\n LoweredStatement,\n LowererContext,\n} from '@prisma-next/sql-relational-core/ast';\nimport type {\n DependencyIR,\n PrimaryKey,\n SqlColumnIR,\n SqlForeignKeyIR,\n SqlIndexIR,\n SqlReferentialAction,\n SqlSchemaIR,\n SqlTableIR,\n SqlUniqueIR,\n} from '@prisma-next/sql-schema-ir/types';\nimport { parsePostgresDefault } from '@prisma-next/target-postgres/default-normalizer';\nimport { normalizeSchemaNativeType } from '@prisma-next/target-postgres/native-type-normalizer';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { createPostgresBuiltinCodecLookup } from './codec-lookup';\nimport { pgEnumControlHooks } from './enum-control-hooks';\nimport { renderLoweredSql } from './sql-renderer';\nimport type { PostgresContract } from './types';\n\n/**\n * Postgres control plane adapter for control-plane operations like introspection.\n * Provides target-specific implementations for control-plane domain actions.\n */\nexport class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {\n readonly familyId = 'sql' as const;\n readonly targetId = 'postgres' as const;\n\n private readonly codecLookup: CodecLookup;\n\n /**\n * @param codecLookup - Codec lookup used by the SQL renderer to resolve\n * per-codec metadata at lower-time. Defaults to a Postgres-builtins-only\n * lookup when omitted. Stack-aware callers\n * (`SqlControlAdapterDescriptor.create(stack)`) supply\n * `stack.codecLookup` so extension codecs are visible to the renderer.\n */\n constructor(codecLookup?: CodecLookup) {\n this.codecLookup = codecLookup ?? createPostgresBuiltinCodecLookup();\n }\n\n /**\n * Target-specific normalizer for raw Postgres default expressions.\n * Used by schema verification to normalize raw defaults before comparison.\n */\n readonly normalizeDefault = parsePostgresDefault;\n\n /**\n * Target-specific normalizer for Postgres schema native type names.\n * Used by schema verification to normalize introspected type names\n * before comparison with contract native types.\n */\n readonly normalizeNativeType = normalizeSchemaNativeType;\n\n /**\n * Lower a SQL query AST into a Postgres-flavored `{ sql, params }` payload.\n *\n * Delegates to the shared `renderLoweredSql` renderer so the control adapter\n * emits byte-identical SQL to `PostgresAdapterImpl.lower()` for the same AST\n * and contract. Used at migration plan/emit time (e.g. by `dataTransform`)\n * without instantiating the runtime adapter.\n */\n lower(ast: AnyQueryAst, context: LowererContext<unknown>): LoweredStatement {\n return renderLoweredSql(ast, context.contract as PostgresContract, this.codecLookup);\n }\n\n /**\n * Reads the contract marker from `prisma_contract.marker`. Probes\n * `information_schema.tables` first so a fresh database (where the\n * `prisma_contract` schema doesn't yet exist) returns `null` instead of a\n * \"relation does not exist\" error — some Postgres wire-protocol clients\n * (e.g. PGlite's TCP proxy) don't fully recover from extended-protocol\n * parse errors, so we probe before reading.\n */\n async readMarker(\n driver: ControlDriverInstance<'sql', 'postgres'>,\n space: string,\n ): Promise<ContractMarkerRecord | null> {\n const exists = await driver.query(\n `select 1\n from information_schema.tables\n where table_schema = $1 and table_name = $2`,\n ['prisma_contract', 'marker'],\n );\n if (exists.rows.length === 0) {\n return null;\n }\n\n const result = await driver.query<{\n core_hash: string;\n profile_hash: string;\n contract_json: unknown | null;\n canonical_version: number | null;\n updated_at: Date | string;\n app_tag: string | null;\n meta: unknown | null;\n invariants: readonly string[];\n }>(\n `select\n core_hash,\n profile_hash,\n contract_json,\n canonical_version,\n updated_at,\n app_tag,\n meta,\n invariants\n from prisma_contract.marker\n where space = $1`,\n [space],\n );\n\n const row = result.rows[0];\n if (!row) return null;\n return parseContractMarkerRow(row);\n }\n\n /**\n * Reads every row from `prisma_contract.marker` and returns them keyed\n * by `space`. Mirrors the existence probe in {@link readMarker}: a\n * fresh database without the `prisma_contract` schema returns an empty\n * map rather than raising \"relation does not exist\".\n */\n async readAllMarkers(\n driver: ControlDriverInstance<'sql', 'postgres'>,\n ): Promise<ReadonlyMap<string, ContractMarkerRecord>> {\n const exists = await driver.query(\n `select 1\n from information_schema.tables\n where table_schema = $1 and table_name = $2`,\n ['prisma_contract', 'marker'],\n );\n if (exists.rows.length === 0) {\n return new Map();\n }\n\n const result = await driver.query<{\n space: string;\n core_hash: string;\n profile_hash: string;\n contract_json: unknown | null;\n canonical_version: number | null;\n updated_at: Date | string;\n app_tag: string | null;\n meta: unknown | null;\n invariants: readonly string[];\n }>(\n `select\n space,\n core_hash,\n profile_hash,\n contract_json,\n canonical_version,\n updated_at,\n app_tag,\n meta,\n invariants\n from prisma_contract.marker`,\n );\n\n const rows = new Map<string, ContractMarkerRecord>();\n for (const row of result.rows) {\n rows.set(row.space, parseContractMarkerRow(row));\n }\n return rows;\n }\n\n /**\n * Introspects a Postgres database schema and returns a raw SqlSchemaIR.\n *\n * This is a pure schema discovery operation that queries the Postgres catalog\n * and returns the schema structure without type mapping or contract enrichment.\n * Type mapping and enrichment are handled separately by enrichment helpers.\n *\n * Uses batched queries to minimize database round trips (7 queries instead of 5T+3).\n *\n * @param driver - ControlDriverInstance<'sql', 'postgres'> instance for executing queries\n * @param contract - Optional contract for contract-guided introspection (filtering, optimization)\n * @param schema - Schema name to introspect (defaults to 'public')\n * @returns Promise resolving to SqlSchemaIR representing the live database schema\n */\n async introspect(\n driver: ControlDriverInstance<'sql', 'postgres'>,\n _contract?: unknown,\n schema = 'public',\n ): Promise<SqlSchemaIR> {\n // Execute all queries in parallel for efficiency (7 queries instead of 5T+3)\n const [\n tablesResult,\n columnsResult,\n pkResult,\n fkResult,\n uniqueResult,\n indexResult,\n extensionsResult,\n ] = await Promise.all([\n // Query all tables\n driver.query<{ table_name: string }>(\n `SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = $1\n AND table_type = 'BASE TABLE'\n ORDER BY table_name`,\n [schema],\n ),\n // Query all columns for all tables in schema\n driver.query<{\n table_name: string;\n column_name: string;\n data_type: string;\n udt_name: string;\n is_nullable: string;\n character_maximum_length: number | null;\n numeric_precision: number | null;\n numeric_scale: number | null;\n column_default: string | null;\n formatted_type: string | null;\n }>(\n `SELECT\n c.table_name,\n column_name,\n data_type,\n udt_name,\n is_nullable,\n character_maximum_length,\n numeric_precision,\n numeric_scale,\n column_default,\n format_type(a.atttypid, a.atttypmod) AS formatted_type\n FROM information_schema.columns c\n JOIN pg_catalog.pg_class cl\n ON cl.relname = c.table_name\n JOIN pg_catalog.pg_namespace ns\n ON ns.nspname = c.table_schema\n AND ns.oid = cl.relnamespace\n JOIN pg_catalog.pg_attribute a\n ON a.attrelid = cl.oid\n AND a.attname = c.column_name\n AND a.attnum > 0\n AND NOT a.attisdropped\n WHERE c.table_schema = $1\n ORDER BY c.table_name, c.ordinal_position`,\n [schema],\n ),\n // Query all primary keys for all tables in schema\n driver.query<{\n table_name: string;\n constraint_name: string;\n column_name: string;\n ordinal_position: number;\n }>(\n `SELECT\n tc.table_name,\n tc.constraint_name,\n kcu.column_name,\n kcu.ordinal_position\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n AND tc.table_name = kcu.table_name\n WHERE tc.table_schema = $1\n AND tc.constraint_type = 'PRIMARY KEY'\n ORDER BY tc.table_name, kcu.ordinal_position`,\n [schema],\n ),\n // Query all foreign keys for all tables in schema, including referential actions.\n // Uses pg_catalog for correct positional pairing of composite FK columns\n // (information_schema.constraint_column_usage lacks ordinal_position,\n // which causes Cartesian products for multi-column FKs).\n driver.query<{\n table_name: string;\n constraint_name: string;\n column_name: string;\n ordinal_position: number;\n referenced_table_schema: string;\n referenced_table_name: string;\n referenced_column_name: string;\n delete_rule: string;\n update_rule: string;\n }>(\n `SELECT\n tc.table_name,\n tc.constraint_name,\n kcu.column_name,\n kcu.ordinal_position,\n ref_ns.nspname AS referenced_table_schema,\n ref_cl.relname AS referenced_table_name,\n ref_att.attname AS referenced_column_name,\n rc.delete_rule,\n rc.update_rule\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n AND tc.table_name = kcu.table_name\n JOIN pg_catalog.pg_constraint pgc\n ON pgc.conname = tc.constraint_name\n AND pgc.connamespace = (\n SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = tc.table_schema\n )\n JOIN pg_catalog.pg_class ref_cl\n ON ref_cl.oid = pgc.confrelid\n JOIN pg_catalog.pg_namespace ref_ns\n ON ref_ns.oid = ref_cl.relnamespace\n JOIN pg_catalog.pg_attribute ref_att\n ON ref_att.attrelid = pgc.confrelid\n AND ref_att.attnum = pgc.confkey[kcu.ordinal_position]\n JOIN information_schema.referential_constraints rc\n ON rc.constraint_name = tc.constraint_name\n AND rc.constraint_schema = tc.table_schema\n WHERE tc.table_schema = $1\n AND tc.constraint_type = 'FOREIGN KEY'\n ORDER BY tc.table_name, tc.constraint_name, kcu.ordinal_position`,\n [schema],\n ),\n // Query all unique constraints for all tables in schema (excluding PKs)\n driver.query<{\n table_name: string;\n constraint_name: string;\n column_name: string;\n ordinal_position: number;\n }>(\n `SELECT\n tc.table_name,\n tc.constraint_name,\n kcu.column_name,\n kcu.ordinal_position\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n AND tc.table_name = kcu.table_name\n WHERE tc.table_schema = $1\n AND tc.constraint_type = 'UNIQUE'\n ORDER BY tc.table_name, tc.constraint_name, kcu.ordinal_position`,\n [schema],\n ),\n // Query all indexes for all tables in schema (excluding constraints)\n driver.query<{\n tablename: string;\n indexname: string;\n indisunique: boolean;\n attname: string;\n attnum: number;\n }>(\n `SELECT\n i.tablename,\n i.indexname,\n ix.indisunique,\n a.attname,\n a.attnum\n FROM pg_indexes i\n JOIN pg_class ic ON ic.relname = i.indexname\n JOIN pg_namespace ins ON ins.oid = ic.relnamespace AND ins.nspname = $1\n JOIN pg_index ix ON ix.indexrelid = ic.oid\n JOIN pg_class t ON t.oid = ix.indrelid\n JOIN pg_namespace tn ON tn.oid = t.relnamespace AND tn.nspname = $1\n LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey) AND a.attnum > 0\n WHERE i.schemaname = $1\n AND NOT EXISTS (\n SELECT 1\n FROM information_schema.table_constraints tc\n WHERE tc.table_schema = $1\n AND tc.table_name = i.tablename\n AND tc.constraint_name = i.indexname\n )\n ORDER BY i.tablename, i.indexname, a.attnum`,\n [schema],\n ),\n // Query extensions\n driver.query<{ extname: string }>(\n `SELECT extname\n FROM pg_extension\n ORDER BY extname`,\n [],\n ),\n ]);\n\n // Group results by table name for efficient lookup\n const columnsByTable = groupBy(columnsResult.rows, 'table_name');\n const pksByTable = groupBy(pkResult.rows, 'table_name');\n const fksByTable = groupBy(fkResult.rows, 'table_name');\n const uniquesByTable = groupBy(uniqueResult.rows, 'table_name');\n const indexesByTable = groupBy(indexResult.rows, 'tablename');\n\n // Get set of PK constraint names per table (to exclude from uniques)\n const pkConstraintsByTable = new Map<string, Set<string>>();\n for (const row of pkResult.rows) {\n let constraints = pkConstraintsByTable.get(row.table_name);\n if (!constraints) {\n constraints = new Set();\n pkConstraintsByTable.set(row.table_name, constraints);\n }\n constraints.add(row.constraint_name);\n }\n\n const tables: Record<string, SqlTableIR> = {};\n\n for (const tableRow of tablesResult.rows) {\n const tableName = tableRow.table_name;\n\n // Process columns for this table\n const columns: Record<string, SqlColumnIR> = {};\n for (const colRow of columnsByTable.get(tableName) ?? []) {\n let nativeType = colRow.udt_name;\n const formattedType = colRow.formatted_type\n ? normalizeFormattedType(colRow.formatted_type, colRow.data_type, colRow.udt_name)\n : null;\n if (formattedType) {\n nativeType = formattedType;\n } else if (colRow.data_type === 'character varying' || colRow.data_type === 'character') {\n if (colRow.character_maximum_length) {\n nativeType = `${colRow.data_type}(${colRow.character_maximum_length})`;\n } else {\n nativeType = colRow.data_type;\n }\n } else if (colRow.data_type === 'numeric' || colRow.data_type === 'decimal') {\n if (colRow.numeric_precision && colRow.numeric_scale !== null) {\n nativeType = `${colRow.data_type}(${colRow.numeric_precision},${colRow.numeric_scale})`;\n } else if (colRow.numeric_precision) {\n nativeType = `${colRow.data_type}(${colRow.numeric_precision})`;\n } else {\n nativeType = colRow.data_type;\n }\n } else {\n nativeType = colRow.udt_name || colRow.data_type;\n }\n\n columns[colRow.column_name] = {\n name: colRow.column_name,\n nativeType,\n nullable: colRow.is_nullable === 'YES',\n ...ifDefined('default', colRow.column_default ?? undefined),\n };\n }\n\n // Process primary key\n const pkRows = [...(pksByTable.get(tableName) ?? [])];\n const primaryKeyColumns = pkRows\n .sort((a, b) => a.ordinal_position - b.ordinal_position)\n .map((row) => row.column_name);\n const primaryKey: PrimaryKey | undefined =\n primaryKeyColumns.length > 0\n ? {\n columns: primaryKeyColumns,\n ...(pkRows[0]?.constraint_name ? { name: pkRows[0].constraint_name } : {}),\n }\n : undefined;\n\n // Process foreign keys\n const foreignKeysMap = new Map<\n string,\n {\n columns: string[];\n referencedTable: string;\n referencedColumns: string[];\n name: string;\n deleteRule: string;\n updateRule: string;\n }\n >();\n for (const fkRow of fksByTable.get(tableName) ?? []) {\n const existing = foreignKeysMap.get(fkRow.constraint_name);\n if (existing) {\n existing.columns.push(fkRow.column_name);\n existing.referencedColumns.push(fkRow.referenced_column_name);\n } else {\n foreignKeysMap.set(fkRow.constraint_name, {\n columns: [fkRow.column_name],\n referencedTable: fkRow.referenced_table_name,\n referencedColumns: [fkRow.referenced_column_name],\n name: fkRow.constraint_name,\n deleteRule: fkRow.delete_rule,\n updateRule: fkRow.update_rule,\n });\n }\n }\n const foreignKeys: readonly SqlForeignKeyIR[] = Array.from(foreignKeysMap.values()).map(\n (fk) => ({\n columns: Object.freeze([...fk.columns]) as readonly string[],\n referencedTable: fk.referencedTable,\n referencedColumns: Object.freeze([...fk.referencedColumns]) as readonly string[],\n name: fk.name,\n ...ifDefined('onDelete', mapReferentialAction(fk.deleteRule)),\n ...ifDefined('onUpdate', mapReferentialAction(fk.updateRule)),\n }),\n );\n\n // Process unique constraints (excluding those that are also PKs)\n const pkConstraints = pkConstraintsByTable.get(tableName) ?? new Set();\n const uniquesMap = new Map<string, { columns: string[]; name: string }>();\n for (const uniqueRow of uniquesByTable.get(tableName) ?? []) {\n // Skip if this constraint is also a primary key\n if (pkConstraints.has(uniqueRow.constraint_name)) {\n continue;\n }\n const existing = uniquesMap.get(uniqueRow.constraint_name);\n if (existing) {\n existing.columns.push(uniqueRow.column_name);\n } else {\n uniquesMap.set(uniqueRow.constraint_name, {\n columns: [uniqueRow.column_name],\n name: uniqueRow.constraint_name,\n });\n }\n }\n const uniques: readonly SqlUniqueIR[] = Array.from(uniquesMap.values()).map((uq) => ({\n columns: Object.freeze([...uq.columns]) as readonly string[],\n name: uq.name,\n }));\n\n // Process indexes\n const indexesMap = new Map<string, { columns: string[]; name: string; unique: boolean }>();\n for (const idxRow of indexesByTable.get(tableName) ?? []) {\n if (!idxRow.attname) {\n continue;\n }\n const existing = indexesMap.get(idxRow.indexname);\n if (existing) {\n existing.columns.push(idxRow.attname);\n } else {\n indexesMap.set(idxRow.indexname, {\n columns: [idxRow.attname],\n name: idxRow.indexname,\n unique: idxRow.indisunique,\n });\n }\n }\n const indexes: readonly SqlIndexIR[] = Array.from(indexesMap.values()).map((idx) => ({\n columns: Object.freeze([...idx.columns]) as readonly string[],\n name: idx.name,\n unique: idx.unique,\n }));\n\n tables[tableName] = {\n name: tableName,\n columns,\n ...ifDefined('primaryKey', primaryKey),\n foreignKeys,\n uniques,\n indexes,\n };\n }\n\n const dependencies: readonly DependencyIR[] = extensionsResult.rows.map((row) => ({\n id: `postgres.extension.${row.extname}`,\n }));\n\n const storageTypes =\n (await pgEnumControlHooks.introspectTypes?.({ driver, schemaName: schema })) ?? {};\n\n const annotations = {\n pg: {\n schema,\n version: await this.getPostgresVersion(driver),\n ...ifDefined(\n 'storageTypes',\n Object.keys(storageTypes).length > 0 ? storageTypes : undefined,\n ),\n },\n };\n\n return {\n tables,\n dependencies,\n annotations,\n };\n }\n\n /**\n * Gets the Postgres version from the database.\n */\n private async getPostgresVersion(\n driver: ControlDriverInstance<'sql', 'postgres'>,\n ): Promise<string> {\n const result = await driver.query<{ version: string }>('SELECT version() AS version', []);\n const versionString = result.rows[0]?.version ?? '';\n // Extract version number from \"PostgreSQL 15.1 ...\" format\n const match = versionString.match(/PostgreSQL (\\d+\\.\\d+)/);\n return match?.[1] ?? 'unknown';\n }\n}\n\nfunction normalizeFormattedType(formattedType: string, dataType: string, udtName: string): string {\n if (formattedType === 'integer') {\n return 'int4';\n }\n if (formattedType === 'smallint') {\n return 'int2';\n }\n if (formattedType === 'bigint') {\n return 'int8';\n }\n if (formattedType === 'real') {\n return 'float4';\n }\n if (formattedType === 'double precision') {\n return 'float8';\n }\n if (formattedType === 'boolean') {\n return 'bool';\n }\n if (formattedType.startsWith('varchar')) {\n return formattedType.replace('varchar', 'character varying');\n }\n if (formattedType.startsWith('bpchar')) {\n return formattedType.replace('bpchar', 'character');\n }\n if (formattedType.startsWith('varbit')) {\n return formattedType.replace('varbit', 'bit varying');\n }\n if (dataType === 'timestamp with time zone' || udtName === 'timestamptz') {\n return formattedType.replace('timestamp', 'timestamptz').replace(' with time zone', '').trim();\n }\n if (dataType === 'timestamp without time zone' || udtName === 'timestamp') {\n return formattedType.replace(' without time zone', '').trim();\n }\n if (dataType === 'time with time zone' || udtName === 'timetz') {\n return formattedType.replace('time', 'timetz').replace(' with time zone', '').trim();\n }\n if (dataType === 'time without time zone' || udtName === 'time') {\n return formattedType.replace(' without time zone', '').trim();\n }\n // Only dataType === 'USER-DEFINED' should ever be quoted, but this should be safe without\n // checking that explicitly either way\n if (formattedType.startsWith('\"') && formattedType.endsWith('\"')) {\n return formattedType.slice(1, -1);\n }\n return formattedType;\n}\n\n/**\n * The five standard PostgreSQL referential action rules as returned by\n * `information_schema.referential_constraints.delete_rule` / `update_rule`.\n */\ntype PgReferentialActionRule = 'NO ACTION' | 'RESTRICT' | 'CASCADE' | 'SET NULL' | 'SET DEFAULT';\n\nconst PG_REFERENTIAL_ACTION_MAP: Record<PgReferentialActionRule, SqlReferentialAction> = {\n 'NO ACTION': 'noAction',\n RESTRICT: 'restrict',\n CASCADE: 'cascade',\n 'SET NULL': 'setNull',\n 'SET DEFAULT': 'setDefault',\n};\n\n/**\n * Maps a Postgres referential action rule to the canonical SqlReferentialAction.\n * Returns undefined for 'NO ACTION' (the database default) to keep the IR sparse.\n * Throws for unrecognized rules to prevent silent data loss.\n */\nfunction mapReferentialAction(rule: string): SqlReferentialAction | undefined {\n const mapped = PG_REFERENTIAL_ACTION_MAP[rule as PgReferentialActionRule];\n if (mapped === undefined) {\n throw new Error(\n `Unknown PostgreSQL referential action rule: \"${rule}\". Expected one of: NO ACTION, RESTRICT, CASCADE, SET NULL, SET DEFAULT.`,\n );\n }\n if (mapped === 'noAction') return undefined;\n return mapped;\n}\n\n/**\n * Groups an array of objects by a specified key.\n * Returns a Map for O(1) lookup by group key.\n */\nfunction groupBy<T, K extends keyof T>(items: readonly T[], key: K): Map<T[K], T[]> {\n const map = new Map<T[K], T[]>();\n for (const item of items) {\n const groupKey = item[key];\n let group = map.get(groupKey);\n if (!group) {\n group = [];\n map.set(groupKey, group);\n }\n group.push(item);\n }\n return map;\n}\n","import type { ExecutionMutationDefaultValue } from '@prisma-next/contract/types';\nimport { timestampNowControlDescriptor } from '@prisma-next/family-sql/control';\nimport type {\n ControlMutationDefaultEntry,\n DefaultFunctionLoweringContext,\n LoweredDefaultResult,\n MutationDefaultGeneratorDescriptor,\n ParsedDefaultFunctionCall,\n} from '@prisma-next/framework-components/control';\nimport {\n builtinGeneratorRegistryMetadata,\n resolveBuiltinGeneratedColumnDescriptor,\n} from '@prisma-next/ids';\n\nfunction invalidArgumentDiagnostic(input: {\n readonly context: DefaultFunctionLoweringContext;\n readonly span: ParsedDefaultFunctionCall['span'];\n readonly message: string;\n}): LoweredDefaultResult {\n return {\n ok: false,\n diagnostic: {\n code: 'PSL_INVALID_DEFAULT_FUNCTION_ARGUMENT',\n message: input.message,\n sourceId: input.context.sourceId,\n span: input.span,\n },\n };\n}\n\nfunction executionGenerator(\n id: ExecutionMutationDefaultValue['id'],\n params?: Record<string, unknown>,\n): LoweredDefaultResult {\n return {\n ok: true,\n value: {\n kind: 'execution',\n generated: {\n kind: 'generator',\n id,\n ...(params ? { params } : {}),\n },\n },\n };\n}\n\nfunction expectNoArgs(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n readonly usage: string;\n}): LoweredDefaultResult | undefined {\n if (input.call.args.length === 0) {\n return undefined;\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message: `Default function \"${input.call.name}\" does not accept arguments. Use ${input.usage}.`,\n });\n}\n\nfunction parseIntegerArgument(raw: string): number | undefined {\n const trimmed = raw.trim();\n if (!/^-?\\d+$/.test(trimmed)) {\n return undefined;\n }\n const value = Number(trimmed);\n if (!Number.isInteger(value)) {\n return undefined;\n }\n return value;\n}\n\nfunction parseStringLiteral(raw: string): string | undefined {\n const match = raw.trim().match(/^(['\"])(.*)\\1$/s);\n if (!match) {\n return undefined;\n }\n return match[2] ?? '';\n}\n\nfunction lowerAutoincrement(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n const maybeNoArgs = expectNoArgs({\n call: input.call,\n context: input.context,\n usage: '`autoincrement()`',\n });\n if (maybeNoArgs) {\n return maybeNoArgs;\n }\n return {\n ok: true,\n value: {\n kind: 'storage',\n defaultValue: {\n kind: 'function',\n expression: 'autoincrement()',\n },\n },\n };\n}\n\nfunction lowerNow(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n const maybeNoArgs = expectNoArgs({\n call: input.call,\n context: input.context,\n usage: '`now()`',\n });\n if (maybeNoArgs) {\n return maybeNoArgs;\n }\n return {\n ok: true,\n value: {\n kind: 'storage',\n defaultValue: {\n kind: 'function',\n expression: 'now()',\n },\n },\n };\n}\n\nfunction lowerUuid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length === 0) {\n return executionGenerator('uuidv4');\n }\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message:\n 'Default function \"uuid\" accepts at most one version argument: `uuid()`, `uuid(4)`, or `uuid(7)`.',\n });\n }\n const version = parseIntegerArgument(input.call.args[0]?.raw ?? '');\n if (version === 4) {\n return executionGenerator('uuidv4');\n }\n if (version === 7) {\n return executionGenerator('uuidv7');\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message:\n 'Default function \"uuid\" supports only `uuid()`, `uuid(4)`, or `uuid(7)` in SQL PSL provider v1.',\n });\n}\n\nfunction lowerCuid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length === 0) {\n return {\n ok: false,\n diagnostic: {\n code: 'PSL_UNKNOWN_DEFAULT_FUNCTION',\n message:\n 'Default function \"cuid()\" is not supported in SQL PSL provider v1. Use `cuid(2)` instead.',\n sourceId: input.context.sourceId,\n span: input.call.span,\n },\n };\n }\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message: 'Default function \"cuid\" accepts exactly one version argument: `cuid(2)`.',\n });\n }\n const version = parseIntegerArgument(input.call.args[0]?.raw ?? '');\n if (version === 2) {\n return executionGenerator('cuid2');\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"cuid\" supports only `cuid(2)` in SQL PSL provider v1.',\n });\n}\n\nfunction lowerUlid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n const maybeNoArgs = expectNoArgs({\n call: input.call,\n context: input.context,\n usage: '`ulid()`',\n });\n if (maybeNoArgs) {\n return maybeNoArgs;\n }\n return executionGenerator('ulid');\n}\n\nfunction lowerNanoid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length === 0) {\n return executionGenerator('nanoid');\n }\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message:\n 'Default function \"nanoid\" accepts at most one size argument: `nanoid()` or `nanoid(<2-255>)`.',\n });\n }\n const size = parseIntegerArgument(input.call.args[0]?.raw ?? '');\n if (size !== undefined && size >= 2 && size <= 255) {\n return executionGenerator('nanoid', { size });\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"nanoid\" size argument must be an integer between 2 and 255.',\n });\n}\n\nfunction lowerDbgenerated(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message:\n 'Default function \"dbgenerated\" requires exactly one string argument: `dbgenerated(\"...\")`.',\n });\n }\n const rawExpression = parseStringLiteral(input.call.args[0]?.raw ?? '');\n if (rawExpression === undefined) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"dbgenerated\" argument must be a string literal.',\n });\n }\n if (rawExpression.trim().length === 0) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"dbgenerated\" argument cannot be empty.',\n });\n }\n return {\n ok: true,\n value: {\n kind: 'storage',\n defaultValue: {\n kind: 'function',\n expression: rawExpression,\n },\n },\n };\n}\n\nconst postgresDefaultFunctionRegistryEntries = [\n ['autoincrement', { lower: lowerAutoincrement, usageSignatures: ['autoincrement()'] }],\n ['now', { lower: lowerNow, usageSignatures: ['now()'] }],\n ['uuid', { lower: lowerUuid, usageSignatures: ['uuid()', 'uuid(4)', 'uuid(7)'] }],\n ['cuid', { lower: lowerCuid, usageSignatures: ['cuid(2)'] }],\n ['ulid', { lower: lowerUlid, usageSignatures: ['ulid()'] }],\n ['nanoid', { lower: lowerNanoid, usageSignatures: ['nanoid()', 'nanoid(<2-255>)'] }],\n ['dbgenerated', { lower: lowerDbgenerated, usageSignatures: ['dbgenerated(\"...\")'] }],\n] satisfies ReadonlyArray<readonly [string, ControlMutationDefaultEntry]>;\n\nconst postgresScalarTypeDescriptors = new Map<string, string>([\n ['String', 'pg/text@1'],\n ['Boolean', 'pg/bool@1'],\n ['Int', 'pg/int4@1'],\n ['BigInt', 'pg/int8@1'],\n ['Float', 'pg/float8@1'],\n ['Decimal', 'pg/numeric@1'],\n ['DateTime', 'pg/timestamptz@1'],\n ['Json', 'pg/jsonb@1'],\n ['Bytes', 'pg/bytea@1'],\n]);\n\nexport function createPostgresDefaultFunctionRegistry(): ReadonlyMap<\n string,\n ControlMutationDefaultEntry\n> {\n return new Map(postgresDefaultFunctionRegistryEntries);\n}\n\nexport function createPostgresMutationDefaultGeneratorDescriptors(): readonly MutationDefaultGeneratorDescriptor[] {\n return [\n ...builtinGeneratorRegistryMetadata.map(\n ({ id, applicableCodecIds }): MutationDefaultGeneratorDescriptor => ({\n id,\n applicableCodecIds,\n resolveGeneratedColumnDescriptor: ({ generated }) => {\n if (generated.kind !== 'generator' || generated.id !== id) {\n return undefined;\n }\n const descriptor = resolveBuiltinGeneratedColumnDescriptor({\n id,\n ...(generated.params ? { params: generated.params } : {}),\n });\n return {\n codecId: descriptor.type.codecId,\n nativeType: descriptor.type.nativeType,\n ...(descriptor.type.typeRef ? { typeRef: descriptor.type.typeRef } : {}),\n ...(descriptor.typeParams ? { typeParams: descriptor.typeParams } : {}),\n };\n },\n }),\n ),\n timestampNowControlDescriptor(),\n ];\n}\n\nexport function createPostgresScalarTypeDescriptors(): ReadonlyMap<string, string> {\n return new Map(postgresScalarTypeDescriptors);\n}\n","import type { SqlControlAdapterDescriptor } from '@prisma-next/family-sql/control';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport {\n escapeLiteral,\n qualifyName,\n quoteIdentifier,\n SqlEscapeError,\n} from '@prisma-next/target-postgres/sql-utils';\nimport { PostgresControlAdapter } from '../core/control-adapter';\nimport {\n createPostgresDefaultFunctionRegistry,\n createPostgresMutationDefaultGeneratorDescriptors,\n createPostgresScalarTypeDescriptors,\n} from '../core/control-mutation-defaults';\nimport { postgresAdapterDescriptorMeta } from '../core/descriptor-meta';\n\nconst postgresAdapterDescriptor: SqlControlAdapterDescriptor<'postgres'> = {\n ...postgresAdapterDescriptorMeta,\n scalarTypeDescriptors: createPostgresScalarTypeDescriptors(),\n controlMutationDefaults: {\n defaultFunctionRegistry: createPostgresDefaultFunctionRegistry(),\n generatorDescriptors: createPostgresMutationDefaultGeneratorDescriptors(),\n },\n create(stack): SqlControlAdapter<'postgres'> {\n return new PostgresControlAdapter(stack.codecLookup);\n },\n};\n\nexport default postgresAdapterDescriptor;\n\nexport { parsePostgresDefault } from '@prisma-next/target-postgres/default-normalizer';\nexport { normalizeSchemaNativeType } from '@prisma-next/target-postgres/native-type-normalizer';\nexport { escapeLiteral, qualifyName, quoteIdentifier, SqlEscapeError };\nexport { PostgresControlAdapter } from '../core/control-adapter';\n"],"mappings":"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"}
1
+ {"version":3,"file":"control.mjs","names":["parsePostgresDefault","normalizeSchemaNativeType"],"sources":["../src/core/control-adapter.ts","../src/core/control-mutation-defaults.ts","../src/exports/control.ts"],"sourcesContent":["import type { ContractMarkerRecord } from '@prisma-next/contract/types';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport { parseContractMarkerRow } from '@prisma-next/family-sql/verify';\nimport type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport type { ControlDriverInstance } from '@prisma-next/framework-components/control';\nimport type {\n AnyQueryAst,\n LoweredStatement,\n LowererContext,\n} from '@prisma-next/sql-relational-core/ast';\nimport type {\n DependencyIR,\n PrimaryKey,\n SqlColumnIR,\n SqlForeignKeyIR,\n SqlIndexIR,\n SqlReferentialAction,\n SqlSchemaIR,\n SqlTableIR,\n SqlUniqueIR,\n} from '@prisma-next/sql-schema-ir/types';\nimport { parsePostgresDefault } from '@prisma-next/target-postgres/default-normalizer';\nimport { normalizeSchemaNativeType } from '@prisma-next/target-postgres/native-type-normalizer';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { createPostgresBuiltinCodecLookup } from './codec-lookup';\nimport { pgEnumControlHooks } from './enum-control-hooks';\nimport { renderLoweredSql } from './sql-renderer';\nimport type { PostgresContract } from './types';\n\n/**\n * Postgres control plane adapter for control-plane operations like introspection.\n * Provides target-specific implementations for control-plane domain actions.\n */\nexport class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {\n readonly familyId = 'sql' as const;\n readonly targetId = 'postgres' as const;\n\n private readonly codecLookup: CodecLookup;\n\n /**\n * @param codecLookup - Codec lookup used by the SQL renderer to resolve\n * per-codec metadata at lower-time. Defaults to a Postgres-builtins-only\n * lookup when omitted. Stack-aware callers\n * (`SqlControlAdapterDescriptor.create(stack)`) supply\n * `stack.codecLookup` so extension codecs are visible to the renderer.\n */\n constructor(codecLookup?: CodecLookup) {\n this.codecLookup = codecLookup ?? createPostgresBuiltinCodecLookup();\n }\n\n /**\n * Target-specific normalizer for raw Postgres default expressions.\n * Used by schema verification to normalize raw defaults before comparison.\n */\n readonly normalizeDefault = parsePostgresDefault;\n\n /**\n * Target-specific normalizer for Postgres schema native type names.\n * Used by schema verification to normalize introspected type names\n * before comparison with contract native types.\n */\n readonly normalizeNativeType = normalizeSchemaNativeType;\n\n /**\n * Lower a SQL query AST into a Postgres-flavored `{ sql, params }` payload.\n *\n * Delegates to the shared `renderLoweredSql` renderer so the control adapter\n * emits byte-identical SQL to `PostgresAdapterImpl.lower()` for the same AST\n * and contract. Used at migration plan/emit time (e.g. by `dataTransform`)\n * without instantiating the runtime adapter.\n */\n lower(ast: AnyQueryAst, context: LowererContext<unknown>): LoweredStatement {\n return renderLoweredSql(ast, context.contract as PostgresContract, this.codecLookup);\n }\n\n /**\n * Reads the contract marker from `prisma_contract.marker`. Probes\n * `information_schema.tables` first so a fresh database (where the\n * `prisma_contract` schema doesn't yet exist) returns `null` instead of a\n * \"relation does not exist\" error — some Postgres wire-protocol clients\n * (e.g. PGlite's TCP proxy) don't fully recover from extended-protocol\n * parse errors, so we probe before reading.\n */\n async readMarker(\n driver: ControlDriverInstance<'sql', 'postgres'>,\n space: string,\n ): Promise<ContractMarkerRecord | null> {\n const exists = await driver.query(\n `select 1\n from information_schema.tables\n where table_schema = $1 and table_name = $2`,\n ['prisma_contract', 'marker'],\n );\n if (exists.rows.length === 0) {\n return null;\n }\n\n const result = await driver.query<{\n core_hash: string;\n profile_hash: string;\n contract_json: unknown | null;\n canonical_version: number | null;\n updated_at: Date | string;\n app_tag: string | null;\n meta: unknown | null;\n invariants: readonly string[];\n }>(\n `select\n core_hash,\n profile_hash,\n contract_json,\n canonical_version,\n updated_at,\n app_tag,\n meta,\n invariants\n from prisma_contract.marker\n where space = $1`,\n [space],\n );\n\n const row = result.rows[0];\n if (!row) return null;\n return parseContractMarkerRow(row);\n }\n\n /**\n * Reads every row from `prisma_contract.marker` and returns them keyed\n * by `space`. Mirrors the existence probe in {@link readMarker}: a\n * fresh database without the `prisma_contract` schema returns an empty\n * map rather than raising \"relation does not exist\".\n */\n async readAllMarkers(\n driver: ControlDriverInstance<'sql', 'postgres'>,\n ): Promise<ReadonlyMap<string, ContractMarkerRecord>> {\n const exists = await driver.query(\n `select 1\n from information_schema.tables\n where table_schema = $1 and table_name = $2`,\n ['prisma_contract', 'marker'],\n );\n if (exists.rows.length === 0) {\n return new Map();\n }\n\n const result = await driver.query<{\n space: string;\n core_hash: string;\n profile_hash: string;\n contract_json: unknown | null;\n canonical_version: number | null;\n updated_at: Date | string;\n app_tag: string | null;\n meta: unknown | null;\n invariants: readonly string[];\n }>(\n `select\n space,\n core_hash,\n profile_hash,\n contract_json,\n canonical_version,\n updated_at,\n app_tag,\n meta,\n invariants\n from prisma_contract.marker`,\n );\n\n const rows = new Map<string, ContractMarkerRecord>();\n for (const row of result.rows) {\n rows.set(row.space, parseContractMarkerRow(row));\n }\n return rows;\n }\n\n /**\n * Introspects a Postgres database schema and returns a raw SqlSchemaIR.\n *\n * This is a pure schema discovery operation that queries the Postgres catalog\n * and returns the schema structure without type mapping or contract enrichment.\n * Type mapping and enrichment are handled separately by enrichment helpers.\n *\n * Uses batched queries to minimize database round trips (7 queries instead of 5T+3).\n *\n * @param driver - ControlDriverInstance<'sql', 'postgres'> instance for executing queries\n * @param contract - Optional contract for contract-guided introspection (filtering, optimization)\n * @param schema - Schema name to introspect (defaults to 'public')\n * @returns Promise resolving to SqlSchemaIR representing the live database schema\n */\n async introspect(\n driver: ControlDriverInstance<'sql', 'postgres'>,\n _contract?: unknown,\n schema = 'public',\n ): Promise<SqlSchemaIR> {\n // Execute all queries in parallel for efficiency (7 queries instead of 5T+3)\n const [\n tablesResult,\n columnsResult,\n pkResult,\n fkResult,\n uniqueResult,\n indexResult,\n extensionsResult,\n ] = await Promise.all([\n // Query all tables\n driver.query<{ table_name: string }>(\n `SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = $1\n AND table_type = 'BASE TABLE'\n ORDER BY table_name`,\n [schema],\n ),\n // Query all columns for all tables in schema\n driver.query<{\n table_name: string;\n column_name: string;\n data_type: string;\n udt_name: string;\n is_nullable: string;\n character_maximum_length: number | null;\n numeric_precision: number | null;\n numeric_scale: number | null;\n column_default: string | null;\n formatted_type: string | null;\n }>(\n `SELECT\n c.table_name,\n column_name,\n data_type,\n udt_name,\n is_nullable,\n character_maximum_length,\n numeric_precision,\n numeric_scale,\n column_default,\n format_type(a.atttypid, a.atttypmod) AS formatted_type\n FROM information_schema.columns c\n JOIN pg_catalog.pg_class cl\n ON cl.relname = c.table_name\n JOIN pg_catalog.pg_namespace ns\n ON ns.nspname = c.table_schema\n AND ns.oid = cl.relnamespace\n JOIN pg_catalog.pg_attribute a\n ON a.attrelid = cl.oid\n AND a.attname = c.column_name\n AND a.attnum > 0\n AND NOT a.attisdropped\n WHERE c.table_schema = $1\n ORDER BY c.table_name, c.ordinal_position`,\n [schema],\n ),\n // Query all primary keys for all tables in schema\n driver.query<{\n table_name: string;\n constraint_name: string;\n column_name: string;\n ordinal_position: number;\n }>(\n `SELECT\n tc.table_name,\n tc.constraint_name,\n kcu.column_name,\n kcu.ordinal_position\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n AND tc.table_name = kcu.table_name\n WHERE tc.table_schema = $1\n AND tc.constraint_type = 'PRIMARY KEY'\n ORDER BY tc.table_name, kcu.ordinal_position`,\n [schema],\n ),\n // Query all foreign keys for all tables in schema, including referential actions.\n // Uses pg_catalog for correct positional pairing of composite FK columns\n // (information_schema.constraint_column_usage lacks ordinal_position,\n // which causes Cartesian products for multi-column FKs).\n driver.query<{\n table_name: string;\n constraint_name: string;\n column_name: string;\n ordinal_position: number;\n referenced_table_schema: string;\n referenced_table_name: string;\n referenced_column_name: string;\n delete_rule: string;\n update_rule: string;\n }>(\n `SELECT\n tc.table_name,\n tc.constraint_name,\n kcu.column_name,\n kcu.ordinal_position,\n ref_ns.nspname AS referenced_table_schema,\n ref_cl.relname AS referenced_table_name,\n ref_att.attname AS referenced_column_name,\n rc.delete_rule,\n rc.update_rule\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n AND tc.table_name = kcu.table_name\n JOIN pg_catalog.pg_constraint pgc\n ON pgc.conname = tc.constraint_name\n AND pgc.connamespace = (\n SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = tc.table_schema\n )\n JOIN pg_catalog.pg_class ref_cl\n ON ref_cl.oid = pgc.confrelid\n JOIN pg_catalog.pg_namespace ref_ns\n ON ref_ns.oid = ref_cl.relnamespace\n JOIN pg_catalog.pg_attribute ref_att\n ON ref_att.attrelid = pgc.confrelid\n AND ref_att.attnum = pgc.confkey[kcu.ordinal_position]\n JOIN information_schema.referential_constraints rc\n ON rc.constraint_name = tc.constraint_name\n AND rc.constraint_schema = tc.table_schema\n WHERE tc.table_schema = $1\n AND tc.constraint_type = 'FOREIGN KEY'\n ORDER BY tc.table_name, tc.constraint_name, kcu.ordinal_position`,\n [schema],\n ),\n // Query all unique constraints for all tables in schema (excluding PKs)\n driver.query<{\n table_name: string;\n constraint_name: string;\n column_name: string;\n ordinal_position: number;\n }>(\n `SELECT\n tc.table_name,\n tc.constraint_name,\n kcu.column_name,\n kcu.ordinal_position\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n AND tc.table_name = kcu.table_name\n WHERE tc.table_schema = $1\n AND tc.constraint_type = 'UNIQUE'\n ORDER BY tc.table_name, tc.constraint_name, kcu.ordinal_position`,\n [schema],\n ),\n // Query all indexes for all tables in schema (excluding constraints)\n driver.query<{\n tablename: string;\n indexname: string;\n indisunique: boolean;\n attname: string;\n attnum: number;\n amname: string;\n reloptions: readonly string[] | null;\n }>(\n `SELECT\n i.tablename,\n i.indexname,\n ix.indisunique,\n a.attname,\n a.attnum,\n am.amname,\n ic.reloptions\n FROM pg_indexes i\n JOIN pg_class ic ON ic.relname = i.indexname\n JOIN pg_namespace ins ON ins.oid = ic.relnamespace AND ins.nspname = $1\n JOIN pg_index ix ON ix.indexrelid = ic.oid\n JOIN pg_am am ON am.oid = ic.relam\n JOIN pg_class t ON t.oid = ix.indrelid\n JOIN pg_namespace tn ON tn.oid = t.relnamespace AND tn.nspname = $1\n LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey) AND a.attnum > 0\n WHERE i.schemaname = $1\n AND NOT EXISTS (\n SELECT 1\n FROM information_schema.table_constraints tc\n WHERE tc.table_schema = $1\n AND tc.table_name = i.tablename\n AND tc.constraint_name = i.indexname\n )\n ORDER BY i.tablename, i.indexname, a.attnum`,\n [schema],\n ),\n // Query extensions\n driver.query<{ extname: string }>(\n `SELECT extname\n FROM pg_extension\n ORDER BY extname`,\n [],\n ),\n ]);\n\n // Group results by table name for efficient lookup\n const columnsByTable = groupBy(columnsResult.rows, 'table_name');\n const pksByTable = groupBy(pkResult.rows, 'table_name');\n const fksByTable = groupBy(fkResult.rows, 'table_name');\n const uniquesByTable = groupBy(uniqueResult.rows, 'table_name');\n const indexesByTable = groupBy(indexResult.rows, 'tablename');\n\n // Get set of PK constraint names per table (to exclude from uniques)\n const pkConstraintsByTable = new Map<string, Set<string>>();\n for (const row of pkResult.rows) {\n let constraints = pkConstraintsByTable.get(row.table_name);\n if (!constraints) {\n constraints = new Set();\n pkConstraintsByTable.set(row.table_name, constraints);\n }\n constraints.add(row.constraint_name);\n }\n\n const tables: Record<string, SqlTableIR> = {};\n\n for (const tableRow of tablesResult.rows) {\n const tableName = tableRow.table_name;\n\n // Process columns for this table\n const columns: Record<string, SqlColumnIR> = {};\n for (const colRow of columnsByTable.get(tableName) ?? []) {\n let nativeType = colRow.udt_name;\n const formattedType = colRow.formatted_type\n ? normalizeFormattedType(colRow.formatted_type, colRow.data_type, colRow.udt_name)\n : null;\n if (formattedType) {\n nativeType = formattedType;\n } else if (colRow.data_type === 'character varying' || colRow.data_type === 'character') {\n if (colRow.character_maximum_length) {\n nativeType = `${colRow.data_type}(${colRow.character_maximum_length})`;\n } else {\n nativeType = colRow.data_type;\n }\n } else if (colRow.data_type === 'numeric' || colRow.data_type === 'decimal') {\n if (colRow.numeric_precision && colRow.numeric_scale !== null) {\n nativeType = `${colRow.data_type}(${colRow.numeric_precision},${colRow.numeric_scale})`;\n } else if (colRow.numeric_precision) {\n nativeType = `${colRow.data_type}(${colRow.numeric_precision})`;\n } else {\n nativeType = colRow.data_type;\n }\n } else {\n nativeType = colRow.udt_name || colRow.data_type;\n }\n\n columns[colRow.column_name] = {\n name: colRow.column_name,\n nativeType,\n nullable: colRow.is_nullable === 'YES',\n ...ifDefined('default', colRow.column_default ?? undefined),\n };\n }\n\n // Process primary key\n const pkRows = [...(pksByTable.get(tableName) ?? [])];\n const primaryKeyColumns = pkRows\n .sort((a, b) => a.ordinal_position - b.ordinal_position)\n .map((row) => row.column_name);\n const primaryKey: PrimaryKey | undefined =\n primaryKeyColumns.length > 0\n ? {\n columns: primaryKeyColumns,\n ...(pkRows[0]?.constraint_name ? { name: pkRows[0].constraint_name } : {}),\n }\n : undefined;\n\n // Process foreign keys\n const foreignKeysMap = new Map<\n string,\n {\n columns: string[];\n referencedTable: string;\n referencedColumns: string[];\n name: string;\n deleteRule: string;\n updateRule: string;\n }\n >();\n for (const fkRow of fksByTable.get(tableName) ?? []) {\n const existing = foreignKeysMap.get(fkRow.constraint_name);\n if (existing) {\n existing.columns.push(fkRow.column_name);\n existing.referencedColumns.push(fkRow.referenced_column_name);\n } else {\n foreignKeysMap.set(fkRow.constraint_name, {\n columns: [fkRow.column_name],\n referencedTable: fkRow.referenced_table_name,\n referencedColumns: [fkRow.referenced_column_name],\n name: fkRow.constraint_name,\n deleteRule: fkRow.delete_rule,\n updateRule: fkRow.update_rule,\n });\n }\n }\n const foreignKeys: readonly SqlForeignKeyIR[] = Array.from(foreignKeysMap.values()).map(\n (fk) => ({\n columns: Object.freeze([...fk.columns]) as readonly string[],\n referencedTable: fk.referencedTable,\n referencedColumns: Object.freeze([...fk.referencedColumns]) as readonly string[],\n name: fk.name,\n ...ifDefined('onDelete', mapReferentialAction(fk.deleteRule)),\n ...ifDefined('onUpdate', mapReferentialAction(fk.updateRule)),\n }),\n );\n\n // Process unique constraints (excluding those that are also PKs)\n const pkConstraints = pkConstraintsByTable.get(tableName) ?? new Set();\n const uniquesMap = new Map<string, { columns: string[]; name: string }>();\n for (const uniqueRow of uniquesByTable.get(tableName) ?? []) {\n // Skip if this constraint is also a primary key\n if (pkConstraints.has(uniqueRow.constraint_name)) {\n continue;\n }\n const existing = uniquesMap.get(uniqueRow.constraint_name);\n if (existing) {\n existing.columns.push(uniqueRow.column_name);\n } else {\n uniquesMap.set(uniqueRow.constraint_name, {\n columns: [uniqueRow.column_name],\n name: uniqueRow.constraint_name,\n });\n }\n }\n const uniques: readonly SqlUniqueIR[] = Array.from(uniquesMap.values()).map((uq) => ({\n columns: Object.freeze([...uq.columns]) as readonly string[],\n name: uq.name,\n }));\n\n // Process indexes\n const indexesMap = new Map<\n string,\n {\n columns: string[];\n name: string;\n unique: boolean;\n type: string | undefined;\n options: Record<string, string> | undefined;\n }\n >();\n for (const idxRow of indexesByTable.get(tableName) ?? []) {\n if (!idxRow.attname) {\n continue;\n }\n const existing = indexesMap.get(idxRow.indexname);\n if (existing) {\n existing.columns.push(idxRow.attname);\n } else {\n // Drop btree (the Postgres default) so a contract index without an\n // explicit type matches a default-method introspected index without\n // forcing DROP+CREATE on every plan.\n const indexType = idxRow.amname === 'btree' ? undefined : idxRow.amname;\n const indexOptions = parsePgReloptions(idxRow.reloptions, idxRow.indexname);\n indexesMap.set(idxRow.indexname, {\n columns: [idxRow.attname],\n name: idxRow.indexname,\n unique: idxRow.indisunique,\n type: indexType,\n options: indexOptions,\n });\n }\n }\n const indexes: readonly SqlIndexIR[] = Array.from(indexesMap.values()).map((idx) => ({\n columns: Object.freeze([...idx.columns]) as readonly string[],\n name: idx.name,\n unique: idx.unique,\n ...(idx.type !== undefined && { type: idx.type }),\n ...(idx.options !== undefined && { options: idx.options }),\n }));\n\n tables[tableName] = {\n name: tableName,\n columns,\n ...ifDefined('primaryKey', primaryKey),\n foreignKeys,\n uniques,\n indexes,\n };\n }\n\n const dependencies: readonly DependencyIR[] = extensionsResult.rows.map((row) => ({\n id: `postgres.extension.${row.extname}`,\n }));\n\n const storageTypes =\n (await pgEnumControlHooks.introspectTypes?.({ driver, schemaName: schema })) ?? {};\n\n const annotations = {\n pg: {\n schema,\n version: await this.getPostgresVersion(driver),\n ...ifDefined(\n 'storageTypes',\n Object.keys(storageTypes).length > 0 ? storageTypes : undefined,\n ),\n },\n };\n\n return {\n tables,\n dependencies,\n annotations,\n };\n }\n\n /**\n * Gets the Postgres version from the database.\n */\n private async getPostgresVersion(\n driver: ControlDriverInstance<'sql', 'postgres'>,\n ): Promise<string> {\n const result = await driver.query<{ version: string }>('SELECT version() AS version', []);\n const versionString = result.rows[0]?.version ?? '';\n // Extract version number from \"PostgreSQL 15.1 ...\" format\n const match = versionString.match(/PostgreSQL (\\d+\\.\\d+)/);\n return match?.[1] ?? 'unknown';\n }\n}\n\nfunction normalizeFormattedType(formattedType: string, dataType: string, udtName: string): string {\n if (formattedType === 'integer') {\n return 'int4';\n }\n if (formattedType === 'smallint') {\n return 'int2';\n }\n if (formattedType === 'bigint') {\n return 'int8';\n }\n if (formattedType === 'real') {\n return 'float4';\n }\n if (formattedType === 'double precision') {\n return 'float8';\n }\n if (formattedType === 'boolean') {\n return 'bool';\n }\n if (formattedType.startsWith('varchar')) {\n return formattedType.replace('varchar', 'character varying');\n }\n if (formattedType.startsWith('bpchar')) {\n return formattedType.replace('bpchar', 'character');\n }\n if (formattedType.startsWith('varbit')) {\n return formattedType.replace('varbit', 'bit varying');\n }\n if (dataType === 'timestamp with time zone' || udtName === 'timestamptz') {\n return formattedType.replace('timestamp', 'timestamptz').replace(' with time zone', '').trim();\n }\n if (dataType === 'timestamp without time zone' || udtName === 'timestamp') {\n return formattedType.replace(' without time zone', '').trim();\n }\n if (dataType === 'time with time zone' || udtName === 'timetz') {\n return formattedType.replace('time', 'timetz').replace(' with time zone', '').trim();\n }\n if (dataType === 'time without time zone' || udtName === 'time') {\n return formattedType.replace(' without time zone', '').trim();\n }\n // Only dataType === 'USER-DEFINED' should ever be quoted, but this should be safe without\n // checking that explicitly either way\n if (formattedType.startsWith('\"') && formattedType.endsWith('\"')) {\n return formattedType.slice(1, -1);\n }\n return formattedType;\n}\n\n/**\n * The five standard PostgreSQL referential action rules as returned by\n * `information_schema.referential_constraints.delete_rule` / `update_rule`.\n */\ntype PgReferentialActionRule = 'NO ACTION' | 'RESTRICT' | 'CASCADE' | 'SET NULL' | 'SET DEFAULT';\n\nconst PG_REFERENTIAL_ACTION_MAP: Record<PgReferentialActionRule, SqlReferentialAction> = {\n 'NO ACTION': 'noAction',\n RESTRICT: 'restrict',\n CASCADE: 'cascade',\n 'SET NULL': 'setNull',\n 'SET DEFAULT': 'setDefault',\n};\n\n/**\n * Maps a Postgres referential action rule to the canonical SqlReferentialAction.\n * Returns undefined for 'NO ACTION' (the database default) to keep the IR sparse.\n * Throws for unrecognized rules to prevent silent data loss.\n */\nfunction mapReferentialAction(rule: string): SqlReferentialAction | undefined {\n const mapped = PG_REFERENTIAL_ACTION_MAP[rule as PgReferentialActionRule];\n if (mapped === undefined) {\n throw new Error(\n `Unknown PostgreSQL referential action rule: \"${rule}\". Expected one of: NO ACTION, RESTRICT, CASCADE, SET NULL, SET DEFAULT.`,\n );\n }\n if (mapped === 'noAction') return undefined;\n return mapped;\n}\n\n/**\n * Groups an array of objects by a specified key.\n * Returns a Map for O(1) lookup by group key.\n */\n/**\n * Parses a `pg_class.reloptions` array into a `Record<string, string>`.\n *\n * Postgres returns reloptions as a `text[]` whose entries are `key=value`\n * strings; the value side is always a string regardless of the underlying\n * scalar type. The verifier compares contract options to introspected\n * options after coercing both sides to strings, so keeping the raw text\n * here is correct.\n *\n * Returns `undefined` when the input is null/empty (no WITH clause).\n */\nexport function parsePgReloptions(\n reloptions: readonly string[] | null,\n indexName: string,\n): Record<string, string> | undefined {\n if (!reloptions || reloptions.length === 0) {\n return undefined;\n }\n const result: Record<string, string> = {};\n for (const entry of reloptions) {\n const eq = entry.indexOf('=');\n if (eq === -1) {\n throw new Error(\n `Postgres introspection: malformed reloption entry \"${entry}\" on index \"${indexName}\" (expected \"key=value\")`,\n );\n }\n const key = entry.slice(0, eq);\n const value = entry.slice(eq + 1);\n result[key] = value;\n }\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\nfunction groupBy<T, K extends keyof T>(items: readonly T[], key: K): Map<T[K], T[]> {\n const map = new Map<T[K], T[]>();\n for (const item of items) {\n const groupKey = item[key];\n let group = map.get(groupKey);\n if (!group) {\n group = [];\n map.set(groupKey, group);\n }\n group.push(item);\n }\n return map;\n}\n","import type { ExecutionMutationDefaultValue } from '@prisma-next/contract/types';\nimport { timestampNowControlDescriptor } from '@prisma-next/family-sql/control';\nimport type {\n ControlMutationDefaultEntry,\n DefaultFunctionLoweringContext,\n LoweredDefaultResult,\n MutationDefaultGeneratorDescriptor,\n ParsedDefaultFunctionCall,\n} from '@prisma-next/framework-components/control';\nimport {\n builtinGeneratorRegistryMetadata,\n resolveBuiltinGeneratedColumnDescriptor,\n} from '@prisma-next/ids';\n\nfunction invalidArgumentDiagnostic(input: {\n readonly context: DefaultFunctionLoweringContext;\n readonly span: ParsedDefaultFunctionCall['span'];\n readonly message: string;\n}): LoweredDefaultResult {\n return {\n ok: false,\n diagnostic: {\n code: 'PSL_INVALID_DEFAULT_FUNCTION_ARGUMENT',\n message: input.message,\n sourceId: input.context.sourceId,\n span: input.span,\n },\n };\n}\n\nfunction executionGenerator(\n id: ExecutionMutationDefaultValue['id'],\n params?: Record<string, unknown>,\n): LoweredDefaultResult {\n return {\n ok: true,\n value: {\n kind: 'execution',\n generated: {\n kind: 'generator',\n id,\n ...(params ? { params } : {}),\n },\n },\n };\n}\n\nfunction expectNoArgs(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n readonly usage: string;\n}): LoweredDefaultResult | undefined {\n if (input.call.args.length === 0) {\n return undefined;\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message: `Default function \"${input.call.name}\" does not accept arguments. Use ${input.usage}.`,\n });\n}\n\nfunction parseIntegerArgument(raw: string): number | undefined {\n const trimmed = raw.trim();\n if (!/^-?\\d+$/.test(trimmed)) {\n return undefined;\n }\n const value = Number(trimmed);\n if (!Number.isInteger(value)) {\n return undefined;\n }\n return value;\n}\n\nfunction parseStringLiteral(raw: string): string | undefined {\n const match = raw.trim().match(/^(['\"])(.*)\\1$/s);\n if (!match) {\n return undefined;\n }\n return match[2] ?? '';\n}\n\nfunction lowerAutoincrement(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n const maybeNoArgs = expectNoArgs({\n call: input.call,\n context: input.context,\n usage: '`autoincrement()`',\n });\n if (maybeNoArgs) {\n return maybeNoArgs;\n }\n return {\n ok: true,\n value: {\n kind: 'storage',\n defaultValue: {\n kind: 'function',\n expression: 'autoincrement()',\n },\n },\n };\n}\n\nfunction lowerNow(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n const maybeNoArgs = expectNoArgs({\n call: input.call,\n context: input.context,\n usage: '`now()`',\n });\n if (maybeNoArgs) {\n return maybeNoArgs;\n }\n return {\n ok: true,\n value: {\n kind: 'storage',\n defaultValue: {\n kind: 'function',\n expression: 'now()',\n },\n },\n };\n}\n\nfunction lowerUuid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length === 0) {\n return executionGenerator('uuidv4');\n }\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message:\n 'Default function \"uuid\" accepts at most one version argument: `uuid()`, `uuid(4)`, or `uuid(7)`.',\n });\n }\n const version = parseIntegerArgument(input.call.args[0]?.raw ?? '');\n if (version === 4) {\n return executionGenerator('uuidv4');\n }\n if (version === 7) {\n return executionGenerator('uuidv7');\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message:\n 'Default function \"uuid\" supports only `uuid()`, `uuid(4)`, or `uuid(7)` in SQL PSL provider v1.',\n });\n}\n\nfunction lowerCuid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length === 0) {\n return {\n ok: false,\n diagnostic: {\n code: 'PSL_UNKNOWN_DEFAULT_FUNCTION',\n message:\n 'Default function \"cuid()\" is not supported in SQL PSL provider v1. Use `cuid(2)` instead.',\n sourceId: input.context.sourceId,\n span: input.call.span,\n },\n };\n }\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message: 'Default function \"cuid\" accepts exactly one version argument: `cuid(2)`.',\n });\n }\n const version = parseIntegerArgument(input.call.args[0]?.raw ?? '');\n if (version === 2) {\n return executionGenerator('cuid2');\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"cuid\" supports only `cuid(2)` in SQL PSL provider v1.',\n });\n}\n\nfunction lowerUlid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n const maybeNoArgs = expectNoArgs({\n call: input.call,\n context: input.context,\n usage: '`ulid()`',\n });\n if (maybeNoArgs) {\n return maybeNoArgs;\n }\n return executionGenerator('ulid');\n}\n\nfunction lowerNanoid(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length === 0) {\n return executionGenerator('nanoid');\n }\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message:\n 'Default function \"nanoid\" accepts at most one size argument: `nanoid()` or `nanoid(<2-255>)`.',\n });\n }\n const size = parseIntegerArgument(input.call.args[0]?.raw ?? '');\n if (size !== undefined && size >= 2 && size <= 255) {\n return executionGenerator('nanoid', { size });\n }\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"nanoid\" size argument must be an integer between 2 and 255.',\n });\n}\n\nfunction lowerDbgenerated(input: {\n readonly call: ParsedDefaultFunctionCall;\n readonly context: DefaultFunctionLoweringContext;\n}): LoweredDefaultResult {\n if (input.call.args.length !== 1) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.span,\n message:\n 'Default function \"dbgenerated\" requires exactly one string argument: `dbgenerated(\"...\")`.',\n });\n }\n const rawExpression = parseStringLiteral(input.call.args[0]?.raw ?? '');\n if (rawExpression === undefined) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"dbgenerated\" argument must be a string literal.',\n });\n }\n if (rawExpression.trim().length === 0) {\n return invalidArgumentDiagnostic({\n context: input.context,\n span: input.call.args[0]?.span ?? input.call.span,\n message: 'Default function \"dbgenerated\" argument cannot be empty.',\n });\n }\n return {\n ok: true,\n value: {\n kind: 'storage',\n defaultValue: {\n kind: 'function',\n expression: rawExpression,\n },\n },\n };\n}\n\nconst postgresDefaultFunctionRegistryEntries = [\n ['autoincrement', { lower: lowerAutoincrement, usageSignatures: ['autoincrement()'] }],\n ['now', { lower: lowerNow, usageSignatures: ['now()'] }],\n ['uuid', { lower: lowerUuid, usageSignatures: ['uuid()', 'uuid(4)', 'uuid(7)'] }],\n ['cuid', { lower: lowerCuid, usageSignatures: ['cuid(2)'] }],\n ['ulid', { lower: lowerUlid, usageSignatures: ['ulid()'] }],\n ['nanoid', { lower: lowerNanoid, usageSignatures: ['nanoid()', 'nanoid(<2-255>)'] }],\n ['dbgenerated', { lower: lowerDbgenerated, usageSignatures: ['dbgenerated(\"...\")'] }],\n] satisfies ReadonlyArray<readonly [string, ControlMutationDefaultEntry]>;\n\nconst postgresScalarTypeDescriptors = new Map<string, string>([\n ['String', 'pg/text@1'],\n ['Boolean', 'pg/bool@1'],\n ['Int', 'pg/int4@1'],\n ['BigInt', 'pg/int8@1'],\n ['Float', 'pg/float8@1'],\n ['Decimal', 'pg/numeric@1'],\n ['DateTime', 'pg/timestamptz@1'],\n ['Json', 'pg/jsonb@1'],\n ['Bytes', 'pg/bytea@1'],\n]);\n\nexport function createPostgresDefaultFunctionRegistry(): ReadonlyMap<\n string,\n ControlMutationDefaultEntry\n> {\n return new Map(postgresDefaultFunctionRegistryEntries);\n}\n\nexport function createPostgresMutationDefaultGeneratorDescriptors(): readonly MutationDefaultGeneratorDescriptor[] {\n return [\n ...builtinGeneratorRegistryMetadata.map(\n ({ id, applicableCodecIds }): MutationDefaultGeneratorDescriptor => ({\n id,\n applicableCodecIds,\n resolveGeneratedColumnDescriptor: ({ generated }) => {\n if (generated.kind !== 'generator' || generated.id !== id) {\n return undefined;\n }\n const descriptor = resolveBuiltinGeneratedColumnDescriptor({\n id,\n ...(generated.params ? { params: generated.params } : {}),\n });\n return {\n codecId: descriptor.type.codecId,\n nativeType: descriptor.type.nativeType,\n ...(descriptor.type.typeRef ? { typeRef: descriptor.type.typeRef } : {}),\n ...(descriptor.typeParams ? { typeParams: descriptor.typeParams } : {}),\n };\n },\n }),\n ),\n timestampNowControlDescriptor(),\n ];\n}\n\nexport function createPostgresScalarTypeDescriptors(): ReadonlyMap<string, string> {\n return new Map(postgresScalarTypeDescriptors);\n}\n","import type { SqlControlAdapterDescriptor } from '@prisma-next/family-sql/control';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport {\n escapeLiteral,\n qualifyName,\n quoteIdentifier,\n SqlEscapeError,\n} from '@prisma-next/target-postgres/sql-utils';\nimport { PostgresControlAdapter } from '../core/control-adapter';\nimport {\n createPostgresDefaultFunctionRegistry,\n createPostgresMutationDefaultGeneratorDescriptors,\n createPostgresScalarTypeDescriptors,\n} from '../core/control-mutation-defaults';\nimport { postgresAdapterDescriptorMeta } from '../core/descriptor-meta';\n\nconst postgresAdapterDescriptor: SqlControlAdapterDescriptor<'postgres'> = {\n ...postgresAdapterDescriptorMeta,\n scalarTypeDescriptors: createPostgresScalarTypeDescriptors(),\n controlMutationDefaults: {\n defaultFunctionRegistry: createPostgresDefaultFunctionRegistry(),\n generatorDescriptors: createPostgresMutationDefaultGeneratorDescriptors(),\n },\n create(stack): SqlControlAdapter<'postgres'> {\n return new PostgresControlAdapter(stack.codecLookup);\n },\n};\n\nexport default postgresAdapterDescriptor;\n\nexport { parsePostgresDefault } from '@prisma-next/target-postgres/default-normalizer';\nexport { normalizeSchemaNativeType } from '@prisma-next/target-postgres/native-type-normalizer';\nexport { escapeLiteral, qualifyName, quoteIdentifier, SqlEscapeError };\nexport { PostgresControlAdapter } from '../core/control-adapter';\n"],"mappings":"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"}
@@ -532,8 +532,7 @@ const precisionHooks = { expandNativeType: expandPrecision };
532
532
  const numericHooks = { expandNativeType: expandNumeric };
533
533
  const identityHooks = { expandNativeType: ({ nativeType }) => nativeType };
534
534
  function postgresQueryOperations() {
535
- return [{
536
- method: "ilike",
535
+ return { ilike: {
537
536
  self: { traits: ["textual"] },
538
537
  impl: (self, pattern) => {
539
538
  const selfRefs = refsOf(self);
@@ -551,7 +550,7 @@ function postgresQueryOperations() {
551
550
  }
552
551
  });
553
552
  }
554
- }];
553
+ } };
555
554
  }
556
555
  const postgresAdapterDescriptorMeta = {
557
556
  kind: "adapter",
@@ -798,4 +797,4 @@ const postgresAdapterDescriptorMeta = {
798
797
  //#endregion
799
798
  export { postgresQueryOperations as n, pgEnumControlHooks as r, postgresAdapterDescriptorMeta as t };
800
799
 
801
- //# sourceMappingURL=descriptor-meta-C2VasIft.mjs.map
800
+ //# sourceMappingURL=descriptor-meta-CyjnYUWG.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"descriptor-meta-C2VasIft.mjs","names":[],"sources":["../src/core/enum-control-hooks.ts","../src/core/descriptor-meta.ts"],"sourcesContent":["import type { Contract } from '@prisma-next/contract/types';\nimport type { CodecControlHooks, SqlMigrationPlanOperation } from '@prisma-next/family-sql/control';\nimport { arraysEqual } from '@prisma-next/family-sql/schema-verify';\nimport type { SqlStorage, StorageTypeInstance } from '@prisma-next/sql-contract/types';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { PG_ENUM_CODEC_ID } from '@prisma-next/target-postgres/codec-ids';\nimport {\n escapeLiteral,\n qualifyName,\n quoteIdentifier,\n validateEnumValueLength,\n} from '@prisma-next/target-postgres/sql-utils';\n\n/**\n * Postgres enum control hooks.\n *\n * - Plans enum type operations for migrations\n * - Verifies enum types in schema IR\n * - Introspects enum types from the database\n */\ntype EnumRow = {\n schema_name: string;\n type_name: string;\n values: string[];\n};\n\ntype EnumDiff =\n | { kind: 'unchanged' }\n | { kind: 'add_values'; values: readonly string[] }\n | { kind: 'rebuild'; removedValues: readonly string[] };\n\n// ============================================================================\n// Introspection SQL\n// ============================================================================\n\nconst ENUM_INTROSPECT_QUERY = `\n SELECT\n n.nspname AS schema_name,\n t.typname AS type_name,\n array_agg(e.enumlabel ORDER BY e.enumsortorder) AS values\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n JOIN pg_enum e ON t.oid = e.enumtypid\n WHERE n.nspname = $1\n GROUP BY n.nspname, t.typname\n ORDER BY n.nspname, t.typname\n`;\n\n// ============================================================================\n// Schema Helpers (Simplified)\n// ============================================================================\n\n/**\n * Type guard for string arrays. Used for runtime validation of introspected data.\n */\nfunction isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((entry) => typeof entry === 'string');\n}\n\n/**\n * Parses a PostgreSQL array value into a JavaScript string array.\n *\n * PostgreSQL's `pg` library may return `array_agg` results either as:\n * - A JavaScript array (when type parsers are configured)\n * - A string in PostgreSQL array literal format: `{value1,value2,...}`\n *\n * Handles PostgreSQL's quoting rules for array elements:\n * - Elements containing commas, double quotes, backslashes, or whitespace are double-quoted\n * - Inside quoted elements, `\\\"` represents `\"` and `\\\\` represents `\\`\n *\n * @param value - The value to parse (array or PostgreSQL array string)\n * @returns A string array, or null if the value cannot be parsed\n */\nexport function parsePostgresArray(value: unknown): string[] | null {\n if (isStringArray(value)) {\n return value;\n }\n if (typeof value === 'string' && value.startsWith('{') && value.endsWith('}')) {\n const inner = value.slice(1, -1);\n if (inner === '') {\n return [];\n }\n return parseArrayElements(inner);\n }\n return null;\n}\n\nfunction parseArrayElements(input: string): string[] {\n const result: string[] = [];\n let i = 0;\n while (i < input.length) {\n if (input[i] === ',') {\n i++;\n continue;\n }\n if (input[i] === '\"') {\n i++;\n let element = '';\n while (i < input.length && input[i] !== '\"') {\n if (input[i] === '\\\\' && i + 1 < input.length) {\n i++;\n element += input[i];\n } else {\n element += input[i];\n }\n i++;\n }\n i++;\n result.push(element);\n } else {\n const nextComma = input.indexOf(',', i);\n if (nextComma === -1) {\n result.push(input.slice(i).trim());\n i = input.length;\n } else {\n result.push(input.slice(i, nextComma).trim());\n i = nextComma;\n }\n }\n }\n return result;\n}\n\n/**\n * Extracts enum values from a StorageTypeInstance.\n * Returns null if values are missing or invalid.\n */\nfunction getEnumValues(typeInstance: StorageTypeInstance): readonly string[] | null {\n const values = typeInstance.typeParams?.['values'];\n return isStringArray(values) ? values : null;\n}\n\n/**\n * Reads existing enum values from the schema IR for a given native type.\n * Uses optional chaining to simplify navigation through the annotations structure.\n */\nfunction readExistingEnumValues(schema: SqlSchemaIR, nativeType: string): readonly string[] | null {\n const storageTypes = (schema.annotations?.['pg'] as Record<string, unknown> | undefined)?.[\n 'storageTypes'\n ] as Record<string, StorageTypeInstance> | undefined;\n\n const existing = storageTypes?.[nativeType];\n if (!existing || existing.codecId !== PG_ENUM_CODEC_ID) {\n return null;\n }\n return getEnumValues(existing);\n}\n\n/**\n * Determines what changes are needed to transform existing enum values to desired values.\n *\n * Returns one of:\n * - `unchanged`: No changes needed, values match exactly\n * - `add_values`: New values can be safely appended (PostgreSQL supports this)\n * - `rebuild`: Full enum rebuild required (value removal, reordering, or both)\n *\n * Note: PostgreSQL enums can only have values added (not removed or reordered) without\n * a full type rebuild involving temp type creation and column migration.\n *\n * @param existing - Current enum values in the database\n * @param desired - Target enum values from the contract\n * @returns The type of change required\n */\nfunction determineEnumDiff(existing: readonly string[], desired: readonly string[]): EnumDiff {\n if (arraysEqual(existing, desired)) {\n return { kind: 'unchanged' };\n }\n\n // Use Sets for O(1) lookups instead of O(n) array.includes()\n const existingSet = new Set(existing);\n const desiredSet = new Set(desired);\n\n const missingValues = desired.filter((value) => !existingSet.has(value));\n const removedValues = existing.filter((value) => !desiredSet.has(value));\n const orderMismatch =\n missingValues.length === 0 && removedValues.length === 0 && !arraysEqual(existing, desired);\n\n if (removedValues.length > 0 || orderMismatch) {\n return { kind: 'rebuild', removedValues };\n }\n\n return { kind: 'add_values', values: missingValues };\n}\n\n// ============================================================================\n// SQL Helpers\n// ============================================================================\n\nfunction enumTypeExistsCheck(schemaName: string, typeName: string, exists = true): string {\n const existsClause = exists ? 'EXISTS' : 'NOT EXISTS';\n return `SELECT ${existsClause} (\n SELECT 1\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n WHERE n.nspname = '${escapeLiteral(schemaName)}'\n AND t.typname = '${escapeLiteral(typeName)}'\n)`;\n}\n\n// ============================================================================\n// Operation Builders\n// ============================================================================\n\nfunction buildCreateEnumOperation(\n typeName: string,\n nativeType: string,\n schemaName: string,\n values: readonly string[],\n): SqlMigrationPlanOperation<unknown> {\n // Validate all enum values don't exceed PostgreSQL's label length limit\n for (const value of values) {\n validateEnumValueLength(value, typeName);\n }\n const literalValues = values.map((value) => `'${escapeLiteral(value)}'`).join(', ');\n const qualifiedType = qualifyName(schemaName, nativeType);\n return {\n id: `type.${typeName}`,\n label: `Create type ${typeName}`,\n summary: `Creates enum type ${typeName}`,\n operationClass: 'additive',\n target: { id: 'postgres' },\n precheck: [\n {\n description: `ensure type \"${nativeType}\" does not exist`,\n sql: enumTypeExistsCheck(schemaName, nativeType, false),\n },\n ],\n execute: [\n {\n description: `create type \"${nativeType}\"`,\n sql: `CREATE TYPE ${qualifiedType} AS ENUM (${literalValues})`,\n },\n ],\n postcheck: [\n {\n description: `verify type \"${nativeType}\" exists`,\n sql: enumTypeExistsCheck(schemaName, nativeType),\n },\n ],\n };\n}\n\n/**\n * Computes the optimal position for inserting a new enum value to maintain\n * the desired order relative to existing values.\n *\n * PostgreSQL's `ALTER TYPE ADD VALUE` supports BEFORE/AFTER positioning.\n * This function finds the best reference value by:\n * 1. Looking for the nearest preceding value that already exists\n * 2. Falling back to the nearest following value if no preceding exists\n * 3. Defaulting to end-of-list if no reference is found\n *\n * @param options.desired - The target ordered list of all enum values\n * @param options.desiredIndex - Index of the value being inserted in the desired list\n * @param options.current - Current list of enum values (being built up incrementally)\n * @returns SQL clause (e.g., \" AFTER 'x'\") and insert position for tracking\n */\nfunction computeInsertPosition(options: {\n desired: readonly string[];\n desiredIndex: number;\n current: readonly string[];\n}): { clause: string; insertAt: number } {\n const { desired, desiredIndex, current } = options;\n const currentSet = new Set(current);\n const previous = desired\n .slice(0, desiredIndex)\n .reverse()\n .find((candidate) => currentSet.has(candidate));\n const next = desired.slice(desiredIndex + 1).find((candidate) => currentSet.has(candidate));\n const clause = previous\n ? ` AFTER '${escapeLiteral(previous)}'`\n : next\n ? ` BEFORE '${escapeLiteral(next)}'`\n : '';\n const insertAt = previous\n ? current.indexOf(previous) + 1\n : next\n ? current.indexOf(next)\n : current.length;\n\n return { clause, insertAt };\n}\n\n/**\n * Builds operations to add new enum values to an existing PostgreSQL enum type.\n *\n * Each new value is added with `ALTER TYPE ... ADD VALUE IF NOT EXISTS` for idempotency.\n * Values are inserted in the correct order using BEFORE/AFTER positioning to match\n * the desired final order.\n *\n * This is a safe, non-destructive operation - existing data is not affected.\n *\n * @param options.typeName - Contract-level type name (e.g., 'Role')\n * @param options.nativeType - PostgreSQL type name (e.g., 'role')\n * @param options.schemaName - PostgreSQL schema (e.g., 'public')\n * @param options.desired - Target ordered list of all enum values\n * @param options.existing - Current enum values in the database\n * @returns Array of migration operations to add each missing value\n */\nfunction buildAddValueOperations(options: {\n typeName: string;\n nativeType: string;\n schemaName: string;\n desired: readonly string[];\n existing: readonly string[];\n}): SqlMigrationPlanOperation<unknown>[] {\n const { typeName, nativeType, schemaName } = options;\n const current = [...options.existing];\n const currentSet = new Set(current);\n const operations: SqlMigrationPlanOperation<unknown>[] = [];\n for (let index = 0; index < options.desired.length; index += 1) {\n const value = options.desired[index];\n if (value === undefined) {\n continue;\n }\n if (currentSet.has(value)) {\n continue;\n }\n // Validate the new value doesn't exceed PostgreSQL's label length limit\n validateEnumValueLength(value, typeName);\n const { clause, insertAt } = computeInsertPosition({\n desired: options.desired,\n desiredIndex: index,\n current,\n });\n // Use IF NOT EXISTS for idempotency - safe to re-run after partial failures.\n // Supported in PostgreSQL 9.3+, and we require PostgreSQL 12+.\n operations.push({\n id: `type.${typeName}.value.${value}`,\n label: `Add value ${value} to ${typeName}`,\n summary: `Adds enum value ${value} to ${typeName}`,\n operationClass: 'widening',\n target: { id: 'postgres' },\n precheck: [],\n execute: [\n {\n description: `add value \"${value}\" if not exists`,\n sql: `ALTER TYPE ${qualifyName(schemaName, nativeType)} ADD VALUE IF NOT EXISTS '${escapeLiteral(\n value,\n )}'${clause}`,\n },\n ],\n postcheck: [],\n });\n current.splice(insertAt, 0, value);\n currentSet.add(value);\n }\n return operations;\n}\n\n/**\n * Collects columns using the enum type from the contract (desired state).\n * Used for type-safe reference tracking.\n */\nfunction collectEnumColumnsFromContract(\n contract: Contract<SqlStorage>,\n typeName: string,\n nativeType: string,\n): ReadonlyArray<{ table: string; column: string }> {\n const columns: Array<{ table: string; column: string }> = [];\n for (const [tableName, table] of Object.entries(contract.storage.tables)) {\n for (const [columnName, column] of Object.entries(table.columns)) {\n if (\n column.typeRef === typeName ||\n (column.nativeType === nativeType && column.codecId === PG_ENUM_CODEC_ID)\n ) {\n columns.push({ table: tableName, column: columnName });\n }\n }\n }\n return columns;\n}\n\n/**\n * Collects columns using the enum type from the schema IR (live database state).\n * This ensures we find ALL dependent columns, including those added outside the contract\n * (e.g., manual DDL), which is critical for safe enum rebuild operations.\n */\nfunction collectEnumColumnsFromSchema(\n schema: SqlSchemaIR,\n nativeType: string,\n): ReadonlyArray<{ table: string; column: string }> {\n const columns: Array<{ table: string; column: string }> = [];\n for (const [tableName, table] of Object.entries(schema.tables)) {\n for (const [columnName, column] of Object.entries(table.columns)) {\n // Match by nativeType since schema IR doesn't have codecId/typeRef\n if (column.nativeType === nativeType) {\n columns.push({ table: tableName, column: columnName });\n }\n }\n }\n return columns;\n}\n\n/**\n * Collects all columns using the enum type from both contract AND live database.\n * Merges and deduplicates to ensure we migrate ALL dependent columns during rebuild.\n *\n * This is critical for data integrity: if a column exists in the database using\n * this enum but is not in the contract (e.g., added via manual DDL), we must\n * still migrate it to avoid DROP TYPE failures.\n */\nfunction collectAllEnumColumns(\n contract: Contract<SqlStorage>,\n schema: SqlSchemaIR,\n typeName: string,\n nativeType: string,\n): ReadonlyArray<{ table: string; column: string }> {\n const contractColumns = collectEnumColumnsFromContract(contract, typeName, nativeType);\n const schemaColumns = collectEnumColumnsFromSchema(schema, nativeType);\n\n // Merge and deduplicate using a Set of \"table.column\" keys\n const seen = new Set<string>();\n const result: Array<{ table: string; column: string }> = [];\n\n for (const col of [...contractColumns, ...schemaColumns]) {\n const key = `${col.table}.${col.column}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(col);\n }\n }\n\n // Sort for deterministic operation order\n return result.sort((a, b) => {\n const tableCompare = a.table.localeCompare(b.table);\n return tableCompare !== 0 ? tableCompare : a.column.localeCompare(b.column);\n });\n}\n\n/**\n * Builds a SQL check to verify a column's type matches an expected type.\n */\nfunction columnTypeCheck(options: {\n schemaName: string;\n tableName: string;\n columnName: string;\n expectedType: string;\n}): string {\n return `SELECT EXISTS (\n SELECT 1\n FROM information_schema.columns\n WHERE table_schema = '${escapeLiteral(options.schemaName)}'\n AND table_name = '${escapeLiteral(options.tableName)}'\n AND column_name = '${escapeLiteral(options.columnName)}'\n AND udt_name = '${escapeLiteral(options.expectedType)}'\n)`;\n}\n\n/** PostgreSQL maximum identifier length (NAMEDATALEN - 1) */\nconst MAX_IDENTIFIER_LENGTH = 63;\n\n/** Suffix added to enum type names during rebuild operations */\nconst REBUILD_SUFFIX = '__pn_rebuild';\n\n/**\n * Builds an SQL check to verify no rows contain any of the removed enum values.\n * This prevents data loss during enum rebuild operations.\n *\n * @param schemaName - PostgreSQL schema name\n * @param tableName - Table containing the enum column\n * @param columnName - Column using the enum type\n * @param removedValues - Array of enum values being removed\n * @returns SQL query that returns true if no rows contain removed values\n */\nfunction noRemovedValuesExistCheck(\n schemaName: string,\n tableName: string,\n columnName: string,\n removedValues: readonly string[],\n): string {\n if (removedValues.length === 0) {\n // No values being removed, always passes\n return 'SELECT true';\n }\n const valuesList = removedValues.map((v) => `'${escapeLiteral(v)}'`).join(', ');\n return `SELECT NOT EXISTS (\n SELECT 1 FROM ${qualifyName(schemaName, tableName)}\n WHERE ${quoteIdentifier(columnName)}::text IN (${valuesList})\n LIMIT 1\n)`;\n}\n\n/**\n * Builds a migration operation to recreate a PostgreSQL enum type with updated values.\n *\n * This is required when:\n * - Enum values are removed (PostgreSQL doesn't support direct removal)\n * - Enum values are reordered (PostgreSQL doesn't support reordering)\n *\n * The operation:\n * 1. Creates a new enum type with the desired values (temp name)\n * 2. Migrates all columns to use the new type via text cast\n * 3. Drops the original type\n * 4. Renames the temp type to the original name\n *\n * IMPORTANT: If values are being removed and data exists using those values,\n * the operation will fail at the precheck stage with a clear error message.\n * This prevents silent data loss.\n *\n * @param options.typeName - Contract-level type name\n * @param options.nativeType - PostgreSQL type name\n * @param options.schemaName - PostgreSQL schema\n * @param options.values - Desired final enum values\n * @param options.removedValues - Values being removed (for data loss checks)\n * @param options.contract - Full contract for column discovery\n * @param options.schema - Current schema IR for column discovery\n * @returns Migration operation for full enum rebuild\n */\nfunction buildRecreateEnumOperation(options: {\n typeName: string;\n nativeType: string;\n schemaName: string;\n values: readonly string[];\n removedValues: readonly string[];\n contract: Contract<SqlStorage>;\n schema: SqlSchemaIR;\n}): SqlMigrationPlanOperation<unknown> {\n const tempTypeName = `${options.nativeType}${REBUILD_SUFFIX}`;\n\n // Validate temp type name length won't exceed PostgreSQL's 63-character limit.\n // If it would, PostgreSQL silently truncates which could cause conflicts.\n if (tempTypeName.length > MAX_IDENTIFIER_LENGTH) {\n const maxBaseLength = MAX_IDENTIFIER_LENGTH - REBUILD_SUFFIX.length;\n throw new Error(\n `Enum type name \"${options.nativeType}\" is too long for rebuild operation. ` +\n `Maximum length is ${maxBaseLength} characters (type name + \"${REBUILD_SUFFIX}\" suffix ` +\n `must fit within PostgreSQL's ${MAX_IDENTIFIER_LENGTH}-character identifier limit).`,\n );\n }\n\n const qualifiedOriginal = qualifyName(options.schemaName, options.nativeType);\n const qualifiedTemp = qualifyName(options.schemaName, tempTypeName);\n const literalValues = options.values.map((value) => `'${escapeLiteral(value)}'`).join(', ');\n\n // CRITICAL: Collect columns from BOTH contract AND live database.\n // This ensures we migrate ALL dependent columns, including those added\n // outside of Prisma Next (e.g., manual DDL). Without this, DROP TYPE\n // would fail if the database has columns not tracked in the contract.\n const columnRefs = collectAllEnumColumns(\n options.contract,\n options.schema,\n options.typeName,\n options.nativeType,\n );\n\n const alterColumns = columnRefs.map((ref) => ({\n description: `alter ${ref.table}.${ref.column} to ${tempTypeName}`,\n sql: `ALTER TABLE ${qualifyName(options.schemaName, ref.table)}\nALTER COLUMN ${quoteIdentifier(ref.column)}\nTYPE ${qualifiedTemp}\nUSING ${quoteIdentifier(ref.column)}::text::${qualifiedTemp}`,\n }));\n\n // Build postchecks to verify:\n // 1. The final type exists with the correct name\n // 2. The temp type was cleaned up (renamed away)\n // 3. All migrated columns now reference the final type\n const postchecks = [\n {\n description: `verify type \"${options.nativeType}\" exists`,\n sql: enumTypeExistsCheck(options.schemaName, options.nativeType),\n },\n {\n description: `verify temp type \"${tempTypeName}\" was removed`,\n sql: enumTypeExistsCheck(options.schemaName, tempTypeName, false),\n },\n // Verify each column was successfully migrated to the final type\n ...columnRefs.map((ref) => ({\n description: `verify ${ref.table}.${ref.column} uses type \"${options.nativeType}\"`,\n sql: columnTypeCheck({\n schemaName: options.schemaName,\n tableName: ref.table,\n columnName: ref.column,\n expectedType: options.nativeType,\n }),\n })),\n ];\n\n return {\n id: `type.${options.typeName}.rebuild`,\n label: `Rebuild type ${options.typeName}`,\n summary: `Recreates enum type ${options.typeName} with updated values`,\n operationClass: 'destructive',\n target: { id: 'postgres' },\n precheck: [\n {\n description: `ensure type \"${options.nativeType}\" exists`,\n sql: enumTypeExistsCheck(options.schemaName, options.nativeType),\n },\n // Note: We don't precheck that temp type doesn't exist because we handle\n // orphaned temp types in the execute step below.\n\n // CRITICAL: If values are being removed, verify no data exists using those values.\n // This prevents silent data loss during the rebuild - the USING cast would fail\n // at runtime if rows contain values that don't exist in the new enum.\n ...(options.removedValues.length > 0\n ? columnRefs.map((ref) => ({\n description: `ensure no rows in ${ref.table}.${ref.column} contain removed values (${options.removedValues.join(', ')})`,\n sql: noRemovedValuesExistCheck(\n options.schemaName,\n ref.table,\n ref.column,\n options.removedValues,\n ),\n }))\n : []),\n ],\n execute: [\n // Clean up any orphaned temp type from a previous failed migration.\n // This makes the operation recoverable without manual intervention.\n // DROP TYPE IF EXISTS is safe - it's a no-op if the type doesn't exist.\n {\n description: `drop orphaned temp type \"${tempTypeName}\" if exists`,\n sql: `DROP TYPE IF EXISTS ${qualifiedTemp}`,\n },\n {\n description: `create temp type \"${tempTypeName}\"`,\n sql: `CREATE TYPE ${qualifiedTemp} AS ENUM (${literalValues})`,\n },\n ...alterColumns,\n {\n description: `drop type \"${options.nativeType}\"`,\n sql: `DROP TYPE ${qualifiedOriginal}`,\n },\n {\n description: `rename type \"${tempTypeName}\" to \"${options.nativeType}\"`,\n sql: `ALTER TYPE ${qualifiedTemp} RENAME TO ${quoteIdentifier(options.nativeType)}`,\n },\n ],\n postcheck: postchecks,\n };\n}\n\n// ============================================================================\n// Codec Control Hooks\n// ============================================================================\n\n/**\n * Postgres enum hooks for planning, verifying, and introspecting `storage.types`.\n */\nexport const pgEnumControlHooks: CodecControlHooks = {\n planTypeOperations: ({ typeName, typeInstance, contract, schema, schemaName }) => {\n const desired = getEnumValues(typeInstance);\n if (!desired || desired.length === 0) {\n return { operations: [] };\n }\n\n const schemaNamespace = schemaName ?? 'public';\n const existing = readExistingEnumValues(schema, typeInstance.nativeType);\n if (!existing) {\n return {\n operations: [\n buildCreateEnumOperation(typeName, typeInstance.nativeType, schemaNamespace, desired),\n ],\n };\n }\n\n const diff = determineEnumDiff(existing, desired);\n if (diff.kind === 'unchanged') {\n return { operations: [] };\n }\n\n if (diff.kind === 'rebuild') {\n return {\n operations: [\n buildRecreateEnumOperation({\n typeName,\n nativeType: typeInstance.nativeType,\n schemaName: schemaNamespace,\n values: desired,\n removedValues: diff.removedValues,\n contract,\n schema,\n }),\n ],\n };\n }\n\n return {\n operations: buildAddValueOperations({\n typeName,\n nativeType: typeInstance.nativeType,\n schemaName: schemaNamespace,\n desired,\n existing,\n }),\n };\n },\n verifyType: ({ typeName, typeInstance, schema }) => {\n const desired = getEnumValues(typeInstance);\n if (!desired) {\n return [];\n }\n const existing = readExistingEnumValues(schema, typeInstance.nativeType);\n if (!existing) {\n return [\n {\n kind: 'type_missing',\n typeName,\n message: `Type \"${typeName}\" is missing from database`,\n },\n ];\n }\n const diff = determineEnumDiff(existing, desired);\n if (diff.kind === 'unchanged') return [];\n const existingSet = new Set(existing);\n const desiredSet = new Set(desired);\n const addedValues = desired.filter((v) => !existingSet.has(v));\n const removedValues = existing.filter((v) => !desiredSet.has(v));\n return [\n {\n kind: 'enum_values_changed' as const,\n typeName,\n addedValues,\n removedValues,\n message:\n diff.kind === 'add_values'\n ? `Enum type \"${typeName}\" needs new values: ${addedValues.join(', ')}`\n : `Enum type \"${typeName}\" values changed (requires rebuild): +[${addedValues.join(', ')}] -[${removedValues.join(', ')}]`,\n },\n ];\n },\n introspectTypes: async ({ driver, schemaName }) => {\n const namespace = schemaName ?? 'public';\n const result = await driver.query<EnumRow>(ENUM_INTROSPECT_QUERY, [namespace]);\n const types: Record<string, StorageTypeInstance> = {};\n for (const row of result.rows) {\n const values = parsePostgresArray(row.values);\n if (!values) {\n throw new Error(\n `Failed to parse enum values for type \"${row.type_name}\": ` +\n `unexpected format: ${JSON.stringify(row.values)}`,\n );\n }\n types[row.type_name] = {\n codecId: PG_ENUM_CODEC_ID,\n nativeType: row.type_name,\n typeParams: { values },\n };\n }\n return types;\n },\n};\n","import type { CodecControlHooks, ExpandNativeTypeInput } from '@prisma-next/family-sql/control';\nimport type { SqlOperationDescriptor } from '@prisma-next/sql-operations';\nimport {\n buildOperation,\n type CodecExpression,\n type Expression,\n refsOf,\n type TraitExpression,\n toExpr,\n} from '@prisma-next/sql-relational-core/expression';\nimport {\n PG_BIT_CODEC_ID,\n PG_BOOL_CODEC_ID,\n PG_BYTEA_CODEC_ID,\n PG_CHAR_CODEC_ID,\n PG_ENUM_CODEC_ID,\n PG_FLOAT_CODEC_ID,\n PG_FLOAT4_CODEC_ID,\n PG_FLOAT8_CODEC_ID,\n PG_INT_CODEC_ID,\n PG_INT2_CODEC_ID,\n PG_INT4_CODEC_ID,\n PG_INT8_CODEC_ID,\n PG_INTERVAL_CODEC_ID,\n PG_JSON_CODEC_ID,\n PG_JSONB_CODEC_ID,\n PG_NUMERIC_CODEC_ID,\n PG_TEXT_CODEC_ID,\n PG_TIME_CODEC_ID,\n PG_TIMESTAMP_CODEC_ID,\n PG_TIMESTAMPTZ_CODEC_ID,\n PG_TIMETZ_CODEC_ID,\n PG_VARBIT_CODEC_ID,\n PG_VARCHAR_CODEC_ID,\n SQL_CHAR_CODEC_ID,\n SQL_FLOAT_CODEC_ID,\n SQL_INT_CODEC_ID,\n SQL_TEXT_CODEC_ID,\n SQL_TIMESTAMP_CODEC_ID,\n SQL_VARCHAR_CODEC_ID,\n} from '@prisma-next/target-postgres/codec-ids';\nimport { postgresCodecRegistry } from '@prisma-next/target-postgres/codecs';\nimport { pgEnumControlHooks } from './enum-control-hooks';\n\n// ============================================================================ Helper functions for reducing boilerplate ============================================================================\n\n/** Creates a type import spec for codec types */\nconst codecTypeImport = (named: string) =>\n ({\n package: '@prisma-next/target-postgres/codec-types',\n named,\n alias: named,\n }) as const;\n\nfunction isPositiveInteger(value: unknown): value is number {\n return (\n typeof value === 'number' && Number.isFinite(value) && Number.isInteger(value) && value > 0\n );\n}\n\nfunction isNonNegativeInteger(value: unknown): value is number {\n return (\n typeof value === 'number' && Number.isFinite(value) && Number.isInteger(value) && value >= 0\n );\n}\n\nfunction expandLength({ nativeType, typeParams }: ExpandNativeTypeInput): string {\n if (!typeParams || !('length' in typeParams)) {\n return nativeType;\n }\n const length = typeParams['length'];\n if (!isPositiveInteger(length)) {\n throw new Error(\n `Invalid \"length\" type parameter for \"${nativeType}\": expected a positive integer, got ${JSON.stringify(length)}`,\n );\n }\n return `${nativeType}(${length})`;\n}\n\nfunction expandPrecision({ nativeType, typeParams }: ExpandNativeTypeInput): string {\n if (!typeParams || !('precision' in typeParams)) {\n return nativeType;\n }\n const precision = typeParams['precision'];\n if (!isPositiveInteger(precision)) {\n throw new Error(\n `Invalid \"precision\" type parameter for \"${nativeType}\": expected a positive integer, got ${JSON.stringify(precision)}`,\n );\n }\n return `${nativeType}(${precision})`;\n}\n\nfunction expandNumeric({ nativeType, typeParams }: ExpandNativeTypeInput): string {\n const hasPrecision = typeParams && 'precision' in typeParams;\n const hasScale = typeParams && 'scale' in typeParams;\n\n if (!hasPrecision && !hasScale) {\n return nativeType;\n }\n\n if (!hasPrecision && hasScale) {\n throw new Error(\n `Invalid type parameters for \"${nativeType}\": \"scale\" requires \"precision\" to be specified`,\n );\n }\n\n if (hasPrecision) {\n const precision = typeParams['precision'];\n if (!isPositiveInteger(precision)) {\n throw new Error(\n `Invalid \"precision\" type parameter for \"${nativeType}\": expected a positive integer, got ${JSON.stringify(precision)}`,\n );\n }\n if (hasScale) {\n const scale = typeParams['scale'];\n if (!isNonNegativeInteger(scale)) {\n throw new Error(\n `Invalid \"scale\" type parameter for \"${nativeType}\": expected a non-negative integer, got ${JSON.stringify(scale)}`,\n );\n }\n return `${nativeType}(${precision},${scale})`;\n }\n return `${nativeType}(${precision})`;\n }\n\n return nativeType;\n}\n\nconst lengthHooks: CodecControlHooks = { expandNativeType: expandLength };\nconst precisionHooks: CodecControlHooks = { expandNativeType: expandPrecision };\nconst numericHooks: CodecControlHooks = { expandNativeType: expandNumeric };\nconst identityHooks: CodecControlHooks = { expandNativeType: ({ nativeType }) => nativeType };\n\n// ============================================================================ Descriptor metadata ============================================================================\n\ntype CodecTypesBase = Record<string, { readonly input: unknown; readonly output: unknown }>;\n\nexport function postgresQueryOperations<\n CT extends CodecTypesBase,\n>(): readonly SqlOperationDescriptor[] {\n return [\n {\n method: 'ilike',\n self: { traits: ['textual'] },\n impl: (\n self: TraitExpression<readonly ['textual'], false, CT>,\n pattern: CodecExpression<'pg/text@1', false, CT>,\n ): Expression<{ codecId: 'pg/bool@1'; nullable: false }> => {\n const selfRefs = refsOf(self);\n return buildOperation({\n method: 'ilike',\n args: [toExpr(self), toExpr(pattern, PG_TEXT_CODEC_ID, selfRefs)],\n returns: { codecId: PG_BOOL_CODEC_ID, nullable: false },\n lowering: { targetFamily: 'sql', strategy: 'infix', template: '{{self}} ILIKE {{arg0}}' },\n });\n },\n },\n ];\n}\n\nexport const postgresAdapterDescriptorMeta = {\n kind: 'adapter',\n familyId: 'sql',\n targetId: 'postgres',\n id: 'postgres',\n version: '0.0.1',\n capabilities: {\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 types: {\n codecTypes: {\n codecDescriptors: Array.from(postgresCodecRegistry.values()),\n import: {\n package: '@prisma-next/target-postgres/codec-types',\n named: 'CodecTypes',\n alias: 'PgTypes',\n },\n typeImports: [\n {\n package: '@prisma-next/target-postgres/codec-types',\n named: 'JsonValue',\n alias: 'JsonValue',\n },\n codecTypeImport('Char'),\n codecTypeImport('Varchar'),\n codecTypeImport('Numeric'),\n codecTypeImport('Bit'),\n codecTypeImport('VarBit'),\n codecTypeImport('Timestamp'),\n codecTypeImport('Timestamptz'),\n codecTypeImport('Time'),\n codecTypeImport('Timetz'),\n codecTypeImport('Interval'),\n ],\n controlPlaneHooks: {\n [SQL_CHAR_CODEC_ID]: lengthHooks,\n [SQL_VARCHAR_CODEC_ID]: lengthHooks,\n [SQL_TIMESTAMP_CODEC_ID]: precisionHooks,\n [PG_CHAR_CODEC_ID]: lengthHooks,\n [PG_VARCHAR_CODEC_ID]: lengthHooks,\n [PG_NUMERIC_CODEC_ID]: numericHooks,\n [PG_BIT_CODEC_ID]: lengthHooks,\n [PG_VARBIT_CODEC_ID]: lengthHooks,\n [PG_TIMESTAMP_CODEC_ID]: precisionHooks,\n [PG_TIMESTAMPTZ_CODEC_ID]: precisionHooks,\n [PG_TIME_CODEC_ID]: precisionHooks,\n [PG_TIMETZ_CODEC_ID]: precisionHooks,\n [PG_INTERVAL_CODEC_ID]: precisionHooks,\n [PG_ENUM_CODEC_ID]: pgEnumControlHooks,\n [PG_JSON_CODEC_ID]: identityHooks,\n [PG_JSONB_CODEC_ID]: identityHooks,\n [PG_BYTEA_CODEC_ID]: identityHooks,\n },\n },\n storage: [\n { typeId: PG_TEXT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'text' },\n { typeId: SQL_TEXT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'text' },\n { typeId: SQL_CHAR_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'character' },\n {\n typeId: SQL_VARCHAR_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'character varying',\n },\n { typeId: SQL_INT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int4' },\n { typeId: SQL_FLOAT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'float8' },\n {\n typeId: SQL_TIMESTAMP_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'timestamp',\n },\n { typeId: PG_CHAR_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'character' },\n {\n typeId: PG_VARCHAR_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'character varying',\n },\n { typeId: PG_INT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int4' },\n { typeId: PG_FLOAT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'float8' },\n { typeId: PG_INT4_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int4' },\n { typeId: PG_INT2_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int2' },\n { typeId: PG_INT8_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int8' },\n { typeId: PG_FLOAT4_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'float4' },\n { typeId: PG_FLOAT8_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'float8' },\n { typeId: PG_NUMERIC_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'numeric' },\n {\n typeId: PG_TIMESTAMP_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'timestamp',\n },\n {\n typeId: PG_TIMESTAMPTZ_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'timestamptz',\n },\n { typeId: PG_TIME_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'time' },\n { typeId: PG_TIMETZ_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'timetz' },\n { typeId: PG_BOOL_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'bool' },\n { typeId: PG_BIT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'bit' },\n {\n typeId: PG_VARBIT_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'bit varying',\n },\n {\n typeId: PG_INTERVAL_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'interval',\n },\n { typeId: PG_JSON_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'json' },\n { typeId: PG_JSONB_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'jsonb' },\n { typeId: PG_BYTEA_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'bytea' },\n ],\n queryOperationTypes: {\n import: {\n package: '@prisma-next/adapter-postgres/operation-types',\n named: 'QueryOperationTypes',\n alias: 'PgAdapterQueryOps',\n },\n },\n },\n} as const;\n"],"mappings":"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"}
1
+ {"version":3,"file":"descriptor-meta-CyjnYUWG.mjs","names":[],"sources":["../src/core/enum-control-hooks.ts","../src/core/descriptor-meta.ts"],"sourcesContent":["import type { Contract } from '@prisma-next/contract/types';\nimport type { CodecControlHooks, SqlMigrationPlanOperation } from '@prisma-next/family-sql/control';\nimport { arraysEqual } from '@prisma-next/family-sql/schema-verify';\nimport type { SqlStorage, StorageTypeInstance } from '@prisma-next/sql-contract/types';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { PG_ENUM_CODEC_ID } from '@prisma-next/target-postgres/codec-ids';\nimport {\n escapeLiteral,\n qualifyName,\n quoteIdentifier,\n validateEnumValueLength,\n} from '@prisma-next/target-postgres/sql-utils';\n\n/**\n * Postgres enum control hooks.\n *\n * - Plans enum type operations for migrations\n * - Verifies enum types in schema IR\n * - Introspects enum types from the database\n */\ntype EnumRow = {\n schema_name: string;\n type_name: string;\n values: string[];\n};\n\ntype EnumDiff =\n | { kind: 'unchanged' }\n | { kind: 'add_values'; values: readonly string[] }\n | { kind: 'rebuild'; removedValues: readonly string[] };\n\n// ============================================================================\n// Introspection SQL\n// ============================================================================\n\nconst ENUM_INTROSPECT_QUERY = `\n SELECT\n n.nspname AS schema_name,\n t.typname AS type_name,\n array_agg(e.enumlabel ORDER BY e.enumsortorder) AS values\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n JOIN pg_enum e ON t.oid = e.enumtypid\n WHERE n.nspname = $1\n GROUP BY n.nspname, t.typname\n ORDER BY n.nspname, t.typname\n`;\n\n// ============================================================================\n// Schema Helpers (Simplified)\n// ============================================================================\n\n/**\n * Type guard for string arrays. Used for runtime validation of introspected data.\n */\nfunction isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((entry) => typeof entry === 'string');\n}\n\n/**\n * Parses a PostgreSQL array value into a JavaScript string array.\n *\n * PostgreSQL's `pg` library may return `array_agg` results either as:\n * - A JavaScript array (when type parsers are configured)\n * - A string in PostgreSQL array literal format: `{value1,value2,...}`\n *\n * Handles PostgreSQL's quoting rules for array elements:\n * - Elements containing commas, double quotes, backslashes, or whitespace are double-quoted\n * - Inside quoted elements, `\\\"` represents `\"` and `\\\\` represents `\\`\n *\n * @param value - The value to parse (array or PostgreSQL array string)\n * @returns A string array, or null if the value cannot be parsed\n */\nexport function parsePostgresArray(value: unknown): string[] | null {\n if (isStringArray(value)) {\n return value;\n }\n if (typeof value === 'string' && value.startsWith('{') && value.endsWith('}')) {\n const inner = value.slice(1, -1);\n if (inner === '') {\n return [];\n }\n return parseArrayElements(inner);\n }\n return null;\n}\n\nfunction parseArrayElements(input: string): string[] {\n const result: string[] = [];\n let i = 0;\n while (i < input.length) {\n if (input[i] === ',') {\n i++;\n continue;\n }\n if (input[i] === '\"') {\n i++;\n let element = '';\n while (i < input.length && input[i] !== '\"') {\n if (input[i] === '\\\\' && i + 1 < input.length) {\n i++;\n element += input[i];\n } else {\n element += input[i];\n }\n i++;\n }\n i++;\n result.push(element);\n } else {\n const nextComma = input.indexOf(',', i);\n if (nextComma === -1) {\n result.push(input.slice(i).trim());\n i = input.length;\n } else {\n result.push(input.slice(i, nextComma).trim());\n i = nextComma;\n }\n }\n }\n return result;\n}\n\n/**\n * Extracts enum values from a StorageTypeInstance.\n * Returns null if values are missing or invalid.\n */\nfunction getEnumValues(typeInstance: StorageTypeInstance): readonly string[] | null {\n const values = typeInstance.typeParams?.['values'];\n return isStringArray(values) ? values : null;\n}\n\n/**\n * Reads existing enum values from the schema IR for a given native type.\n * Uses optional chaining to simplify navigation through the annotations structure.\n */\nfunction readExistingEnumValues(schema: SqlSchemaIR, nativeType: string): readonly string[] | null {\n const storageTypes = (schema.annotations?.['pg'] as Record<string, unknown> | undefined)?.[\n 'storageTypes'\n ] as Record<string, StorageTypeInstance> | undefined;\n\n const existing = storageTypes?.[nativeType];\n if (!existing || existing.codecId !== PG_ENUM_CODEC_ID) {\n return null;\n }\n return getEnumValues(existing);\n}\n\n/**\n * Determines what changes are needed to transform existing enum values to desired values.\n *\n * Returns one of:\n * - `unchanged`: No changes needed, values match exactly\n * - `add_values`: New values can be safely appended (PostgreSQL supports this)\n * - `rebuild`: Full enum rebuild required (value removal, reordering, or both)\n *\n * Note: PostgreSQL enums can only have values added (not removed or reordered) without\n * a full type rebuild involving temp type creation and column migration.\n *\n * @param existing - Current enum values in the database\n * @param desired - Target enum values from the contract\n * @returns The type of change required\n */\nfunction determineEnumDiff(existing: readonly string[], desired: readonly string[]): EnumDiff {\n if (arraysEqual(existing, desired)) {\n return { kind: 'unchanged' };\n }\n\n // Use Sets for O(1) lookups instead of O(n) array.includes()\n const existingSet = new Set(existing);\n const desiredSet = new Set(desired);\n\n const missingValues = desired.filter((value) => !existingSet.has(value));\n const removedValues = existing.filter((value) => !desiredSet.has(value));\n const orderMismatch =\n missingValues.length === 0 && removedValues.length === 0 && !arraysEqual(existing, desired);\n\n if (removedValues.length > 0 || orderMismatch) {\n return { kind: 'rebuild', removedValues };\n }\n\n return { kind: 'add_values', values: missingValues };\n}\n\n// ============================================================================\n// SQL Helpers\n// ============================================================================\n\nfunction enumTypeExistsCheck(schemaName: string, typeName: string, exists = true): string {\n const existsClause = exists ? 'EXISTS' : 'NOT EXISTS';\n return `SELECT ${existsClause} (\n SELECT 1\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n WHERE n.nspname = '${escapeLiteral(schemaName)}'\n AND t.typname = '${escapeLiteral(typeName)}'\n)`;\n}\n\n// ============================================================================\n// Operation Builders\n// ============================================================================\n\nfunction buildCreateEnumOperation(\n typeName: string,\n nativeType: string,\n schemaName: string,\n values: readonly string[],\n): SqlMigrationPlanOperation<unknown> {\n // Validate all enum values don't exceed PostgreSQL's label length limit\n for (const value of values) {\n validateEnumValueLength(value, typeName);\n }\n const literalValues = values.map((value) => `'${escapeLiteral(value)}'`).join(', ');\n const qualifiedType = qualifyName(schemaName, nativeType);\n return {\n id: `type.${typeName}`,\n label: `Create type ${typeName}`,\n summary: `Creates enum type ${typeName}`,\n operationClass: 'additive',\n target: { id: 'postgres' },\n precheck: [\n {\n description: `ensure type \"${nativeType}\" does not exist`,\n sql: enumTypeExistsCheck(schemaName, nativeType, false),\n },\n ],\n execute: [\n {\n description: `create type \"${nativeType}\"`,\n sql: `CREATE TYPE ${qualifiedType} AS ENUM (${literalValues})`,\n },\n ],\n postcheck: [\n {\n description: `verify type \"${nativeType}\" exists`,\n sql: enumTypeExistsCheck(schemaName, nativeType),\n },\n ],\n };\n}\n\n/**\n * Computes the optimal position for inserting a new enum value to maintain\n * the desired order relative to existing values.\n *\n * PostgreSQL's `ALTER TYPE ADD VALUE` supports BEFORE/AFTER positioning.\n * This function finds the best reference value by:\n * 1. Looking for the nearest preceding value that already exists\n * 2. Falling back to the nearest following value if no preceding exists\n * 3. Defaulting to end-of-list if no reference is found\n *\n * @param options.desired - The target ordered list of all enum values\n * @param options.desiredIndex - Index of the value being inserted in the desired list\n * @param options.current - Current list of enum values (being built up incrementally)\n * @returns SQL clause (e.g., \" AFTER 'x'\") and insert position for tracking\n */\nfunction computeInsertPosition(options: {\n desired: readonly string[];\n desiredIndex: number;\n current: readonly string[];\n}): { clause: string; insertAt: number } {\n const { desired, desiredIndex, current } = options;\n const currentSet = new Set(current);\n const previous = desired\n .slice(0, desiredIndex)\n .reverse()\n .find((candidate) => currentSet.has(candidate));\n const next = desired.slice(desiredIndex + 1).find((candidate) => currentSet.has(candidate));\n const clause = previous\n ? ` AFTER '${escapeLiteral(previous)}'`\n : next\n ? ` BEFORE '${escapeLiteral(next)}'`\n : '';\n const insertAt = previous\n ? current.indexOf(previous) + 1\n : next\n ? current.indexOf(next)\n : current.length;\n\n return { clause, insertAt };\n}\n\n/**\n * Builds operations to add new enum values to an existing PostgreSQL enum type.\n *\n * Each new value is added with `ALTER TYPE ... ADD VALUE IF NOT EXISTS` for idempotency.\n * Values are inserted in the correct order using BEFORE/AFTER positioning to match\n * the desired final order.\n *\n * This is a safe, non-destructive operation - existing data is not affected.\n *\n * @param options.typeName - Contract-level type name (e.g., 'Role')\n * @param options.nativeType - PostgreSQL type name (e.g., 'role')\n * @param options.schemaName - PostgreSQL schema (e.g., 'public')\n * @param options.desired - Target ordered list of all enum values\n * @param options.existing - Current enum values in the database\n * @returns Array of migration operations to add each missing value\n */\nfunction buildAddValueOperations(options: {\n typeName: string;\n nativeType: string;\n schemaName: string;\n desired: readonly string[];\n existing: readonly string[];\n}): SqlMigrationPlanOperation<unknown>[] {\n const { typeName, nativeType, schemaName } = options;\n const current = [...options.existing];\n const currentSet = new Set(current);\n const operations: SqlMigrationPlanOperation<unknown>[] = [];\n for (let index = 0; index < options.desired.length; index += 1) {\n const value = options.desired[index];\n if (value === undefined) {\n continue;\n }\n if (currentSet.has(value)) {\n continue;\n }\n // Validate the new value doesn't exceed PostgreSQL's label length limit\n validateEnumValueLength(value, typeName);\n const { clause, insertAt } = computeInsertPosition({\n desired: options.desired,\n desiredIndex: index,\n current,\n });\n // Use IF NOT EXISTS for idempotency - safe to re-run after partial failures.\n // Supported in PostgreSQL 9.3+, and we require PostgreSQL 12+.\n operations.push({\n id: `type.${typeName}.value.${value}`,\n label: `Add value ${value} to ${typeName}`,\n summary: `Adds enum value ${value} to ${typeName}`,\n operationClass: 'widening',\n target: { id: 'postgres' },\n precheck: [],\n execute: [\n {\n description: `add value \"${value}\" if not exists`,\n sql: `ALTER TYPE ${qualifyName(schemaName, nativeType)} ADD VALUE IF NOT EXISTS '${escapeLiteral(\n value,\n )}'${clause}`,\n },\n ],\n postcheck: [],\n });\n current.splice(insertAt, 0, value);\n currentSet.add(value);\n }\n return operations;\n}\n\n/**\n * Collects columns using the enum type from the contract (desired state).\n * Used for type-safe reference tracking.\n */\nfunction collectEnumColumnsFromContract(\n contract: Contract<SqlStorage>,\n typeName: string,\n nativeType: string,\n): ReadonlyArray<{ table: string; column: string }> {\n const columns: Array<{ table: string; column: string }> = [];\n for (const [tableName, table] of Object.entries(contract.storage.tables)) {\n for (const [columnName, column] of Object.entries(table.columns)) {\n if (\n column.typeRef === typeName ||\n (column.nativeType === nativeType && column.codecId === PG_ENUM_CODEC_ID)\n ) {\n columns.push({ table: tableName, column: columnName });\n }\n }\n }\n return columns;\n}\n\n/**\n * Collects columns using the enum type from the schema IR (live database state).\n * This ensures we find ALL dependent columns, including those added outside the contract\n * (e.g., manual DDL), which is critical for safe enum rebuild operations.\n */\nfunction collectEnumColumnsFromSchema(\n schema: SqlSchemaIR,\n nativeType: string,\n): ReadonlyArray<{ table: string; column: string }> {\n const columns: Array<{ table: string; column: string }> = [];\n for (const [tableName, table] of Object.entries(schema.tables)) {\n for (const [columnName, column] of Object.entries(table.columns)) {\n // Match by nativeType since schema IR doesn't have codecId/typeRef\n if (column.nativeType === nativeType) {\n columns.push({ table: tableName, column: columnName });\n }\n }\n }\n return columns;\n}\n\n/**\n * Collects all columns using the enum type from both contract AND live database.\n * Merges and deduplicates to ensure we migrate ALL dependent columns during rebuild.\n *\n * This is critical for data integrity: if a column exists in the database using\n * this enum but is not in the contract (e.g., added via manual DDL), we must\n * still migrate it to avoid DROP TYPE failures.\n */\nfunction collectAllEnumColumns(\n contract: Contract<SqlStorage>,\n schema: SqlSchemaIR,\n typeName: string,\n nativeType: string,\n): ReadonlyArray<{ table: string; column: string }> {\n const contractColumns = collectEnumColumnsFromContract(contract, typeName, nativeType);\n const schemaColumns = collectEnumColumnsFromSchema(schema, nativeType);\n\n // Merge and deduplicate using a Set of \"table.column\" keys\n const seen = new Set<string>();\n const result: Array<{ table: string; column: string }> = [];\n\n for (const col of [...contractColumns, ...schemaColumns]) {\n const key = `${col.table}.${col.column}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(col);\n }\n }\n\n // Sort for deterministic operation order\n return result.sort((a, b) => {\n const tableCompare = a.table.localeCompare(b.table);\n return tableCompare !== 0 ? tableCompare : a.column.localeCompare(b.column);\n });\n}\n\n/**\n * Builds a SQL check to verify a column's type matches an expected type.\n */\nfunction columnTypeCheck(options: {\n schemaName: string;\n tableName: string;\n columnName: string;\n expectedType: string;\n}): string {\n return `SELECT EXISTS (\n SELECT 1\n FROM information_schema.columns\n WHERE table_schema = '${escapeLiteral(options.schemaName)}'\n AND table_name = '${escapeLiteral(options.tableName)}'\n AND column_name = '${escapeLiteral(options.columnName)}'\n AND udt_name = '${escapeLiteral(options.expectedType)}'\n)`;\n}\n\n/** PostgreSQL maximum identifier length (NAMEDATALEN - 1) */\nconst MAX_IDENTIFIER_LENGTH = 63;\n\n/** Suffix added to enum type names during rebuild operations */\nconst REBUILD_SUFFIX = '__pn_rebuild';\n\n/**\n * Builds an SQL check to verify no rows contain any of the removed enum values.\n * This prevents data loss during enum rebuild operations.\n *\n * @param schemaName - PostgreSQL schema name\n * @param tableName - Table containing the enum column\n * @param columnName - Column using the enum type\n * @param removedValues - Array of enum values being removed\n * @returns SQL query that returns true if no rows contain removed values\n */\nfunction noRemovedValuesExistCheck(\n schemaName: string,\n tableName: string,\n columnName: string,\n removedValues: readonly string[],\n): string {\n if (removedValues.length === 0) {\n // No values being removed, always passes\n return 'SELECT true';\n }\n const valuesList = removedValues.map((v) => `'${escapeLiteral(v)}'`).join(', ');\n return `SELECT NOT EXISTS (\n SELECT 1 FROM ${qualifyName(schemaName, tableName)}\n WHERE ${quoteIdentifier(columnName)}::text IN (${valuesList})\n LIMIT 1\n)`;\n}\n\n/**\n * Builds a migration operation to recreate a PostgreSQL enum type with updated values.\n *\n * This is required when:\n * - Enum values are removed (PostgreSQL doesn't support direct removal)\n * - Enum values are reordered (PostgreSQL doesn't support reordering)\n *\n * The operation:\n * 1. Creates a new enum type with the desired values (temp name)\n * 2. Migrates all columns to use the new type via text cast\n * 3. Drops the original type\n * 4. Renames the temp type to the original name\n *\n * IMPORTANT: If values are being removed and data exists using those values,\n * the operation will fail at the precheck stage with a clear error message.\n * This prevents silent data loss.\n *\n * @param options.typeName - Contract-level type name\n * @param options.nativeType - PostgreSQL type name\n * @param options.schemaName - PostgreSQL schema\n * @param options.values - Desired final enum values\n * @param options.removedValues - Values being removed (for data loss checks)\n * @param options.contract - Full contract for column discovery\n * @param options.schema - Current schema IR for column discovery\n * @returns Migration operation for full enum rebuild\n */\nfunction buildRecreateEnumOperation(options: {\n typeName: string;\n nativeType: string;\n schemaName: string;\n values: readonly string[];\n removedValues: readonly string[];\n contract: Contract<SqlStorage>;\n schema: SqlSchemaIR;\n}): SqlMigrationPlanOperation<unknown> {\n const tempTypeName = `${options.nativeType}${REBUILD_SUFFIX}`;\n\n // Validate temp type name length won't exceed PostgreSQL's 63-character limit.\n // If it would, PostgreSQL silently truncates which could cause conflicts.\n if (tempTypeName.length > MAX_IDENTIFIER_LENGTH) {\n const maxBaseLength = MAX_IDENTIFIER_LENGTH - REBUILD_SUFFIX.length;\n throw new Error(\n `Enum type name \"${options.nativeType}\" is too long for rebuild operation. ` +\n `Maximum length is ${maxBaseLength} characters (type name + \"${REBUILD_SUFFIX}\" suffix ` +\n `must fit within PostgreSQL's ${MAX_IDENTIFIER_LENGTH}-character identifier limit).`,\n );\n }\n\n const qualifiedOriginal = qualifyName(options.schemaName, options.nativeType);\n const qualifiedTemp = qualifyName(options.schemaName, tempTypeName);\n const literalValues = options.values.map((value) => `'${escapeLiteral(value)}'`).join(', ');\n\n // CRITICAL: Collect columns from BOTH contract AND live database.\n // This ensures we migrate ALL dependent columns, including those added\n // outside of Prisma Next (e.g., manual DDL). Without this, DROP TYPE\n // would fail if the database has columns not tracked in the contract.\n const columnRefs = collectAllEnumColumns(\n options.contract,\n options.schema,\n options.typeName,\n options.nativeType,\n );\n\n const alterColumns = columnRefs.map((ref) => ({\n description: `alter ${ref.table}.${ref.column} to ${tempTypeName}`,\n sql: `ALTER TABLE ${qualifyName(options.schemaName, ref.table)}\nALTER COLUMN ${quoteIdentifier(ref.column)}\nTYPE ${qualifiedTemp}\nUSING ${quoteIdentifier(ref.column)}::text::${qualifiedTemp}`,\n }));\n\n // Build postchecks to verify:\n // 1. The final type exists with the correct name\n // 2. The temp type was cleaned up (renamed away)\n // 3. All migrated columns now reference the final type\n const postchecks = [\n {\n description: `verify type \"${options.nativeType}\" exists`,\n sql: enumTypeExistsCheck(options.schemaName, options.nativeType),\n },\n {\n description: `verify temp type \"${tempTypeName}\" was removed`,\n sql: enumTypeExistsCheck(options.schemaName, tempTypeName, false),\n },\n // Verify each column was successfully migrated to the final type\n ...columnRefs.map((ref) => ({\n description: `verify ${ref.table}.${ref.column} uses type \"${options.nativeType}\"`,\n sql: columnTypeCheck({\n schemaName: options.schemaName,\n tableName: ref.table,\n columnName: ref.column,\n expectedType: options.nativeType,\n }),\n })),\n ];\n\n return {\n id: `type.${options.typeName}.rebuild`,\n label: `Rebuild type ${options.typeName}`,\n summary: `Recreates enum type ${options.typeName} with updated values`,\n operationClass: 'destructive',\n target: { id: 'postgres' },\n precheck: [\n {\n description: `ensure type \"${options.nativeType}\" exists`,\n sql: enumTypeExistsCheck(options.schemaName, options.nativeType),\n },\n // Note: We don't precheck that temp type doesn't exist because we handle\n // orphaned temp types in the execute step below.\n\n // CRITICAL: If values are being removed, verify no data exists using those values.\n // This prevents silent data loss during the rebuild - the USING cast would fail\n // at runtime if rows contain values that don't exist in the new enum.\n ...(options.removedValues.length > 0\n ? columnRefs.map((ref) => ({\n description: `ensure no rows in ${ref.table}.${ref.column} contain removed values (${options.removedValues.join(', ')})`,\n sql: noRemovedValuesExistCheck(\n options.schemaName,\n ref.table,\n ref.column,\n options.removedValues,\n ),\n }))\n : []),\n ],\n execute: [\n // Clean up any orphaned temp type from a previous failed migration.\n // This makes the operation recoverable without manual intervention.\n // DROP TYPE IF EXISTS is safe - it's a no-op if the type doesn't exist.\n {\n description: `drop orphaned temp type \"${tempTypeName}\" if exists`,\n sql: `DROP TYPE IF EXISTS ${qualifiedTemp}`,\n },\n {\n description: `create temp type \"${tempTypeName}\"`,\n sql: `CREATE TYPE ${qualifiedTemp} AS ENUM (${literalValues})`,\n },\n ...alterColumns,\n {\n description: `drop type \"${options.nativeType}\"`,\n sql: `DROP TYPE ${qualifiedOriginal}`,\n },\n {\n description: `rename type \"${tempTypeName}\" to \"${options.nativeType}\"`,\n sql: `ALTER TYPE ${qualifiedTemp} RENAME TO ${quoteIdentifier(options.nativeType)}`,\n },\n ],\n postcheck: postchecks,\n };\n}\n\n// ============================================================================\n// Codec Control Hooks\n// ============================================================================\n\n/**\n * Postgres enum hooks for planning, verifying, and introspecting `storage.types`.\n */\nexport const pgEnumControlHooks: CodecControlHooks = {\n planTypeOperations: ({ typeName, typeInstance, contract, schema, schemaName }) => {\n const desired = getEnumValues(typeInstance);\n if (!desired || desired.length === 0) {\n return { operations: [] };\n }\n\n const schemaNamespace = schemaName ?? 'public';\n const existing = readExistingEnumValues(schema, typeInstance.nativeType);\n if (!existing) {\n return {\n operations: [\n buildCreateEnumOperation(typeName, typeInstance.nativeType, schemaNamespace, desired),\n ],\n };\n }\n\n const diff = determineEnumDiff(existing, desired);\n if (diff.kind === 'unchanged') {\n return { operations: [] };\n }\n\n if (diff.kind === 'rebuild') {\n return {\n operations: [\n buildRecreateEnumOperation({\n typeName,\n nativeType: typeInstance.nativeType,\n schemaName: schemaNamespace,\n values: desired,\n removedValues: diff.removedValues,\n contract,\n schema,\n }),\n ],\n };\n }\n\n return {\n operations: buildAddValueOperations({\n typeName,\n nativeType: typeInstance.nativeType,\n schemaName: schemaNamespace,\n desired,\n existing,\n }),\n };\n },\n verifyType: ({ typeName, typeInstance, schema }) => {\n const desired = getEnumValues(typeInstance);\n if (!desired) {\n return [];\n }\n const existing = readExistingEnumValues(schema, typeInstance.nativeType);\n if (!existing) {\n return [\n {\n kind: 'type_missing',\n typeName,\n message: `Type \"${typeName}\" is missing from database`,\n },\n ];\n }\n const diff = determineEnumDiff(existing, desired);\n if (diff.kind === 'unchanged') return [];\n const existingSet = new Set(existing);\n const desiredSet = new Set(desired);\n const addedValues = desired.filter((v) => !existingSet.has(v));\n const removedValues = existing.filter((v) => !desiredSet.has(v));\n return [\n {\n kind: 'enum_values_changed' as const,\n typeName,\n addedValues,\n removedValues,\n message:\n diff.kind === 'add_values'\n ? `Enum type \"${typeName}\" needs new values: ${addedValues.join(', ')}`\n : `Enum type \"${typeName}\" values changed (requires rebuild): +[${addedValues.join(', ')}] -[${removedValues.join(', ')}]`,\n },\n ];\n },\n introspectTypes: async ({ driver, schemaName }) => {\n const namespace = schemaName ?? 'public';\n const result = await driver.query<EnumRow>(ENUM_INTROSPECT_QUERY, [namespace]);\n const types: Record<string, StorageTypeInstance> = {};\n for (const row of result.rows) {\n const values = parsePostgresArray(row.values);\n if (!values) {\n throw new Error(\n `Failed to parse enum values for type \"${row.type_name}\": ` +\n `unexpected format: ${JSON.stringify(row.values)}`,\n );\n }\n types[row.type_name] = {\n codecId: PG_ENUM_CODEC_ID,\n nativeType: row.type_name,\n typeParams: { values },\n };\n }\n return types;\n },\n};\n","import type { CodecControlHooks, ExpandNativeTypeInput } from '@prisma-next/family-sql/control';\nimport { buildOperation, refsOf, toExpr } from '@prisma-next/sql-relational-core/expression';\nimport {\n PG_BIT_CODEC_ID,\n PG_BOOL_CODEC_ID,\n PG_BYTEA_CODEC_ID,\n PG_CHAR_CODEC_ID,\n PG_ENUM_CODEC_ID,\n PG_FLOAT_CODEC_ID,\n PG_FLOAT4_CODEC_ID,\n PG_FLOAT8_CODEC_ID,\n PG_INT_CODEC_ID,\n PG_INT2_CODEC_ID,\n PG_INT4_CODEC_ID,\n PG_INT8_CODEC_ID,\n PG_INTERVAL_CODEC_ID,\n PG_JSON_CODEC_ID,\n PG_JSONB_CODEC_ID,\n PG_NUMERIC_CODEC_ID,\n PG_TEXT_CODEC_ID,\n PG_TIME_CODEC_ID,\n PG_TIMESTAMP_CODEC_ID,\n PG_TIMESTAMPTZ_CODEC_ID,\n PG_TIMETZ_CODEC_ID,\n PG_VARBIT_CODEC_ID,\n PG_VARCHAR_CODEC_ID,\n SQL_CHAR_CODEC_ID,\n SQL_FLOAT_CODEC_ID,\n SQL_INT_CODEC_ID,\n SQL_TEXT_CODEC_ID,\n SQL_TIMESTAMP_CODEC_ID,\n SQL_VARCHAR_CODEC_ID,\n} from '@prisma-next/target-postgres/codec-ids';\nimport { postgresCodecRegistry } from '@prisma-next/target-postgres/codecs';\nimport type { QueryOperationTypes } from '../types/operation-types';\nimport { pgEnumControlHooks } from './enum-control-hooks';\n\n// ============================================================================ Helper functions for reducing boilerplate ============================================================================\n\n/** Creates a type import spec for codec types */\nconst codecTypeImport = (named: string) =>\n ({\n package: '@prisma-next/target-postgres/codec-types',\n named,\n alias: named,\n }) as const;\n\nfunction isPositiveInteger(value: unknown): value is number {\n return (\n typeof value === 'number' && Number.isFinite(value) && Number.isInteger(value) && value > 0\n );\n}\n\nfunction isNonNegativeInteger(value: unknown): value is number {\n return (\n typeof value === 'number' && Number.isFinite(value) && Number.isInteger(value) && value >= 0\n );\n}\n\nfunction expandLength({ nativeType, typeParams }: ExpandNativeTypeInput): string {\n if (!typeParams || !('length' in typeParams)) {\n return nativeType;\n }\n const length = typeParams['length'];\n if (!isPositiveInteger(length)) {\n throw new Error(\n `Invalid \"length\" type parameter for \"${nativeType}\": expected a positive integer, got ${JSON.stringify(length)}`,\n );\n }\n return `${nativeType}(${length})`;\n}\n\nfunction expandPrecision({ nativeType, typeParams }: ExpandNativeTypeInput): string {\n if (!typeParams || !('precision' in typeParams)) {\n return nativeType;\n }\n const precision = typeParams['precision'];\n if (!isPositiveInteger(precision)) {\n throw new Error(\n `Invalid \"precision\" type parameter for \"${nativeType}\": expected a positive integer, got ${JSON.stringify(precision)}`,\n );\n }\n return `${nativeType}(${precision})`;\n}\n\nfunction expandNumeric({ nativeType, typeParams }: ExpandNativeTypeInput): string {\n const hasPrecision = typeParams && 'precision' in typeParams;\n const hasScale = typeParams && 'scale' in typeParams;\n\n if (!hasPrecision && !hasScale) {\n return nativeType;\n }\n\n if (!hasPrecision && hasScale) {\n throw new Error(\n `Invalid type parameters for \"${nativeType}\": \"scale\" requires \"precision\" to be specified`,\n );\n }\n\n if (hasPrecision) {\n const precision = typeParams['precision'];\n if (!isPositiveInteger(precision)) {\n throw new Error(\n `Invalid \"precision\" type parameter for \"${nativeType}\": expected a positive integer, got ${JSON.stringify(precision)}`,\n );\n }\n if (hasScale) {\n const scale = typeParams['scale'];\n if (!isNonNegativeInteger(scale)) {\n throw new Error(\n `Invalid \"scale\" type parameter for \"${nativeType}\": expected a non-negative integer, got ${JSON.stringify(scale)}`,\n );\n }\n return `${nativeType}(${precision},${scale})`;\n }\n return `${nativeType}(${precision})`;\n }\n\n return nativeType;\n}\n\nconst lengthHooks: CodecControlHooks = { expandNativeType: expandLength };\nconst precisionHooks: CodecControlHooks = { expandNativeType: expandPrecision };\nconst numericHooks: CodecControlHooks = { expandNativeType: expandNumeric };\nconst identityHooks: CodecControlHooks = { expandNativeType: ({ nativeType }) => nativeType };\n\n// ============================================================================ Descriptor metadata ============================================================================\n\ntype CodecTypesBase = Record<string, { readonly input: unknown; readonly output: unknown }>;\n\nexport function postgresQueryOperations<CT extends CodecTypesBase>(): QueryOperationTypes<CT> {\n return {\n ilike: {\n self: { traits: ['textual'] },\n impl: (self, pattern) => {\n const selfRefs = refsOf(self);\n return buildOperation({\n method: 'ilike',\n args: [toExpr(self), toExpr(pattern, PG_TEXT_CODEC_ID, selfRefs)],\n returns: { codecId: PG_BOOL_CODEC_ID, nullable: false },\n lowering: { targetFamily: 'sql', strategy: 'infix', template: '{{self}} ILIKE {{arg0}}' },\n });\n },\n },\n };\n}\n\nexport const postgresAdapterDescriptorMeta = {\n kind: 'adapter',\n familyId: 'sql',\n targetId: 'postgres',\n id: 'postgres',\n version: '0.0.1',\n capabilities: {\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 types: {\n codecTypes: {\n codecDescriptors: Array.from(postgresCodecRegistry.values()),\n import: {\n package: '@prisma-next/target-postgres/codec-types',\n named: 'CodecTypes',\n alias: 'PgTypes',\n },\n typeImports: [\n {\n package: '@prisma-next/target-postgres/codec-types',\n named: 'JsonValue',\n alias: 'JsonValue',\n },\n codecTypeImport('Char'),\n codecTypeImport('Varchar'),\n codecTypeImport('Numeric'),\n codecTypeImport('Bit'),\n codecTypeImport('VarBit'),\n codecTypeImport('Timestamp'),\n codecTypeImport('Timestamptz'),\n codecTypeImport('Time'),\n codecTypeImport('Timetz'),\n codecTypeImport('Interval'),\n ],\n controlPlaneHooks: {\n [SQL_CHAR_CODEC_ID]: lengthHooks,\n [SQL_VARCHAR_CODEC_ID]: lengthHooks,\n [SQL_TIMESTAMP_CODEC_ID]: precisionHooks,\n [PG_CHAR_CODEC_ID]: lengthHooks,\n [PG_VARCHAR_CODEC_ID]: lengthHooks,\n [PG_NUMERIC_CODEC_ID]: numericHooks,\n [PG_BIT_CODEC_ID]: lengthHooks,\n [PG_VARBIT_CODEC_ID]: lengthHooks,\n [PG_TIMESTAMP_CODEC_ID]: precisionHooks,\n [PG_TIMESTAMPTZ_CODEC_ID]: precisionHooks,\n [PG_TIME_CODEC_ID]: precisionHooks,\n [PG_TIMETZ_CODEC_ID]: precisionHooks,\n [PG_INTERVAL_CODEC_ID]: precisionHooks,\n [PG_ENUM_CODEC_ID]: pgEnumControlHooks,\n [PG_JSON_CODEC_ID]: identityHooks,\n [PG_JSONB_CODEC_ID]: identityHooks,\n [PG_BYTEA_CODEC_ID]: identityHooks,\n },\n },\n storage: [\n { typeId: PG_TEXT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'text' },\n { typeId: SQL_TEXT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'text' },\n { typeId: SQL_CHAR_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'character' },\n {\n typeId: SQL_VARCHAR_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'character varying',\n },\n { typeId: SQL_INT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int4' },\n { typeId: SQL_FLOAT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'float8' },\n {\n typeId: SQL_TIMESTAMP_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'timestamp',\n },\n { typeId: PG_CHAR_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'character' },\n {\n typeId: PG_VARCHAR_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'character varying',\n },\n { typeId: PG_INT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int4' },\n { typeId: PG_FLOAT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'float8' },\n { typeId: PG_INT4_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int4' },\n { typeId: PG_INT2_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int2' },\n { typeId: PG_INT8_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int8' },\n { typeId: PG_FLOAT4_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'float4' },\n { typeId: PG_FLOAT8_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'float8' },\n { typeId: PG_NUMERIC_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'numeric' },\n {\n typeId: PG_TIMESTAMP_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'timestamp',\n },\n {\n typeId: PG_TIMESTAMPTZ_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'timestamptz',\n },\n { typeId: PG_TIME_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'time' },\n { typeId: PG_TIMETZ_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'timetz' },\n { typeId: PG_BOOL_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'bool' },\n { typeId: PG_BIT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'bit' },\n {\n typeId: PG_VARBIT_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'bit varying',\n },\n {\n typeId: PG_INTERVAL_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'interval',\n },\n { typeId: PG_JSON_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'json' },\n { typeId: PG_JSONB_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'jsonb' },\n { typeId: PG_BYTEA_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'bytea' },\n ],\n queryOperationTypes: {\n import: {\n package: '@prisma-next/adapter-postgres/operation-types',\n named: 'QueryOperationTypes',\n alias: 'PgAdapterQueryOps',\n },\n },\n },\n} as const;\n"],"mappings":"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"}
package/dist/runtime.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as createPostgresAdapter } from "./adapter-Ctu5_BR4.mjs";
2
- import { n as postgresQueryOperations, t as postgresAdapterDescriptorMeta } from "./descriptor-meta-C2VasIft.mjs";
2
+ import { n as postgresQueryOperations, t as postgresAdapterDescriptorMeta } from "./descriptor-meta-CyjnYUWG.mjs";
3
3
  import { extractCodecLookup } from "@prisma-next/framework-components/control";
4
4
  import { postgresCodecRegistry } from "@prisma-next/target-postgres/codecs";
5
5
  import { builtinGeneratorIds } from "@prisma-next/ids";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma-next/adapter-postgres",
3
- "version": "0.5.0-dev.81",
3
+ "version": "0.5.0-dev.83",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -10,34 +10,34 @@
10
10
  ],
11
11
  "dependencies": {
12
12
  "arktype": "^2.1.29",
13
- "@prisma-next/contract-authoring": "0.5.0-dev.81",
14
- "@prisma-next/family-sql": "0.5.0-dev.81",
15
- "@prisma-next/framework-components": "0.5.0-dev.81",
16
- "@prisma-next/contract": "0.5.0-dev.81",
17
- "@prisma-next/sql-contract-psl": "0.5.0-dev.81",
18
- "@prisma-next/ids": "0.5.0-dev.81",
19
- "@prisma-next/sql-contract": "0.5.0-dev.81",
20
- "@prisma-next/sql-contract-ts": "0.5.0-dev.81",
21
- "@prisma-next/sql-relational-core": "0.5.0-dev.81",
22
- "@prisma-next/sql-operations": "0.5.0-dev.81",
23
- "@prisma-next/sql-schema-ir": "0.5.0-dev.81",
24
- "@prisma-next/target-postgres": "0.5.0-dev.81",
25
- "@prisma-next/utils": "0.5.0-dev.81",
26
- "@prisma-next/sql-runtime": "0.5.0-dev.81"
13
+ "@prisma-next/contract": "0.5.0-dev.83",
14
+ "@prisma-next/family-sql": "0.5.0-dev.83",
15
+ "@prisma-next/contract-authoring": "0.5.0-dev.83",
16
+ "@prisma-next/framework-components": "0.5.0-dev.83",
17
+ "@prisma-next/ids": "0.5.0-dev.83",
18
+ "@prisma-next/sql-contract": "0.5.0-dev.83",
19
+ "@prisma-next/sql-contract-psl": "0.5.0-dev.83",
20
+ "@prisma-next/sql-operations": "0.5.0-dev.83",
21
+ "@prisma-next/sql-contract-ts": "0.5.0-dev.83",
22
+ "@prisma-next/sql-relational-core": "0.5.0-dev.83",
23
+ "@prisma-next/sql-schema-ir": "0.5.0-dev.83",
24
+ "@prisma-next/sql-runtime": "0.5.0-dev.83",
25
+ "@prisma-next/target-postgres": "0.5.0-dev.83",
26
+ "@prisma-next/utils": "0.5.0-dev.83"
27
27
  },
28
28
  "devDependencies": {
29
29
  "pathe": "^2.0.3",
30
30
  "tsdown": "0.22.0",
31
31
  "typescript": "5.9.3",
32
32
  "vitest": "4.1.5",
33
- "@prisma-next/cli": "0.5.0-dev.81",
34
- "@prisma-next/driver-postgres": "0.5.0-dev.81",
35
- "@prisma-next/errors": "0.5.0-dev.81",
36
- "@prisma-next/extension-pgvector": "0.5.0-dev.81",
33
+ "@prisma-next/driver-postgres": "0.5.0-dev.83",
34
+ "@prisma-next/errors": "0.5.0-dev.83",
35
+ "@prisma-next/cli": "0.5.0-dev.83",
36
+ "@prisma-next/migration-tools": "0.5.0-dev.83",
37
+ "@prisma-next/extension-pgvector": "0.5.0-dev.83",
37
38
  "@prisma-next/test-utils": "0.0.1",
38
39
  "@prisma-next/tsconfig": "0.0.0",
39
- "@prisma-next/tsdown": "0.0.0",
40
- "@prisma-next/migration-tools": "0.5.0-dev.81"
40
+ "@prisma-next/tsdown": "0.0.0"
41
41
  },
42
42
  "exports": {
43
43
  "./adapter": "./dist/adapter.mjs",
@@ -352,17 +352,22 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
352
352
  indisunique: boolean;
353
353
  attname: string;
354
354
  attnum: number;
355
+ amname: string;
356
+ reloptions: readonly string[] | null;
355
357
  }>(
356
358
  `SELECT
357
359
  i.tablename,
358
360
  i.indexname,
359
361
  ix.indisunique,
360
362
  a.attname,
361
- a.attnum
363
+ a.attnum,
364
+ am.amname,
365
+ ic.reloptions
362
366
  FROM pg_indexes i
363
367
  JOIN pg_class ic ON ic.relname = i.indexname
364
368
  JOIN pg_namespace ins ON ins.oid = ic.relnamespace AND ins.nspname = $1
365
369
  JOIN pg_index ix ON ix.indexrelid = ic.oid
370
+ JOIN pg_am am ON am.oid = ic.relam
366
371
  JOIN pg_class t ON t.oid = ix.indrelid
367
372
  JOIN pg_namespace tn ON tn.oid = t.relnamespace AND tn.nspname = $1
368
373
  LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey) AND a.attnum > 0
@@ -520,7 +525,16 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
520
525
  }));
521
526
 
522
527
  // Process indexes
523
- const indexesMap = new Map<string, { columns: string[]; name: string; unique: boolean }>();
528
+ const indexesMap = new Map<
529
+ string,
530
+ {
531
+ columns: string[];
532
+ name: string;
533
+ unique: boolean;
534
+ type: string | undefined;
535
+ options: Record<string, string> | undefined;
536
+ }
537
+ >();
524
538
  for (const idxRow of indexesByTable.get(tableName) ?? []) {
525
539
  if (!idxRow.attname) {
526
540
  continue;
@@ -529,10 +543,17 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
529
543
  if (existing) {
530
544
  existing.columns.push(idxRow.attname);
531
545
  } else {
546
+ // Drop btree (the Postgres default) so a contract index without an
547
+ // explicit type matches a default-method introspected index without
548
+ // forcing DROP+CREATE on every plan.
549
+ const indexType = idxRow.amname === 'btree' ? undefined : idxRow.amname;
550
+ const indexOptions = parsePgReloptions(idxRow.reloptions, idxRow.indexname);
532
551
  indexesMap.set(idxRow.indexname, {
533
552
  columns: [idxRow.attname],
534
553
  name: idxRow.indexname,
535
554
  unique: idxRow.indisunique,
555
+ type: indexType,
556
+ options: indexOptions,
536
557
  });
537
558
  }
538
559
  }
@@ -540,6 +561,8 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
540
561
  columns: Object.freeze([...idx.columns]) as readonly string[],
541
562
  name: idx.name,
542
563
  unique: idx.unique,
564
+ ...(idx.type !== undefined && { type: idx.type }),
565
+ ...(idx.options !== undefined && { options: idx.options }),
543
566
  }));
544
567
 
545
568
  tables[tableName] = {
@@ -673,6 +696,39 @@ function mapReferentialAction(rule: string): SqlReferentialAction | undefined {
673
696
  * Groups an array of objects by a specified key.
674
697
  * Returns a Map for O(1) lookup by group key.
675
698
  */
699
+ /**
700
+ * Parses a `pg_class.reloptions` array into a `Record<string, string>`.
701
+ *
702
+ * Postgres returns reloptions as a `text[]` whose entries are `key=value`
703
+ * strings; the value side is always a string regardless of the underlying
704
+ * scalar type. The verifier compares contract options to introspected
705
+ * options after coercing both sides to strings, so keeping the raw text
706
+ * here is correct.
707
+ *
708
+ * Returns `undefined` when the input is null/empty (no WITH clause).
709
+ */
710
+ export function parsePgReloptions(
711
+ reloptions: readonly string[] | null,
712
+ indexName: string,
713
+ ): Record<string, string> | undefined {
714
+ if (!reloptions || reloptions.length === 0) {
715
+ return undefined;
716
+ }
717
+ const result: Record<string, string> = {};
718
+ for (const entry of reloptions) {
719
+ const eq = entry.indexOf('=');
720
+ if (eq === -1) {
721
+ throw new Error(
722
+ `Postgres introspection: malformed reloption entry "${entry}" on index "${indexName}" (expected "key=value")`,
723
+ );
724
+ }
725
+ const key = entry.slice(0, eq);
726
+ const value = entry.slice(eq + 1);
727
+ result[key] = value;
728
+ }
729
+ return Object.keys(result).length > 0 ? result : undefined;
730
+ }
731
+
676
732
  function groupBy<T, K extends keyof T>(items: readonly T[], key: K): Map<T[K], T[]> {
677
733
  const map = new Map<T[K], T[]>();
678
734
  for (const item of items) {
@@ -1,13 +1,5 @@
1
1
  import type { CodecControlHooks, ExpandNativeTypeInput } from '@prisma-next/family-sql/control';
2
- import type { SqlOperationDescriptor } from '@prisma-next/sql-operations';
3
- import {
4
- buildOperation,
5
- type CodecExpression,
6
- type Expression,
7
- refsOf,
8
- type TraitExpression,
9
- toExpr,
10
- } from '@prisma-next/sql-relational-core/expression';
2
+ import { buildOperation, refsOf, toExpr } from '@prisma-next/sql-relational-core/expression';
11
3
  import {
12
4
  PG_BIT_CODEC_ID,
13
5
  PG_BOOL_CODEC_ID,
@@ -40,6 +32,7 @@ import {
40
32
  SQL_VARCHAR_CODEC_ID,
41
33
  } from '@prisma-next/target-postgres/codec-ids';
42
34
  import { postgresCodecRegistry } from '@prisma-next/target-postgres/codecs';
35
+ import type { QueryOperationTypes } from '../types/operation-types';
43
36
  import { pgEnumControlHooks } from './enum-control-hooks';
44
37
 
45
38
  // ============================================================================ Helper functions for reducing boilerplate ============================================================================
@@ -135,17 +128,11 @@ const identityHooks: CodecControlHooks = { expandNativeType: ({ nativeType }) =>
135
128
 
136
129
  type CodecTypesBase = Record<string, { readonly input: unknown; readonly output: unknown }>;
137
130
 
138
- export function postgresQueryOperations<
139
- CT extends CodecTypesBase,
140
- >(): readonly SqlOperationDescriptor[] {
141
- return [
142
- {
143
- method: 'ilike',
131
+ export function postgresQueryOperations<CT extends CodecTypesBase>(): QueryOperationTypes<CT> {
132
+ return {
133
+ ilike: {
144
134
  self: { traits: ['textual'] },
145
- impl: (
146
- self: TraitExpression<readonly ['textual'], false, CT>,
147
- pattern: CodecExpression<'pg/text@1', false, CT>,
148
- ): Expression<{ codecId: 'pg/bool@1'; nullable: false }> => {
135
+ impl: (self, pattern) => {
149
136
  const selfRefs = refsOf(self);
150
137
  return buildOperation({
151
138
  method: 'ilike',
@@ -155,7 +142,7 @@ export function postgresQueryOperations<
155
142
  });
156
143
  },
157
144
  },
158
- ];
145
+ };
159
146
  }
160
147
 
161
148
  export const postgresAdapterDescriptorMeta = {