@prisma-next/target-postgres 0.14.0-dev.43 → 0.14.0-dev.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/control.mjs CHANGED
@@ -6,12 +6,12 @@ import { n as PostgresContractSerializer } from "./postgres-contract-view-BegduL
6
6
  import { blindCast } from "@prisma-next/utils/casts";
7
7
  import { extractCodecControlHooks, runnerFailure, runnerSuccess } from "@prisma-next/family-sql/control";
8
8
  import { ifDefined } from "@prisma-next/utils/defined";
9
- import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
9
+ import { UNBOUND_NAMESPACE_ID, coordinateKey, elementCoordinates } from "@prisma-next/framework-components/ir";
10
10
  import { APP_SPACE_ID } from "@prisma-next/framework-components/control";
11
11
  import { notOk, ok, okVoid } from "@prisma-next/utils/result";
12
12
  import { SqlSchemaVerifierBase } from "@prisma-next/family-sql/ir";
13
13
  import { SqlQueryError } from "@prisma-next/sql-errors";
14
- import { inferRelations, mapDefault, parseRawDefault, toFieldName, toModelName, toNamedTypeName } from "@prisma-next/family-sql/psl-infer";
14
+ import { buildChildRelationField, deriveRelationFieldName, inferRelations, mapDefault, parseRawDefault, toFieldName, toModelName, toNamedTypeName } from "@prisma-next/family-sql/psl-infer";
15
15
  import { UNSPECIFIED_PSL_NAMESPACE_ID, makePslNamespace, makePslNamespaceEntries } from "@prisma-next/framework-components/psl-ast";
16
16
  //#region src/core/migrations/runner.ts
17
17
  const LOCK_DOMAIN = "prisma_next.contract.marker";
@@ -621,6 +621,108 @@ const PSL_SCALAR_TYPE_NAMES = new Set([
621
621
  "Bytes"
622
622
  ]);
623
623
  /**
624
+ * Coordinates every element a set of already-assembled contracts declare,
625
+ * mapped to the {@link SqlDescribedContractSpace} that owns it and keyed by
626
+ * the shared {@link coordinateKey} helper. `contract infer` uses this to omit
627
+ * database elements a stack extension pack's contract space already
628
+ * describes — reusing the same coordinate walk the contract-space aggregate
629
+ * and cross-space collision check use (`elementCoordinates`), rather than a
630
+ * bespoke per-entity-kind membership test — and, for a foreign key whose
631
+ * referenced table an entry owns, to resolve the qualified cross-space
632
+ * relation it describes.
633
+ */
634
+ function describedContractOwners(describedContracts) {
635
+ const owners = /* @__PURE__ */ new Map();
636
+ for (const entry of describedContracts) for (const coordinate of elementCoordinates(entry.contract.storage)) owners.set(coordinateKey(coordinate), entry);
637
+ return owners;
638
+ }
639
+ function resolveCrossSpaceTarget(owner, namespaceId, tableName) {
640
+ const domainNamespace = owner.contract.domain.namespaces[namespaceId];
641
+ if (domainNamespace === void 0) return;
642
+ for (const [modelName, model] of Object.entries(domainNamespace.models)) {
643
+ const storage = blindCast(model.storage);
644
+ if (storage.namespaceId !== namespaceId || storage.table !== tableName) continue;
645
+ const fieldNamesByColumn = /* @__PURE__ */ new Map();
646
+ for (const [fieldName, fieldStorage] of Object.entries(storage.fields)) fieldNamesByColumn.set(fieldStorage.column, { fieldName });
647
+ return {
648
+ spaceId: owner.spaceId,
649
+ namespaceId,
650
+ modelName,
651
+ fieldNamesByColumn
652
+ };
653
+ }
654
+ }
655
+ /**
656
+ * Classifies every foreign key on a surviving table into one of three cases.
657
+ * A foreign key that carries a `referencedSchema` is checked against the
658
+ * pack-owned coordinates first, so a pack-owned target wins even when a local
659
+ * table happens to share its bare name; only foreign keys with no owned
660
+ * coordinate fall through to the local/dangling distinction.
661
+ *
662
+ * - **Cross-space**: `referencedSchema` is set and a described contract owns
663
+ * the coordinate `(referencedSchema, 'table', referencedTable)`. The
664
+ * referenced table is absent from the tree (omitted because the pack
665
+ * describes it, or never introspected — `contract infer` walks a single
666
+ * namespace). Removed from `foreignKeys` (so `inferRelations` never falls
667
+ * back to a bare, unqualified table name for it) and replaced with a
668
+ * `RelationField` qualified with the owning pack's space id and namespace
669
+ * id. `owners` holds only pack-declared coordinates, so an app's own table
670
+ * (e.g. `public.users`) is never owned and cannot be captured here.
671
+ * - **Local**: not a pack-owned coordinate, and the referenced table survived
672
+ * introspection — left untouched, `inferRelations` handles it as before.
673
+ * - **Dangling**: not a pack-owned coordinate, and the referenced table is
674
+ * neither in the tree nor owned by any described contract. Removed from
675
+ * `foreignKeys`, keeping the scalar column, rather than emitting a relation
676
+ * to a model that was never defined.
677
+ *
678
+ * A pack that owns the referenced coordinate but declares no domain model
679
+ * mapped to it is malformed; that case throws rather than degrading to a
680
+ * silent drop, which would contradict the dangling definition above.
681
+ */
682
+ function resolveForeignKeys(tables, owners) {
683
+ const resultTables = {};
684
+ const extraRelationsByTable = /* @__PURE__ */ new Map();
685
+ const crossSpaceFieldNamesByTable = /* @__PURE__ */ new Map();
686
+ for (const [tableName, table] of Object.entries(tables)) {
687
+ const keptForeignKeys = [];
688
+ for (const fk of table.foreignKeys) {
689
+ if (fk.referencedSchema !== void 0) {
690
+ const owner = owners.get(coordinateKey({
691
+ namespaceId: fk.referencedSchema,
692
+ entityKind: "table",
693
+ entityName: fk.referencedTable
694
+ }));
695
+ if (owner !== void 0) {
696
+ const target = resolveCrossSpaceTarget(owner, fk.referencedSchema, fk.referencedTable);
697
+ if (target === void 0) throw new Error(`contract infer: described contract space "${owner.spaceId}" owns storage coordinate "${fk.referencedSchema}.${fk.referencedTable}" but declares no domain model mapped to it. A pack that describes a table must also declare the domain model it maps to; this pack is malformed.`);
698
+ if (!crossSpaceFieldNamesByTable.has(fk.referencedTable)) crossSpaceFieldNamesByTable.set(fk.referencedTable, target.fieldNamesByColumn);
699
+ const fieldName = deriveRelationFieldName(fk.columns, fk.referencedTable);
700
+ const optional = fk.columns.some((columnName) => table.columns[columnName]?.nullable ?? false);
701
+ const relationField = {
702
+ ...buildChildRelationField(fieldName, target.modelName, fk, optional),
703
+ typeNamespaceId: target.namespaceId,
704
+ typeContractSpaceId: target.spaceId
705
+ };
706
+ const existingRelations = extraRelationsByTable.get(tableName);
707
+ if (existingRelations) existingRelations.push(relationField);
708
+ else extraRelationsByTable.set(tableName, [relationField]);
709
+ continue;
710
+ }
711
+ }
712
+ if (tables[fk.referencedTable] !== void 0) keptForeignKeys.push(fk);
713
+ }
714
+ resultTables[tableName] = keptForeignKeys.length === table.foreignKeys.length ? table : {
715
+ ...table,
716
+ foreignKeys: keptForeignKeys
717
+ };
718
+ }
719
+ return {
720
+ tables: resultTables,
721
+ extraRelationsByTable,
722
+ crossSpaceFieldNamesByTable
723
+ };
724
+ }
725
+ /**
624
726
  * Infers a PSL AST (for `printPsl`) from an introspected Postgres schema tree.
625
727
  *
626
728
  * Target-owned inference: it walks the `PostgresDatabaseSchemaNode` tree and
@@ -633,9 +735,20 @@ const PSL_SCALAR_TYPE_NAMES = new Set([
633
735
  * introspects a single live namespace) are gathered into the model set and
634
736
  * emitted as one `UNSPECIFIED_PSL_NAMESPACE_ID` bucket. Top-level entities
635
737
  * (policies/roles → PSL extension blocks) are a later slice.
738
+ *
739
+ * `describedContracts` — the stack's extension packs' already-assembled
740
+ * contracts, each paired with its space id — is consulted while gathering
741
+ * tables: a table whose coordinate `(schemaName, 'table', tableName)` one of
742
+ * those contracts already declares is omitted, before the duplicate-name
743
+ * check below and before relation inference, so it cannot spuriously
744
+ * collide with an app table and never contributes a bare relation field. A
745
+ * surviving table's foreign key into an omitted, pack-owned table is not
746
+ * dropped: {@link resolveForeignKeys} rewrites it into a relation qualified
747
+ * with the pack's space id (`<spaceId>:<namespaceId>.<Model>`) instead.
636
748
  */
637
- function inferPostgresPslContract(tree) {
749
+ function inferPostgresPslContract(tree, describedContracts) {
638
750
  const namespaces = Object.values(tree.namespaces);
751
+ const owners = describedContractOwners(describedContracts ?? []);
639
752
  const enumTypeNames = [...new Set(namespaces.flatMap((ns) => ns.nativeEnumTypeNames))];
640
753
  if (enumTypeNames.length > 0) {
641
754
  const names = enumTypeNames.join(", ");
@@ -643,25 +756,35 @@ function inferPostgresPslContract(tree) {
643
756
  }
644
757
  const tables = {};
645
758
  for (const namespace of namespaces) for (const [tableName, table] of Object.entries(namespace.tables)) {
759
+ if (owners.has(coordinateKey({
760
+ namespaceId: namespace.schemaName,
761
+ entityKind: "table",
762
+ entityName: tableName
763
+ }))) continue;
646
764
  if (tables[tableName] !== void 0) throw new Error(`contract infer: duplicate table name "${tableName}" across schemas is not yet supported (single-namespace PSL inference emits one flat bucket; multi-namespace \`namespace { … }\` output is a later slice).`);
647
765
  tables[tableName] = table;
648
766
  }
649
- return buildPslDocumentAst({ tables }, {
767
+ const { tables: resolvedTables, extraRelationsByTable, crossSpaceFieldNamesByTable } = resolveForeignKeys(tables, owners);
768
+ return buildPslDocumentAst({ tables: resolvedTables }, {
650
769
  typeMap: createPostgresTypeMap(/* @__PURE__ */ new Set()),
651
770
  defaultMapping: createPostgresDefaultMapping(),
652
771
  parseRawDefault
772
+ }, {
773
+ extraRelationsByTable,
774
+ crossSpaceFieldNamesByTable
653
775
  });
654
776
  }
655
- function buildPslDocumentAst(schemaIR, options) {
777
+ function buildPslDocumentAst(schemaIR, options, foreignKeyExtras) {
656
778
  const { typeMap, defaultMapping, parseRawDefault: rawDefaultParser } = options;
779
+ const { extraRelationsByTable, crossSpaceFieldNamesByTable } = foreignKeyExtras;
657
780
  const modelNames = buildTopLevelNameMap(Object.keys(schemaIR.tables), toModelName, "model", "table");
658
781
  const modelNameMap = new Map([...modelNames].map(([tableName, result]) => [tableName, result.name]));
659
782
  const reservedNamedTypeNames = createReservedNamedTypeNames(modelNames);
660
- const fieldNamesByTable = buildFieldNamesByTable(schemaIR.tables);
783
+ const fieldNamesByTable = new Map([...crossSpaceFieldNamesByTable, ...buildFieldNamesByTable(schemaIR.tables)]);
661
784
  const { relationsByTable } = inferRelations(schemaIR.tables, modelNameMap);
662
785
  const namedTypes = seedNamedTypeRegistry(schemaIR, typeMap, /* @__PURE__ */ new Map(), reservedNamedTypeNames);
663
786
  const models = [];
664
- for (const table of Object.values(schemaIR.tables)) models.push(buildModel(table, typeMap, /* @__PURE__ */ new Map(), fieldNamesByTable, namedTypes, defaultMapping, rawDefaultParser, relationsByTable.get(table.name) ?? []));
787
+ for (const table of Object.values(schemaIR.tables)) models.push(buildModel(table, typeMap, /* @__PURE__ */ new Map(), fieldNamesByTable, namedTypes, defaultMapping, rawDefaultParser, [...relationsByTable.get(table.name) ?? [], ...extraRelationsByTable.get(table.name) ?? []]));
665
788
  const sortedModels = topologicalSort(models, schemaIR.tables, modelNameMap);
666
789
  const namedTypeEntries = [...namedTypes.entriesByKey.values()].sort((a, b) => a.name.localeCompare(b.name));
667
790
  const types = namedTypeEntries.length > 0 ? {
@@ -786,6 +909,8 @@ function buildRelationField(rel, hostTableName, fieldNamesByTable, usedFieldName
786
909
  kind: "field",
787
910
  name: fieldName,
788
911
  typeName: rel.typeName,
912
+ ...ifDefined("typeNamespaceId", rel.typeNamespaceId),
913
+ ...ifDefined("typeContractSpaceId", rel.typeContractSpaceId),
789
914
  optional: rel.optional,
790
915
  list: rel.list,
791
916
  attributes: attrs,
@@ -1023,9 +1148,9 @@ const postgresTargetDescriptor = {
1023
1148
  ...postgresTargetDescriptorMeta,
1024
1149
  contractSerializer: new PostgresContractSerializer(),
1025
1150
  schemaVerifier: new PostgresSchemaVerifier(),
1026
- inferPslContract(schema) {
1151
+ inferPslContract(schema, describedContracts) {
1027
1152
  PostgresDatabaseSchemaNode.assert(schema);
1028
- return inferPostgresPslContract(schema);
1153
+ return inferPostgresPslContract(schema, describedContracts);
1029
1154
  },
1030
1155
  diffDatabaseSchema(input) {
1031
1156
  return diffPostgresDatabaseSchema({
@@ -1 +1 @@
1
- {"version":3,"file":"control.mjs","names":[],"sources":["../src/core/migrations/runner.ts","../src/core/postgres-schema-verifier.ts","../src/core/psl-infer/postgres-default-mapping.ts","../src/core/psl-infer/postgres-type-map.ts","../src/core/psl-infer/infer-psl-contract.ts","../src/exports/control.ts"],"sourcesContent":["import type { Contract, ContractMarkerRecord } from '@prisma-next/contract/types';\nimport type {\n MigrationOperationPolicy,\n SqlControlFamilyInstance,\n SqlMigrationPlanContractInfo,\n SqlMigrationPlanOperation,\n SqlMigrationPlanOperationStep,\n SqlMigrationRunner,\n SqlMigrationRunnerExecuteOptions,\n SqlMigrationRunnerFailure,\n SqlMigrationRunnerResult,\n SqlMigrationRunnerSuccessValue,\n} from '@prisma-next/family-sql/control';\nimport { runnerFailure, runnerSuccess } from '@prisma-next/family-sql/control';\nimport type { MigrationRunnerResult } from '@prisma-next/framework-components/control';\nimport { APP_SPACE_ID } from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type { SqlControlDriverInstance, SqlStorage } from '@prisma-next/sql-contract/types';\nimport { SqlQueryError } from '@prisma-next/sql-errors';\nimport type { SqlExecuteRequest } from '@prisma-next/sql-relational-core/ast';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { Result } from '@prisma-next/utils/result';\nimport { notOk, ok, okVoid } from '@prisma-next/utils/result';\nimport type { PostgresPlanTargetDetails } from './planner-target-details';\n\ninterface ApplyPlanSuccessValue {\n readonly operationsExecuted: number;\n readonly executedOperations: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[];\n}\n\nconst LOCK_DOMAIN = 'prisma_next.contract.marker';\n\n/**\n * Deep clones and freezes a record object to prevent mutation.\n * Recursively clones nested objects and arrays to ensure complete isolation.\n */\nfunction cloneAndFreezeRecord<T extends Record<string, unknown>>(value: T): T {\n const cloned: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n if (val === null || val === undefined) {\n cloned[key] = val;\n } else if (Array.isArray(val)) {\n cloned[key] = Object.freeze([...val]);\n } else if (typeof val === 'object') {\n cloned[key] = cloneAndFreezeRecord(val as Record<string, unknown>);\n } else {\n cloned[key] = val;\n }\n }\n return Object.freeze(cloned) as T;\n}\n\nexport function createPostgresMigrationRunner(\n family: SqlControlFamilyInstance,\n): SqlMigrationRunner<PostgresPlanTargetDetails> {\n return new PostgresMigrationRunner(family);\n}\n\nclass PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDetails> {\n constructor(private readonly family: SqlControlFamilyInstance) {}\n\n /**\n * Body of the migration runner without transaction management. The\n * caller ({@link PostgresMigrationRunner.execute}) owns the\n * `BEGIN`/`COMMIT`/`ROLLBACK` lifecycle.\n */\n async executeOnConnection(\n options: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,\n ): Promise<SqlMigrationRunnerResult> {\n const schema =\n options.schemaName ??\n Object.keys(options.destinationContract.storage.namespaces).find(\n (id) => id !== UNBOUND_NAMESPACE_ID,\n ) ??\n UNBOUND_NAMESPACE_ID;\n const driver = options.driver;\n if (options.space !== undefined && options.space !== options.plan.spaceId) {\n throw new Error(\n `SqlMigrationRunner: options.space (${options.space}) does not match plan.spaceId (${options.plan.spaceId})`,\n );\n }\n const space = options.plan.spaceId;\n const lockKey = `${LOCK_DOMAIN}:${schema}:${space}`;\n\n // Materialize any async ops before running checks or executing.\n const planOps = blindCast<\n readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[],\n 'ops were produced by the PG planner and are SqlMigrationPlanOperation<PostgresPlanTargetDetails>; MigrationPlan.operations uses the wider framework type to accommodate Promise covariance'\n >(await Promise.all(options.plan.operations));\n\n // Static checks (idempotent — safe to run again when the caller is\n // `execute(...)` because the cost is a single object comparison).\n const destinationCheck = this.ensurePlanMatchesDestinationContract(\n options.plan.destination,\n options.destinationContract,\n );\n if (!destinationCheck.ok) return destinationCheck;\n\n const policyCheck = this.enforcePolicyCompatibility(options.policy, planOps);\n if (!policyCheck.ok) return policyCheck;\n\n await this.acquireLock(driver, lockKey);\n const ensureResult = await this.ensureControlTables(driver, options.destinationContract);\n if (!ensureResult.ok) return ensureResult;\n const existingMarker = await this.family.readMarker({ driver, space });\n\n const markerCheck = this.ensureMarkerCompatibility(existingMarker, options.plan);\n if (!markerCheck.ok) return markerCheck;\n\n const markerAtDestination = this.markerMatchesDestination(existingMarker, options.plan);\n const isSelfEdge = options.plan.origin?.storageHash === options.plan.destination.storageHash;\n const skipOperations = markerAtDestination && options.plan.origin != null && !isSelfEdge;\n let applyValue: ApplyPlanSuccessValue;\n\n if (skipOperations) {\n applyValue = { operationsExecuted: 0, executedOperations: [] };\n } else {\n const applyResult = await this.applyPlan(driver, options, planOps);\n if (!applyResult.ok) return applyResult;\n applyValue = applyResult.value;\n }\n\n // Verify the schema on app-space only: extension spaces don't own\n // user-facing tables, so verifying the destination contract against the\n // database would flag every app-space table as \"extra\". Delegates to the\n // family `verifySchema` — the same comparison the CLI verify runs.\n if (space === APP_SPACE_ID) {\n const schemaNode = await this.family.introspect({\n driver,\n contract: options.destinationContract,\n });\n const schemaVerifyResult = this.family.verifySchema({\n contract: options.destinationContract,\n schema: schemaNode,\n strict: options.strictVerification ?? true,\n frameworkComponents: options.frameworkComponents,\n });\n if (!schemaVerifyResult.ok) {\n return runnerFailure('SCHEMA_VERIFY_FAILED', schemaVerifyResult.summary, {\n why: 'The resulting database schema does not satisfy the destination contract.',\n meta: {\n issues: [\n ...schemaVerifyResult.schema.issues,\n ...schemaVerifyResult.schema.schemaDiffIssues,\n ],\n },\n });\n }\n }\n\n const incomingInvariants = options.plan.providedInvariants ?? [];\n const existingInvariants = new Set(existingMarker?.invariants ?? []);\n const incomingIsSubsetOfExisting = incomingInvariants.every((id) => existingInvariants.has(id));\n const isSelfEdgeNoOp =\n isSelfEdge && applyValue.operationsExecuted === 0 && incomingIsSubsetOfExisting;\n\n if (!isSelfEdgeNoOp) {\n const markerResult = await this.upsertMarker(driver, options, existingMarker, space);\n if (!markerResult.ok) return markerResult;\n await this.recordLedgerEntries(\n driver,\n options,\n applyValue.executedOperations,\n planOps.length,\n );\n }\n\n return runnerSuccess({\n operationsPlanned: planOps.length,\n operationsExecuted: applyValue.operationsExecuted,\n });\n }\n\n async execute(options: {\n readonly driver: SqlControlDriverInstance<string>;\n readonly perSpaceOptions: ReadonlyArray<\n SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>\n >;\n }): Promise<MigrationRunnerResult> {\n const driver = options.driver;\n const perSpaceOptions = options.perSpaceOptions;\n\n if (perSpaceOptions.length === 0) {\n return ok({ perSpaceResults: [] });\n }\n\n await this.beginTransaction(driver);\n let committed = false;\n try {\n const perSpaceResults: Array<{\n space: string;\n value: SqlMigrationRunnerSuccessValue;\n }> = [];\n for (const spaceOptions of perSpaceOptions) {\n const space = spaceOptions.space ?? spaceOptions.plan.spaceId;\n const result = await this.executeOnConnection({ ...spaceOptions, driver, space });\n if (!result.ok) {\n return notOk({ ...result.failure, failingSpace: space });\n }\n perSpaceResults.push({ space, value: result.value });\n }\n\n await this.commitTransaction(driver);\n committed = true;\n return ok({ perSpaceResults });\n } finally {\n if (!committed) {\n await this.rollbackTransaction(driver);\n }\n }\n }\n\n private async applyPlan(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n options: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,\n ops: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[],\n ): Promise<Result<ApplyPlanSuccessValue, SqlMigrationRunnerFailure>> {\n const checks = options.executionChecks;\n const runPrechecks = checks?.prechecks !== false; // Default true\n const runPostchecks = checks?.postchecks !== false; // Default true\n const runIdempotency = checks?.idempotencyChecks !== false; // Default true\n\n let operationsExecuted = 0;\n const executedOperations: Array<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> = [];\n for (const operation of ops) {\n options.callbacks?.onOperationStart?.(operation);\n try {\n // Idempotency probe: only run if both postchecks and idempotency checks are enabled\n if (runPostchecks && runIdempotency) {\n const postcheckAlreadySatisfied = await this.expectationsAreSatisfied(\n driver,\n operation.postcheck,\n );\n if (postcheckAlreadySatisfied) {\n executedOperations.push(this.createPostcheckPreSatisfiedSkipRecord(operation));\n continue;\n }\n }\n\n // Prechecks: only run if enabled\n if (runPrechecks) {\n const precheckResult = await this.runExpectationSteps(\n driver,\n operation.precheck,\n operation,\n 'precheck',\n );\n if (!precheckResult.ok) {\n return precheckResult;\n }\n }\n\n const executeResult = await this.runExecuteSteps(driver, operation.execute, operation);\n if (!executeResult.ok) {\n return executeResult;\n }\n\n // Postchecks: only run if enabled\n if (runPostchecks) {\n const postcheckResult = await this.runExpectationSteps(\n driver,\n operation.postcheck,\n operation,\n 'postcheck',\n );\n if (!postcheckResult.ok) {\n return postcheckResult;\n }\n }\n\n executedOperations.push(operation);\n operationsExecuted += 1;\n } finally {\n options.callbacks?.onOperationComplete?.(operation);\n }\n }\n return ok({ operationsExecuted, executedOperations });\n }\n\n private async ensureControlTables(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n contract: Contract<SqlStorage>,\n ): Promise<Result<void, SqlMigrationRunnerFailure>> {\n const lowererContext = { contract };\n const bootstrapQueries = this.family.bootstrapControlTableQueries();\n const [schemaQuery, ...tableQueries] = bootstrapQueries;\n if (schemaQuery === undefined) {\n throw new Error('Postgres control-table bootstrap must include CREATE SCHEMA');\n }\n await this.executeStatement(driver, await this.family.lowerAst(schemaQuery, lowererContext));\n const legacyDetection = await this.detectLegacyMarkerShape(driver);\n if (!legacyDetection.ok) {\n return legacyDetection;\n }\n for (const query of tableQueries) {\n await this.executeStatement(driver, await this.family.lowerAst(query, lowererContext));\n }\n return okVoid();\n }\n\n private async detectLegacyMarkerShape(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n ): Promise<Result<void, SqlMigrationRunnerFailure>> {\n const result = await driver.query<{ column_name: string }>(\n `select column_name\n from information_schema.columns\n where table_schema = 'prisma_contract'\n and table_name = 'marker'`,\n );\n if (result.rows.length === 0) {\n return okVoid();\n }\n const columns = new Set(result.rows.map((row) => row.column_name));\n if (columns.has('space')) {\n return okVoid();\n }\n return runnerFailure(\n 'LEGACY_MARKER_SHAPE',\n 'Legacy marker-table shape detected on prisma_contract.marker (no `space` column). ' +\n 'Prisma Next is in pre-1.0; the previous transitional auto-migration to the per-space-row schema has been removed. ' +\n 'Drop `prisma_contract.marker` and re-run `dbInit` to reinitialise from a clean baseline.',\n {\n meta: {\n table: 'prisma_contract.marker',\n columns: [...columns].sort(),\n },\n },\n );\n }\n\n private async runExpectationSteps(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n steps: readonly SqlMigrationPlanOperationStep[],\n operation: SqlMigrationPlanOperation<PostgresPlanTargetDetails>,\n phase: 'precheck' | 'postcheck',\n ): Promise<Result<void, SqlMigrationRunnerFailure>> {\n for (const step of steps) {\n const result = await driver.query(step.sql, step.params ?? []);\n if (!this.stepResultIsTrue(result.rows)) {\n const code = phase === 'precheck' ? 'PRECHECK_FAILED' : 'POSTCHECK_FAILED';\n return runnerFailure(\n code,\n `Operation ${operation.id} failed during ${phase}: ${step.description}`,\n {\n meta: {\n operationId: operation.id,\n phase,\n stepDescription: step.description,\n },\n },\n );\n }\n }\n return okVoid();\n }\n\n private async runExecuteSteps(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n steps: readonly SqlMigrationPlanOperationStep[],\n operation: SqlMigrationPlanOperation<PostgresPlanTargetDetails>,\n ): Promise<Result<void, SqlMigrationRunnerFailure>> {\n for (const step of steps) {\n try {\n await driver.query(step.sql, step.params ?? []);\n } catch (error: unknown) {\n if (SqlQueryError.is(error)) {\n return runnerFailure(\n 'EXECUTION_FAILED',\n `Operation ${operation.id} failed during execution: ${step.description}`,\n {\n why: error.message,\n meta: {\n operationId: operation.id,\n stepDescription: step.description,\n sql: step.sql,\n sqlState: error.sqlState,\n constraint: error.constraint,\n table: error.table,\n column: error.column,\n detail: error.detail,\n },\n },\n );\n }\n throw error;\n }\n }\n return okVoid();\n }\n\n private stepResultIsTrue(rows: readonly Record<string, unknown>[]): boolean {\n if (!rows || rows.length === 0) {\n return false;\n }\n const firstRow = rows[0];\n const firstValue = firstRow ? Object.values(firstRow)[0] : undefined;\n if (typeof firstValue === 'boolean') {\n return firstValue;\n }\n if (typeof firstValue === 'number') {\n return firstValue !== 0;\n }\n if (typeof firstValue === 'string') {\n const lower = firstValue.toLowerCase();\n // PostgreSQL boolean representations: 't'/'f', 'true'/'false', '1'/'0'\n if (lower === 't' || lower === 'true' || lower === '1') {\n return true;\n }\n if (lower === 'f' || lower === 'false' || lower === '0') {\n return false;\n }\n // For other strings, non-empty is truthy (though this case shouldn't occur for boolean checks)\n return firstValue.length > 0;\n }\n return Boolean(firstValue);\n }\n\n private async expectationsAreSatisfied(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n steps: readonly SqlMigrationPlanOperationStep[],\n ): Promise<boolean> {\n if (steps.length === 0) {\n return false;\n }\n for (const step of steps) {\n const result = await driver.query(step.sql, step.params ?? []);\n if (!this.stepResultIsTrue(result.rows)) {\n return false;\n }\n }\n return true;\n }\n\n private createPostcheckPreSatisfiedSkipRecord(\n operation: SqlMigrationPlanOperation<PostgresPlanTargetDetails>,\n ): SqlMigrationPlanOperation<PostgresPlanTargetDetails> {\n // Clone and freeze existing meta if present\n const clonedMeta = operation.meta ? cloneAndFreezeRecord(operation.meta) : undefined;\n\n // Create frozen runner metadata\n const runnerMeta = Object.freeze({\n skipped: true,\n reason: 'postcheck_pre_satisfied',\n });\n\n // Merge and freeze the combined meta\n const mergedMeta = Object.freeze({\n ...(clonedMeta ?? {}),\n runner: runnerMeta,\n });\n\n // Clone and freeze arrays to prevent mutation\n const frozenPostcheck = Object.freeze([...operation.postcheck]);\n\n return Object.freeze({\n id: operation.id,\n label: operation.label,\n ...ifDefined('summary', operation.summary),\n operationClass: operation.operationClass,\n target: operation.target, // Already frozen from plan creation\n precheck: Object.freeze([]),\n execute: Object.freeze([]),\n postcheck: frozenPostcheck,\n ...ifDefined('meta', operation.meta || mergedMeta ? mergedMeta : undefined),\n });\n }\n\n private markerMatchesDestination(\n marker: ContractMarkerRecord | null,\n plan: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['plan'],\n ): boolean {\n if (!marker) {\n return false;\n }\n if (marker.storageHash !== plan.destination.storageHash) {\n return false;\n }\n if (plan.destination.profileHash && marker.profileHash !== plan.destination.profileHash) {\n return false;\n }\n return true;\n }\n\n private enforcePolicyCompatibility(\n policy: MigrationOperationPolicy,\n operations: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[],\n ): Result<void, SqlMigrationRunnerFailure> {\n const allowedClasses = new Set(policy.allowedOperationClasses);\n for (const operation of operations) {\n if (!allowedClasses.has(operation.operationClass)) {\n return runnerFailure(\n 'POLICY_VIOLATION',\n `Operation ${operation.id} has class \"${operation.operationClass}\" which is not allowed by policy.`,\n {\n why: `Policy only allows: ${policy.allowedOperationClasses.join(', ')}.`,\n meta: {\n operationId: operation.id,\n operationClass: operation.operationClass,\n allowedClasses: policy.allowedOperationClasses,\n },\n },\n );\n }\n }\n return okVoid();\n }\n\n private ensureMarkerCompatibility(\n marker: ContractMarkerRecord | null,\n plan: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['plan'],\n ): Result<void, SqlMigrationRunnerFailure> {\n const origin = plan.origin ?? null;\n if (!origin) {\n // No origin assertion on the plan — the caller does not want origin validation.\n // This is the case for `db update`, which introspects the live schema and does not\n // rely on marker continuity. `db init` handles its own marker checks before the runner.\n return okVoid();\n }\n\n if (!marker) {\n return runnerFailure(\n 'MARKER_ORIGIN_MISMATCH',\n `Missing contract marker: expected origin storage hash ${origin.storageHash}.`,\n {\n meta: {\n expectedOriginStorageHash: origin.storageHash,\n },\n },\n );\n }\n if (marker.storageHash !== origin.storageHash) {\n return runnerFailure(\n 'MARKER_ORIGIN_MISMATCH',\n `Existing contract marker (${marker.storageHash}) does not match plan origin (${origin.storageHash}).`,\n {\n meta: {\n markerStorageHash: marker.storageHash,\n expectedOriginStorageHash: origin.storageHash,\n },\n },\n );\n }\n if (origin.profileHash && marker.profileHash !== origin.profileHash) {\n return runnerFailure(\n 'MARKER_ORIGIN_MISMATCH',\n `Existing contract marker profile hash (${marker.profileHash}) does not match plan origin profile hash (${origin.profileHash}).`,\n {\n meta: {\n markerProfileHash: marker.profileHash,\n expectedOriginProfileHash: origin.profileHash,\n },\n },\n );\n }\n return okVoid();\n }\n\n private ensurePlanMatchesDestinationContract(\n destination: SqlMigrationPlanContractInfo,\n contract: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['destinationContract'],\n ): Result<void, SqlMigrationRunnerFailure> {\n if (destination.storageHash !== contract.storage.storageHash) {\n return runnerFailure(\n 'DESTINATION_CONTRACT_MISMATCH',\n `Plan destination storage hash (${destination.storageHash}) does not match provided contract storage hash (${contract.storage.storageHash}).`,\n {\n meta: {\n planStorageHash: destination.storageHash,\n contractStorageHash: contract.storage.storageHash,\n },\n },\n );\n }\n if (\n destination.profileHash &&\n contract.profileHash &&\n destination.profileHash !== contract.profileHash\n ) {\n return runnerFailure(\n 'DESTINATION_CONTRACT_MISMATCH',\n `Plan destination profile hash (${destination.profileHash}) does not match provided contract profile hash (${contract.profileHash}).`,\n {\n meta: {\n planProfileHash: destination.profileHash,\n contractProfileHash: contract.profileHash,\n },\n },\n );\n }\n return okVoid();\n }\n\n private async upsertMarker(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n options: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,\n existingMarker: ContractMarkerRecord | null,\n space: string,\n ): Promise<Result<void, SqlMigrationRunnerFailure>> {\n const destination = {\n storageHash: options.plan.destination.storageHash,\n profileHash:\n options.plan.destination.profileHash ??\n options.destinationContract.profileHash ??\n options.plan.destination.storageHash,\n invariants: options.plan.providedInvariants ?? [],\n };\n if (!existingMarker) {\n await this.family.initMarker({ driver, space, destination });\n return okVoid();\n }\n const updated = await this.family.updateMarker({\n driver,\n space,\n expectedFrom: existingMarker.storageHash,\n destination,\n });\n if (!updated) {\n return runnerFailure(\n 'MARKER_CAS_FAILURE',\n 'Marker was modified by another process during migration execution.',\n {\n meta: {\n space,\n expectedStorageHash: existingMarker.storageHash,\n destinationStorageHash: options.plan.destination.storageHash,\n },\n },\n );\n }\n return okVoid();\n }\n\n private async recordLedgerEntries(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n options: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,\n executedOperations: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[],\n planOpsLength: number,\n ): Promise<void> {\n const plan = options.plan;\n const space = plan.spaceId;\n const edges = options.migrationEdges;\n const totalEdgeOps = edges.reduce((sum, edge) => sum + edge.operationCount, 0);\n if (totalEdgeOps !== planOpsLength) {\n throw new Error(\n `Ledger write: plan.operations length (${planOpsLength}) does not match sum of migrationEdges operationCount (${totalEdgeOps})`,\n );\n }\n // The ledger records the operations as executed — idempotency-skipped ops\n // are substituted with skip records (empty `execute`) by `applyPlan`, so the\n // journal reflects what actually ran rather than the raw plan.\n let offset = 0;\n for (const edge of edges) {\n const edgeOps = executedOperations.slice(offset, offset + edge.operationCount);\n offset += edge.operationCount;\n await this.family.writeLedgerEntry({\n driver,\n space,\n entry: {\n edgeId: `${edge.from}->${edge.to}`,\n from: edge.from,\n to: edge.to,\n migrationName: edge.dirName,\n migrationHash: edge.migrationHash,\n operations: edgeOps,\n },\n });\n }\n }\n\n private async acquireLock(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n key: string,\n ): Promise<void> {\n await driver.query('select pg_advisory_xact_lock(hashtext($1))', [key]);\n }\n\n private async beginTransaction(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n ): Promise<void> {\n await driver.query('BEGIN');\n }\n\n private async commitTransaction(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n ): Promise<void> {\n await driver.query('COMMIT');\n }\n\n private async rollbackTransaction(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n ): Promise<void> {\n await driver.query('ROLLBACK');\n }\n\n private async executeStatement(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n statement: SqlExecuteRequest,\n ): Promise<void> {\n await driver.query(statement.sql, statement.params);\n }\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport { SqlSchemaVerifierBase } from '@prisma-next/family-sql/ir';\nimport type { SchemaIssue, SchemaVerifyOptions } from '@prisma-next/framework-components/control';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\n\n/**\n * Postgres target `SchemaVerifier` concretion. Plugs into the\n * SQL-shared verification surface; production verification today still\n * routes through the legacy `verifySqlSchema` entry point, which\n * carries options (codec hooks, normalizers, framework components)\n * that the framework-level `SchemaVerifyOptions` shape does not yet\n * surface.\n *\n * The hooks return the empty list pending the call-site migration that\n * routes the existing verifier behaviour through the SPI — at that\n * point `verifyCommonSqlSchema` will likely lift onto the family base\n * (mirroring `verifyCommonMongoSchema`) and `verifyTargetExtensions`\n * will house Postgres-only kinds (functions, RLS policies in a future\n * project).\n */\nexport class PostgresSchemaVerifier extends SqlSchemaVerifierBase<\n Contract<SqlStorage>,\n SqlSchemaIR\n> {\n protected verifyCommonSqlSchema(\n _options: SchemaVerifyOptions<Contract<SqlStorage>, SqlSchemaIR>,\n ): readonly SchemaIssue[] {\n return [];\n }\n\n protected verifyTargetExtensions(\n _options: SchemaVerifyOptions<Contract<SqlStorage>, SqlSchemaIR>,\n ): readonly SchemaIssue[] {\n return [];\n }\n}\n","import type { DefaultMappingOptions } from '@prisma-next/family-sql/psl-infer';\n\nconst POSTGRES_FUNCTION_ATTRIBUTES: Readonly<Record<string, string>> = {\n 'gen_random_uuid()': '@default(dbgenerated(\"gen_random_uuid()\"))',\n};\n\nfunction formatDbGeneratedAttribute(expression: string): string {\n return `@default(dbgenerated(${JSON.stringify(expression)}))`;\n}\n\nexport function createPostgresDefaultMapping(): DefaultMappingOptions {\n return {\n functionAttributes: POSTGRES_FUNCTION_ATTRIBUTES,\n fallbackFunctionAttribute: formatDbGeneratedAttribute,\n };\n}\n","import type {\n EnumInfo,\n PslNativeTypeAttribute,\n PslTypeMap,\n PslTypeResolution,\n} from '@prisma-next/family-sql/psl-infer';\n\nconst POSTGRES_TO_PSL: Record<string, string> = {\n text: 'String',\n bool: 'Boolean',\n boolean: 'Boolean',\n int4: 'Int',\n integer: 'Int',\n int8: 'BigInt',\n bigint: 'BigInt',\n float8: 'Float',\n 'double precision': 'Float',\n numeric: 'Decimal',\n decimal: 'Decimal',\n timestamptz: 'DateTime',\n 'timestamp with time zone': 'DateTime',\n jsonb: 'Json',\n bytea: 'Bytes',\n};\n\nconst PRESERVED_NATIVE_TYPES: Record<\n string,\n { readonly pslType: string; readonly attributeName: string }\n> = {\n 'character varying': { pslType: 'String', attributeName: 'db.VarChar' },\n character: { pslType: 'String', attributeName: 'db.Char' },\n char: { pslType: 'String', attributeName: 'db.Char' },\n varchar: { pslType: 'String', attributeName: 'db.VarChar' },\n uuid: { pslType: 'String', attributeName: 'db.Uuid' },\n int2: { pslType: 'Int', attributeName: 'db.SmallInt' },\n smallint: { pslType: 'Int', attributeName: 'db.SmallInt' },\n float4: { pslType: 'Float', attributeName: 'db.Real' },\n real: { pslType: 'Float', attributeName: 'db.Real' },\n timestamp: { pslType: 'DateTime', attributeName: 'db.Timestamp' },\n 'timestamp without time zone': { pslType: 'DateTime', attributeName: 'db.Timestamp' },\n date: { pslType: 'DateTime', attributeName: 'db.Date' },\n time: { pslType: 'DateTime', attributeName: 'db.Time' },\n 'time without time zone': { pslType: 'DateTime', attributeName: 'db.Time' },\n timetz: { pslType: 'DateTime', attributeName: 'db.Timetz' },\n 'time with time zone': { pslType: 'DateTime', attributeName: 'db.Timetz' },\n json: { pslType: 'Json', attributeName: 'db.Json' },\n};\n\nconst PARAMETERIZED_NATIVE_TYPES: Record<\n string,\n { readonly pslType: string; readonly attributeName: string }\n> = {\n 'character varying': { pslType: 'String', attributeName: 'db.VarChar' },\n character: { pslType: 'String', attributeName: 'db.Char' },\n char: { pslType: 'String', attributeName: 'db.Char' },\n varchar: { pslType: 'String', attributeName: 'db.VarChar' },\n numeric: { pslType: 'Decimal', attributeName: 'db.Numeric' },\n timestamp: { pslType: 'DateTime', attributeName: 'db.Timestamp' },\n timestamptz: { pslType: 'DateTime', attributeName: 'db.Timestamptz' },\n time: { pslType: 'DateTime', attributeName: 'db.Time' },\n timetz: { pslType: 'DateTime', attributeName: 'db.Timetz' },\n};\n\nconst PARAMETERIZED_TYPE_PATTERN = /^(.+?)\\((.+)\\)$/;\n\nfunction getOwnMappingValue(map: Record<string, string>, key: string): string | undefined {\n return Object.hasOwn(map, key) ? map[key] : undefined;\n}\n\nfunction getOwnRecordValue<T>(map: Record<string, T>, key: string): T | undefined {\n return Object.hasOwn(map, key) ? map[key] : undefined;\n}\n\nfunction createNativeTypeAttribute(name: string, args?: readonly string[]): PslNativeTypeAttribute {\n return args && args.length > 0 ? { name, args } : { name };\n}\n\nfunction splitTypeParameterList(params: string): readonly string[] {\n return params\n .split(',')\n .map((part) => part.trim())\n .filter((part) => part.length > 0);\n}\n\nexport function createPostgresTypeMap(enumTypeNames?: ReadonlySet<string>): PslTypeMap {\n return {\n resolve(nativeType: string): PslTypeResolution {\n if (enumTypeNames?.has(nativeType)) {\n return { pslType: nativeType, nativeType };\n }\n\n const paramMatch = nativeType.match(PARAMETERIZED_TYPE_PATTERN);\n if (paramMatch) {\n const [, baseType = nativeType, params = ''] = paramMatch;\n const template = getOwnRecordValue(PARAMETERIZED_NATIVE_TYPES, baseType);\n if (template) {\n return {\n pslType: template.pslType,\n nativeType,\n typeParams: { baseType, params },\n nativeTypeAttribute: createNativeTypeAttribute(\n template.attributeName,\n splitTypeParameterList(params),\n ),\n };\n }\n }\n\n const preservedType = getOwnRecordValue(PRESERVED_NATIVE_TYPES, nativeType);\n if (preservedType) {\n return {\n pslType: preservedType.pslType,\n nativeType,\n nativeTypeAttribute: createNativeTypeAttribute(preservedType.attributeName),\n };\n }\n\n const pslType = getOwnMappingValue(POSTGRES_TO_PSL, nativeType);\n if (pslType) {\n return {\n pslType,\n nativeType,\n };\n }\n\n return { unsupported: true, nativeType };\n },\n };\n}\n\nexport function extractEnumInfo(annotations?: Record<string, unknown>): EnumInfo {\n const pgAnnotations = annotations?.['pg'] as Record<string, unknown> | undefined;\n const nativeEnumTypeNames = pgAnnotations?.['nativeEnumTypeNames'];\n\n const typeNames = new Set<string>();\n const definitions = new Map<string, readonly string[]>();\n\n if (Array.isArray(nativeEnumTypeNames)) {\n for (const name of nativeEnumTypeNames) {\n if (typeof name === 'string') {\n typeNames.add(name);\n }\n }\n }\n\n return { typeNames, definitions };\n}\n\nexport function extractEnumTypeNames(annotations?: Record<string, unknown>): ReadonlySet<string> {\n return extractEnumInfo(annotations).typeNames;\n}\n\nexport function extractEnumDefinitions(\n annotations?: Record<string, unknown>,\n): ReadonlyMap<string, readonly string[]> {\n return extractEnumInfo(annotations).definitions;\n}\n","import type { ColumnDefault } from '@prisma-next/contract/types';\nimport type {\n DefaultMappingOptions,\n PslNativeTypeAttribute,\n PslPrinterOptions,\n PslTypeMap,\n RelationField,\n} from '@prisma-next/family-sql/psl-infer';\nimport {\n inferRelations,\n mapDefault,\n parseRawDefault,\n toFieldName,\n toModelName,\n toNamedTypeName,\n} from '@prisma-next/family-sql/psl-infer';\nimport type {\n PslAttribute,\n PslAttributeArgument,\n PslDocumentAst,\n PslField,\n PslFieldAttribute,\n PslModel,\n PslModelAttribute,\n PslNamedTypeDeclaration,\n PslSpan,\n PslTypesBlock,\n} from '@prisma-next/framework-components/psl-ast';\nimport {\n makePslNamespace,\n makePslNamespaceEntries,\n UNSPECIFIED_PSL_NAMESPACE_ID,\n} from '@prisma-next/framework-components/psl-ast';\nimport type { SqlColumnIR, SqlSchemaIR, SqlTableIR } from '@prisma-next/sql-schema-ir/types';\nimport type { PostgresDatabaseSchemaNode } from '../schema-ir/postgres-database-schema-node';\nimport { createPostgresDefaultMapping } from './postgres-default-mapping';\nimport { createPostgresTypeMap } from './postgres-type-map';\n\nconst SYNTHETIC_SPAN: PslSpan = {\n start: { offset: 0, line: 1, column: 1 },\n end: { offset: 0, line: 1, column: 1 },\n};\n\nconst PSL_SCALAR_TYPE_NAMES = new Set([\n 'String',\n 'Boolean',\n 'Int',\n 'BigInt',\n 'Float',\n 'Decimal',\n 'DateTime',\n 'Json',\n 'Bytes',\n]);\n\ntype ResolvedColumnFieldName = {\n readonly fieldName: string;\n readonly fieldMap?: string | undefined;\n};\n\ntype TableColumnFieldNameMap = ReadonlyMap<string, ResolvedColumnFieldName>;\n\ntype NamedTypeRegistryEntry = {\n readonly name: string;\n readonly baseType: string;\n readonly nativeTypeAttribute: PslNativeTypeAttribute;\n};\n\ntype NamedTypeRegistry = {\n readonly entriesByKey: Map<string, NamedTypeRegistryEntry>;\n readonly usedNames: Set<string>;\n};\n\ntype TopLevelNameResult = {\n readonly name: string;\n readonly map?: string | undefined;\n};\n\n/**\n * Infers a PSL AST (for `printPsl`) from an introspected Postgres schema tree.\n *\n * Target-owned inference: it walks the `PostgresDatabaseSchemaNode` tree and\n * owns the Postgres dialect knowledge — the native type map and default map.\n * Relation inference, name transforms, generic default mapping, and raw-default\n * parsing are shape-neutral utilities imported from the SQL family.\n *\n * This slice emits relational-only PSL, byte-identical to the prior flat\n * inference: the tree's tables (across its namespaces — `contract infer`\n * introspects a single live namespace) are gathered into the model set and\n * emitted as one `UNSPECIFIED_PSL_NAMESPACE_ID` bucket. Top-level entities\n * (policies/roles → PSL extension blocks) are a later slice.\n */\nexport function inferPostgresPslContract(tree: PostgresDatabaseSchemaNode): PslDocumentAst {\n const namespaces = Object.values(tree.namespaces);\n\n // Native Postgres enums (CREATE TYPE … AS ENUM) are not adoptable by\n // `contract infer`; throw an actionable diagnostic naming the type(s). Enum\n // names live on each namespace node's `nativeEnumTypeNames`.\n const enumTypeNames = [...new Set(namespaces.flatMap((ns) => ns.nativeEnumTypeNames))];\n if (enumTypeNames.length > 0) {\n const names = enumTypeNames.join(', ');\n throw new Error(\n `contract infer: the database contains native Postgres enum type(s): ${names}. ` +\n 'Native Postgres enums (CREATE TYPE … AS ENUM) are not adoptable by contract infer. ' +\n 'Drop the native type and replace each column with a text column carrying a CHECK constraint, ' +\n `then re-run contract infer. The domain enum (enum Name { @@type(\"pg/text@1\") … }) authoring ` +\n 'surface generates the required check automatically.',\n );\n }\n\n // Stopgap (TML-2958): flatten the schema-IR *tree* into the single `{ tables }`\n // map the PSL writer expects. The writer still walks a flat table map, so this\n // is a read-only projection — it does not reintroduce a stored flat schema.\n // The real fix is to extend the PSL writer to walk the namespace tree and emit\n // per-namespace `namespace { … }` blocks; until then `contract infer` handles a\n // single introspected namespace, and a same-named table in two schemas has no\n // unambiguous single-bucket model, so we throw rather than silently drop one.\n const tables: Record<string, SqlTableIR> = {};\n for (const namespace of namespaces) {\n for (const [tableName, table] of Object.entries(namespace.tables)) {\n if (tables[tableName] !== undefined) {\n throw new Error(\n `contract infer: duplicate table name \"${tableName}\" across schemas is not yet supported ` +\n '(single-namespace PSL inference emits one flat bucket; multi-namespace `namespace { … }` ' +\n 'output is a later slice).',\n );\n }\n tables[tableName] = table;\n }\n }\n const schemaIR: SqlSchemaIR = { tables };\n\n const options: PslPrinterOptions = {\n typeMap: createPostgresTypeMap(new Set()),\n defaultMapping: createPostgresDefaultMapping(),\n parseRawDefault,\n };\n\n return buildPslDocumentAst(schemaIR, options);\n}\n\nfunction buildPslDocumentAst(schemaIR: SqlSchemaIR, options: PslPrinterOptions): PslDocumentAst {\n const { typeMap, defaultMapping, parseRawDefault: rawDefaultParser } = options;\n\n const modelNames = buildTopLevelNameMap(\n Object.keys(schemaIR.tables),\n toModelName,\n 'model',\n 'table',\n );\n\n const modelNameMap = new Map(\n [...modelNames].map(([tableName, result]) => [tableName, result.name]),\n );\n const reservedNamedTypeNames = createReservedNamedTypeNames(modelNames);\n\n const fieldNamesByTable = buildFieldNamesByTable(schemaIR.tables);\n const { relationsByTable } = inferRelations(schemaIR.tables, modelNameMap);\n const namedTypes = seedNamedTypeRegistry(schemaIR, typeMap, new Map(), reservedNamedTypeNames);\n\n const models: PslModel[] = [];\n for (const table of Object.values(schemaIR.tables)) {\n models.push(\n buildModel(\n table,\n typeMap,\n new Map(),\n fieldNamesByTable,\n namedTypes,\n defaultMapping,\n rawDefaultParser,\n relationsByTable.get(table.name) ?? [],\n ),\n );\n }\n\n const sortedModels = topologicalSort(models, schemaIR.tables, modelNameMap);\n\n const namedTypeEntries = [...namedTypes.entriesByKey.values()].sort((a, b) =>\n a.name.localeCompare(b.name),\n );\n const types: PslTypesBlock | undefined =\n namedTypeEntries.length > 0\n ? {\n kind: 'types',\n declarations: namedTypeEntries.map(buildNamedTypeDeclaration),\n span: SYNTHETIC_SPAN,\n }\n : undefined;\n\n // Inferred PSL nodes will eventually be routed into per-namespace buckets\n // matching the source storage; for now we synthesise a single\n // `__unspecified__` bucket so round-tripping the AST through the framework\n // printer (which emits the synthesised bucket at top level with no\n // `namespace { … }` wrapper) preserves the existing introspection output\n // verbatim.\n const ast: PslDocumentAst = {\n kind: 'document',\n sourceId: '<sql-schema-ir>',\n namespaces: [\n makePslNamespace({\n kind: 'namespace',\n name: UNSPECIFIED_PSL_NAMESPACE_ID,\n entries: makePslNamespaceEntries(sortedModels, [], []),\n span: SYNTHETIC_SPAN,\n }),\n ],\n ...(types ? { types } : {}),\n span: SYNTHETIC_SPAN,\n };\n\n return ast;\n}\n\nfunction buildModel(\n table: SqlTableIR,\n typeMap: PslTypeMap,\n enumNameMap: ReadonlyMap<string, string>,\n fieldNamesByTable: ReadonlyMap<string, TableColumnFieldNameMap>,\n namedTypes: NamedTypeRegistry,\n defaultMapping: DefaultMappingOptions | undefined,\n rawDefaultParser: PslPrinterOptions['parseRawDefault'],\n relationFields: readonly RelationField[],\n): PslModel {\n const { name: modelName, map: mapName } = toModelName(table.name);\n const fieldNameMap = fieldNamesByTable.get(table.name);\n\n const pkColumns = new Set(table.primaryKey?.columns ?? []);\n const isSinglePk = pkColumns.size === 1;\n const singlePkConstraintName = isSinglePk ? table.primaryKey?.name : undefined;\n\n const uniqueColumns = new Map<string, string | undefined>();\n for (const unique of table.uniques) {\n if (unique.columns.length === 1) {\n const [columnName = ''] = unique.columns;\n const existingConstraintName = uniqueColumns.get(columnName);\n if (!uniqueColumns.has(columnName) || (existingConstraintName === undefined && unique.name)) {\n uniqueColumns.set(columnName, unique.name);\n }\n }\n }\n\n const fields: PslField[] = [];\n for (const column of Object.values(table.columns)) {\n fields.push(\n buildScalarField(\n column,\n table,\n typeMap,\n enumNameMap,\n fieldNameMap,\n namedTypes,\n defaultMapping,\n rawDefaultParser,\n pkColumns,\n isSinglePk,\n singlePkConstraintName,\n uniqueColumns,\n ),\n );\n }\n\n const usedFieldNames = new Set(fields.map((field) => field.name));\n for (const rel of relationFields) {\n fields.push(buildRelationField(rel, table.name, fieldNamesByTable, usedFieldNames));\n }\n\n const modelAttributes: PslModelAttribute[] = [];\n\n if (table.primaryKey && table.primaryKey.columns.length > 1) {\n const pkFieldNames = table.primaryKey.columns.map((columnName) =>\n resolveColumnFieldName(fieldNamesByTable, table.name, columnName),\n );\n modelAttributes.push(buildModelConstraintAttribute('id', pkFieldNames, table.primaryKey.name));\n }\n\n for (const unique of table.uniques) {\n if (unique.columns.length > 1) {\n const uniqueFieldNames = unique.columns.map((columnName) =>\n resolveColumnFieldName(fieldNamesByTable, table.name, columnName),\n );\n modelAttributes.push(buildModelConstraintAttribute('unique', uniqueFieldNames, unique.name));\n }\n }\n\n for (const index of table.indexes) {\n if (!index.unique) {\n const indexFieldNames = index.columns.map((columnName) =>\n resolveColumnFieldName(fieldNamesByTable, table.name, columnName),\n );\n modelAttributes.push(buildModelConstraintAttribute('index', indexFieldNames, index.name));\n }\n }\n\n if (mapName) {\n modelAttributes.push(buildMapAttribute('model', mapName));\n }\n\n // Surface introspection advisory: tables without a primary key cannot serve\n // as the right-hand side of a `findUnique`-style query downstream, so the\n // user should add an `@id`. This warning is part of the emitted SQL output\n // and is asserted byte-for-byte, so keep the exact wording.\n const comment = table.primaryKey\n ? undefined\n : '// WARNING: This table has no primary key in the database';\n\n return {\n kind: 'model',\n name: modelName,\n fields,\n attributes: modelAttributes,\n span: SYNTHETIC_SPAN,\n ...(comment !== undefined ? { comment } : {}),\n };\n}\n\nfunction buildScalarField(\n column: SqlColumnIR,\n table: SqlTableIR,\n typeMap: PslTypeMap,\n enumNameMap: ReadonlyMap<string, string>,\n fieldNameMap: TableColumnFieldNameMap | undefined,\n namedTypes: NamedTypeRegistry,\n defaultMapping: DefaultMappingOptions | undefined,\n rawDefaultParser: PslPrinterOptions['parseRawDefault'],\n pkColumns: ReadonlySet<string>,\n isSinglePk: boolean,\n singlePkConstraintName: string | undefined,\n uniqueColumns: ReadonlyMap<string, string | undefined>,\n): PslField {\n const resolvedField = fieldNameMap?.get(column.name);\n const fieldName = resolvedField?.fieldName ?? toFieldName(column.name).name;\n const fieldMap = resolvedField?.fieldMap;\n\n const resolution = typeMap.resolve(column.nativeType, table.annotations);\n\n if ('unsupported' in resolution) {\n const attrs: PslFieldAttribute[] = [];\n if (fieldMap !== undefined) {\n attrs.push(buildMapAttribute('field', fieldMap));\n }\n return {\n kind: 'field',\n name: fieldName,\n typeName: `Unsupported(\"${escapePslString(resolution.nativeType)}\")`,\n optional: column.nullable,\n list: column.many === true,\n attributes: attrs,\n span: SYNTHETIC_SPAN,\n };\n }\n\n let typeName = resolution.pslType;\n const enumPslName = enumNameMap.get(column.nativeType);\n if (enumPslName) {\n typeName = enumPslName;\n }\n if (resolution.nativeTypeAttribute && !enumPslName) {\n typeName = resolveNamedTypeName(namedTypes, resolution);\n }\n\n const attributes: PslFieldAttribute[] = [];\n const isId = isSinglePk && pkColumns.has(column.name);\n if (isId) {\n attributes.push(buildSimpleConstraintFieldAttribute('id', singlePkConstraintName));\n }\n\n if (column.default !== undefined) {\n const parsed = parseColumnDefault(column.default, column.nativeType, rawDefaultParser);\n if (parsed) {\n const result = mapDefault(parsed, defaultMapping);\n if ('attribute' in result) {\n attributes.push(parseDefaultAttributeString(result.attribute));\n }\n // 'comment' fallback (unrecognized raw default) is dropped — the\n // M1 legacy path emitted a `// Raw default: ...` line above the field via\n // `PrinterField.comment`. M2 drops this since it would require comment\n // nodes in the AST.\n }\n }\n\n if (uniqueColumns.has(column.name) && !isId) {\n const uniqueConstraintName = uniqueColumns.get(column.name);\n attributes.push(buildSimpleConstraintFieldAttribute('unique', uniqueConstraintName));\n }\n\n if (fieldMap !== undefined) {\n attributes.push(buildMapAttribute('field', fieldMap));\n }\n\n return {\n kind: 'field',\n name: fieldName,\n typeName,\n optional: column.nullable,\n list: column.many === true,\n attributes,\n span: SYNTHETIC_SPAN,\n };\n}\n\nfunction buildRelationField(\n rel: RelationField,\n hostTableName: string,\n fieldNamesByTable: ReadonlyMap<string, TableColumnFieldNameMap>,\n usedFieldNames: Set<string>,\n): PslField {\n const fieldName = createUniqueFieldName(rel.fieldName, usedFieldNames);\n usedFieldNames.add(fieldName);\n\n const args: PslAttributeArgument[] = [];\n\n if (rel.fields && rel.references) {\n if (rel.relationName) {\n args.push(namedArg('name', `\"${escapePslString(rel.relationName)}\"`));\n }\n args.push(\n namedArg(\n 'fields',\n `[${rel.fields\n .map((columnName) => resolveColumnFieldName(fieldNamesByTable, hostTableName, columnName))\n .join(', ')}]`,\n ),\n );\n args.push(\n namedArg(\n 'references',\n `[${rel.references\n .map((columnName) =>\n resolveColumnFieldName(fieldNamesByTable, rel.referencedTableName ?? '', columnName),\n )\n .join(', ')}]`,\n ),\n );\n if (rel.onDelete) {\n args.push(namedArg('onDelete', rel.onDelete));\n }\n if (rel.onUpdate) {\n args.push(namedArg('onUpdate', rel.onUpdate));\n }\n if (rel.fkName) {\n args.push(namedArg('map', `\"${escapePslString(rel.fkName)}\"`));\n }\n } else if (rel.relationName) {\n args.push(namedArg('name', `\"${escapePslString(rel.relationName)}\"`));\n }\n\n const attrs: PslFieldAttribute[] =\n args.length > 0 ? [buildAttribute('field', 'relation', args)] : [];\n\n return {\n kind: 'field',\n name: fieldName,\n typeName: rel.typeName,\n optional: rel.optional,\n list: rel.list,\n attributes: attrs,\n span: SYNTHETIC_SPAN,\n };\n}\n\nfunction buildModelConstraintAttribute(\n name: 'id' | 'unique' | 'index',\n fields: readonly string[],\n constraintName?: string,\n): PslModelAttribute {\n const args: PslAttributeArgument[] = [positionalArg(`[${fields.join(', ')}]`)];\n if (constraintName !== undefined) {\n args.push(namedArg('map', `\"${escapePslString(constraintName)}\"`));\n }\n return buildAttribute('model', name, args);\n}\n\nfunction buildSimpleConstraintFieldAttribute(\n name: 'id' | 'unique',\n constraintName: string | undefined,\n): PslFieldAttribute {\n if (constraintName === undefined) {\n return buildAttribute('field', name, []);\n }\n return buildAttribute('field', name, [namedArg('map', `\"${escapePslString(constraintName)}\"`)]);\n}\n\nfunction parseDefaultAttributeString(attributeText: string): PslFieldAttribute {\n // Strip leading \"@default(\" and trailing \")\" — `mapDefault` always returns one\n // top-level positional expression.\n const inner = attributeText.replace(/^@default\\(/, '').replace(/\\)$/, '');\n return buildAttribute('field', 'default', [positionalArg(inner)]);\n}\n\nfunction buildMapAttribute(target: 'model' | 'field' | 'enum', mapName: string): PslAttribute {\n return buildAttribute(target, 'map', [positionalArg(`\"${escapePslString(mapName)}\"`)]);\n}\n\nfunction buildAttribute(\n target: PslAttribute['target'],\n name: string,\n args: readonly PslAttributeArgument[],\n): PslAttribute {\n return {\n kind: 'attribute',\n target,\n name,\n args,\n span: SYNTHETIC_SPAN,\n };\n}\n\nfunction positionalArg(value: string): PslAttributeArgument {\n return { kind: 'positional', value, span: SYNTHETIC_SPAN };\n}\n\nfunction namedArg(name: string, value: string): PslAttributeArgument {\n return { kind: 'named', name, value, span: SYNTHETIC_SPAN };\n}\n\nfunction buildNamedTypeDeclaration(entry: NamedTypeRegistryEntry): PslNamedTypeDeclaration {\n const attribute = buildAttribute(\n 'namedType',\n entry.nativeTypeAttribute.name,\n (entry.nativeTypeAttribute.args ?? []).map(positionalArg),\n );\n return {\n kind: 'namedType',\n name: entry.name,\n baseType: entry.baseType,\n attributes: [attribute],\n span: SYNTHETIC_SPAN,\n };\n}\n\nfunction escapePslString(value: string): string {\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r');\n}\n\n/**\n * Resolves a `SqlColumnIR.default` value into a normalized {@link ColumnDefault}.\n *\n * `SqlSchemaIR` types the column default as `string` (a raw database default\n * expression). Some legacy fixtures and tests still pass already-normalized\n * `ColumnDefault` objects in the same slot, so we accept either shape\n * defensively at runtime.\n */\nfunction parseColumnDefault(\n value: unknown,\n nativeType: string | undefined,\n rawDefaultParser: PslPrinterOptions['parseRawDefault'],\n): ColumnDefault | undefined {\n if (typeof value === 'string') {\n return rawDefaultParser ? rawDefaultParser(value, nativeType) : undefined;\n }\n if (value !== null && typeof value === 'object' && 'kind' in (value as Record<string, unknown>)) {\n return value as ColumnDefault;\n }\n return undefined;\n}\n\nfunction buildFieldNamesByTable(\n tables: Record<string, SqlTableIR>,\n): ReadonlyMap<string, TableColumnFieldNameMap> {\n const fieldNamesByTable = new Map<string, TableColumnFieldNameMap>();\n\n for (const table of Object.values(tables)) {\n const columns = Object.values(table.columns).map((column, index) => {\n const { name, map } = toFieldName(column.name);\n return {\n columnName: column.name,\n desiredFieldName: name,\n fieldMap: map,\n index,\n };\n });\n\n const assignmentOrder = [...columns].sort((left, right) => {\n const mapComparison =\n Number(left.fieldMap !== undefined) - Number(right.fieldMap !== undefined);\n if (mapComparison !== 0) {\n return mapComparison;\n }\n return left.index - right.index;\n });\n\n const usedFieldNames = new Set<string>();\n const tableFieldNames = new Map<string, ResolvedColumnFieldName>();\n\n for (const column of assignmentOrder) {\n const fieldName = createUniqueFieldName(column.desiredFieldName, usedFieldNames);\n usedFieldNames.add(fieldName);\n tableFieldNames.set(column.columnName, {\n fieldName,\n fieldMap: column.fieldMap,\n });\n }\n\n fieldNamesByTable.set(table.name, tableFieldNames);\n }\n\n return fieldNamesByTable;\n}\n\nfunction resolveColumnFieldName(\n fieldNamesByTable: ReadonlyMap<string, TableColumnFieldNameMap>,\n tableName: string,\n columnName: string,\n): string {\n return (\n fieldNamesByTable.get(tableName)?.get(columnName)?.fieldName ?? toFieldName(columnName).name\n );\n}\n\nfunction createUniqueFieldName(desiredName: string, usedFieldNames: ReadonlySet<string>): string {\n if (!usedFieldNames.has(desiredName)) {\n return desiredName;\n }\n\n let counter = 2;\n while (usedFieldNames.has(`${desiredName}${counter}`)) {\n counter++;\n }\n return `${desiredName}${counter}`;\n}\n\nfunction buildTopLevelNameMap(\n sources: Iterable<string>,\n normalize: (source: string) => TopLevelNameResult,\n kind: 'model' | 'enum',\n sourceKind: 'table' | 'enum type',\n): Map<string, TopLevelNameResult> {\n const results = new Map<string, TopLevelNameResult>();\n const normalizedToSources = new Map<string, string[]>();\n\n for (const source of sources) {\n const normalized = normalize(source);\n results.set(source, normalized);\n normalizedToSources.set(normalized.name, [\n ...(normalizedToSources.get(normalized.name) ?? []),\n source,\n ]);\n }\n\n const duplicates = [...normalizedToSources.entries()].filter(\n ([, conflictingSources]) => conflictingSources.length > 1,\n );\n if (duplicates.length > 0) {\n const details = duplicates.map(\n ([normalizedName, conflictingSources]) =>\n `- ${kind} \"${normalizedName}\" from ${sourceKind}s ${conflictingSources\n .map((source) => `\"${source}\"`)\n .join(', ')}`,\n );\n throw new Error(`PSL ${kind} name collisions detected:\\n${details.join('\\n')}`);\n }\n\n return results;\n}\n\nfunction createReservedNamedTypeNames(\n modelNames: ReadonlyMap<string, TopLevelNameResult>,\n): Set<string> {\n const reservedNames = new Set<string>(PSL_SCALAR_TYPE_NAMES);\n\n for (const result of modelNames.values()) {\n reservedNames.add(result.name);\n }\n\n return reservedNames;\n}\n\nfunction seedNamedTypeRegistry(\n schemaIR: SqlSchemaIR,\n typeMap: PslTypeMap,\n enumNameMap: ReadonlyMap<string, string>,\n reservedNames: ReadonlySet<string>,\n): NamedTypeRegistry {\n type Seed = {\n readonly baseType: string;\n readonly desiredName: string;\n readonly nativeTypeAttribute: PslNativeTypeAttribute;\n };\n\n const seeds = new Map<string, Seed>();\n\n for (const tableName of Object.keys(schemaIR.tables).sort()) {\n const table = schemaIR.tables[tableName];\n if (!table) {\n continue;\n }\n\n for (const columnName of Object.keys(table.columns).sort()) {\n const column = table.columns[columnName];\n if (!column) {\n continue;\n }\n\n const resolution = typeMap.resolve(column.nativeType, table.annotations);\n if (\n 'unsupported' in resolution ||\n enumNameMap.has(column.nativeType) ||\n !resolution.nativeTypeAttribute\n ) {\n continue;\n }\n\n const signatureKey = createNamedTypeSignatureKey(resolution);\n if (!seeds.has(signatureKey)) {\n seeds.set(signatureKey, {\n baseType: resolution.pslType,\n desiredName: toNamedTypeName(column.name),\n nativeTypeAttribute: resolution.nativeTypeAttribute,\n });\n }\n }\n }\n\n const registry: NamedTypeRegistry = {\n entriesByKey: new Map<string, NamedTypeRegistryEntry>(),\n usedNames: new Set<string>(reservedNames),\n };\n\n const sortedSeeds = [...seeds.entries()].sort((left, right) => {\n const desiredNameComparison = left[1].desiredName.localeCompare(right[1].desiredName);\n if (desiredNameComparison !== 0) {\n return desiredNameComparison;\n }\n return left[0].localeCompare(right[0]);\n });\n\n for (const [signatureKey, seed] of sortedSeeds) {\n const name = createUniqueFieldName(seed.desiredName, registry.usedNames);\n registry.entriesByKey.set(signatureKey, {\n name,\n baseType: seed.baseType,\n nativeTypeAttribute: seed.nativeTypeAttribute,\n });\n registry.usedNames.add(name);\n }\n\n return registry;\n}\n\nfunction resolveNamedTypeName(\n registry: NamedTypeRegistry,\n resolution: {\n readonly pslType: string;\n readonly nativeType: string;\n readonly typeParams?: Record<string, unknown>;\n readonly nativeTypeAttribute?: PslNativeTypeAttribute;\n },\n): string {\n const key = createNamedTypeSignatureKey(resolution);\n const existing = registry.entriesByKey.get(key);\n if (existing) {\n return existing.name;\n }\n\n throw new Error(`Named type registry was not seeded for native type \"${resolution.nativeType}\"`);\n}\n\nfunction createNamedTypeSignatureKey(resolution: {\n readonly pslType: string;\n readonly nativeType: string;\n readonly typeParams?: Record<string, unknown>;\n readonly nativeTypeAttribute?: PslNativeTypeAttribute;\n}): string {\n return JSON.stringify({\n baseType: resolution.pslType,\n nativeTypeAttribute: resolution.nativeTypeAttribute\n ? {\n name: resolution.nativeTypeAttribute.name,\n args: resolution.nativeTypeAttribute.args ?? null,\n }\n : null,\n });\n}\n\nfunction topologicalSort(\n models: PslModel[],\n tables: Record<string, SqlTableIR>,\n modelNameMap: ReadonlyMap<string, string>,\n): PslModel[] {\n const modelByName = new Map<string, PslModel>();\n for (const model of models) {\n modelByName.set(model.name, model);\n }\n\n const deps = new Map<string, Set<string>>();\n const tableToModel = new Map<string, string>();\n for (const tableName of Object.keys(tables)) {\n const modelName = modelNameMap.get(tableName) as string;\n tableToModel.set(tableName, modelName);\n deps.set(modelName, new Set());\n }\n\n for (const [tableName, table] of Object.entries(tables)) {\n const modelName = tableToModel.get(tableName) as string;\n for (const fk of table.foreignKeys) {\n const refModelName = tableToModel.get(fk.referencedTable);\n if (refModelName && refModelName !== modelName) {\n (deps.get(modelName) as Set<string>).add(refModelName);\n }\n }\n }\n\n const result: PslModel[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n\n const sortedNames = [...deps.keys()].sort();\n\n function visit(name: string): void {\n if (visited.has(name)) return;\n if (visiting.has(name)) return;\n visiting.add(name);\n\n const sortedDeps = [...(deps.get(name) as Set<string>)].sort();\n for (const dep of sortedDeps) {\n visit(dep);\n }\n\n visiting.delete(name);\n visited.add(name);\n result.push(modelByName.get(name) as PslModel);\n }\n\n for (const name of sortedNames) {\n visit(name);\n }\n\n return result;\n}\n","import type { ColumnDefault } from '@prisma-next/contract/types';\nimport type { SqlControlTargetDescriptor } from '@prisma-next/family-sql/control';\nimport { extractCodecControlHooks } from '@prisma-next/family-sql/control';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlTargetInstance,\n MigrationRunner,\n} from '@prisma-next/framework-components/control';\nimport type { StorageColumn } from '@prisma-next/sql-contract/types';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { postgresTargetDescriptorMeta } from '../core/descriptor-meta';\nimport { contractToPostgresDatabaseSchemaNode } from '../core/migrations/contract-to-postgres-database-schema-node';\nimport {\n diffPostgresDatabaseSchema,\n verifyPostgresDatabaseSchema,\n} from '../core/migrations/diff-database-schema';\nimport { createPostgresMigrationPlanner } from '../core/migrations/planner';\nimport { renderDefaultLiteral } from '../core/migrations/planner-ddl-builders';\nimport type { PostgresPlanTargetDetails } from '../core/migrations/planner-target-details';\nimport { createPostgresMigrationRunner } from '../core/migrations/runner';\nimport { PostgresContractSerializer } from '../core/postgres-contract-serializer';\nimport type { PostgresContract } from '../core/postgres-schema';\nimport { PostgresSchemaVerifier } from '../core/postgres-schema-verifier';\nimport { inferPostgresPslContract } from '../core/psl-infer/infer-psl-contract';\nimport { PostgresDatabaseSchemaNode } from '../core/schema-ir/postgres-database-schema-node';\n\nfunction buildNativeTypeExpander(\n frameworkComponents?: ReadonlyArray<TargetBoundComponentDescriptor<'sql', 'postgres'>>,\n) {\n if (!frameworkComponents) {\n return undefined;\n }\n const codecHooks = extractCodecControlHooks(frameworkComponents);\n return (input: {\n readonly nativeType: string;\n readonly codecId?: string;\n readonly typeParams?: Record<string, unknown>;\n }) => {\n if (!input.typeParams) return input.nativeType;\n if (!input.codecId) return input.nativeType;\n const hooks = codecHooks.get(input.codecId);\n if (!hooks?.expandNativeType) return input.nativeType;\n return hooks.expandNativeType(input);\n };\n}\n\nexport function postgresRenderDefault(def: ColumnDefault, column: StorageColumn): string {\n if (def.kind === 'function') {\n return def.expression;\n }\n return renderDefaultLiteral(def.value, column);\n}\n\nconst postgresTargetDescriptor: SqlControlTargetDescriptor<'postgres', PostgresPlanTargetDetails> =\n {\n ...postgresTargetDescriptorMeta,\n contractSerializer: new PostgresContractSerializer(),\n schemaVerifier: new PostgresSchemaVerifier(),\n inferPslContract(schema) {\n PostgresDatabaseSchemaNode.assert(schema);\n return inferPostgresPslContract(schema);\n },\n diffDatabaseSchema(input) {\n return diffPostgresDatabaseSchema({\n contract: input.contract,\n actualSchema: input.schema,\n strict: input.strict,\n typeMetadataRegistry: input.typeMetadataRegistry,\n frameworkComponents: input.frameworkComponents,\n });\n },\n verifyDatabaseSchema(input) {\n return verifyPostgresDatabaseSchema({\n contract: input.contract,\n actualSchema: input.schema,\n strict: input.strict,\n typeMetadataRegistry: input.typeMetadataRegistry,\n frameworkComponents: input.frameworkComponents,\n });\n },\n migrations: {\n createPlanner(adapter: SqlControlAdapter<'postgres'>) {\n return createPostgresMigrationPlanner(adapter);\n },\n createRunner(family) {\n return createPostgresMigrationRunner(family) as MigrationRunner<'sql', 'postgres'>;\n },\n contractToSchema(contract, frameworkComponents) {\n const expander = buildNativeTypeExpander(frameworkComponents);\n const postgresContract = blindCast<\n PostgresContract | null,\n 'the family resolver only binds this hook for a Postgres-target contract'\n >(contract);\n return contractToPostgresDatabaseSchemaNode(postgresContract, {\n annotationNamespace: 'pg',\n ...ifDefined('expandNativeType', expander),\n renderDefault: postgresRenderDefault,\n });\n },\n },\n create(): ControlTargetInstance<'sql', 'postgres'> {\n return {\n familyId: 'sql',\n targetId: 'postgres',\n };\n },\n /**\n * Direct method for SQL-specific usage.\n * @deprecated Use migrations.createPlanner() for CLI compatibility.\n */\n createPlanner(adapter: SqlControlAdapter<'postgres'>) {\n return createPostgresMigrationPlanner(adapter);\n },\n /**\n * Direct method for SQL-specific usage.\n * @deprecated Use migrations.createRunner() for CLI compatibility.\n */\n createRunner(family) {\n return createPostgresMigrationRunner(family);\n },\n };\n\nexport default postgresTargetDescriptor;\n"],"mappings":"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"}
1
+ {"version":3,"file":"control.mjs","names":[],"sources":["../src/core/migrations/runner.ts","../src/core/postgres-schema-verifier.ts","../src/core/psl-infer/postgres-default-mapping.ts","../src/core/psl-infer/postgres-type-map.ts","../src/core/psl-infer/infer-psl-contract.ts","../src/exports/control.ts"],"sourcesContent":["import type { Contract, ContractMarkerRecord } from '@prisma-next/contract/types';\nimport type {\n MigrationOperationPolicy,\n SqlControlFamilyInstance,\n SqlMigrationPlanContractInfo,\n SqlMigrationPlanOperation,\n SqlMigrationPlanOperationStep,\n SqlMigrationRunner,\n SqlMigrationRunnerExecuteOptions,\n SqlMigrationRunnerFailure,\n SqlMigrationRunnerResult,\n SqlMigrationRunnerSuccessValue,\n} from '@prisma-next/family-sql/control';\nimport { runnerFailure, runnerSuccess } from '@prisma-next/family-sql/control';\nimport type { MigrationRunnerResult } from '@prisma-next/framework-components/control';\nimport { APP_SPACE_ID } from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type { SqlControlDriverInstance, SqlStorage } from '@prisma-next/sql-contract/types';\nimport { SqlQueryError } from '@prisma-next/sql-errors';\nimport type { SqlExecuteRequest } from '@prisma-next/sql-relational-core/ast';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { Result } from '@prisma-next/utils/result';\nimport { notOk, ok, okVoid } from '@prisma-next/utils/result';\nimport type { PostgresPlanTargetDetails } from './planner-target-details';\n\ninterface ApplyPlanSuccessValue {\n readonly operationsExecuted: number;\n readonly executedOperations: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[];\n}\n\nconst LOCK_DOMAIN = 'prisma_next.contract.marker';\n\n/**\n * Deep clones and freezes a record object to prevent mutation.\n * Recursively clones nested objects and arrays to ensure complete isolation.\n */\nfunction cloneAndFreezeRecord<T extends Record<string, unknown>>(value: T): T {\n const cloned: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n if (val === null || val === undefined) {\n cloned[key] = val;\n } else if (Array.isArray(val)) {\n cloned[key] = Object.freeze([...val]);\n } else if (typeof val === 'object') {\n cloned[key] = cloneAndFreezeRecord(val as Record<string, unknown>);\n } else {\n cloned[key] = val;\n }\n }\n return Object.freeze(cloned) as T;\n}\n\nexport function createPostgresMigrationRunner(\n family: SqlControlFamilyInstance,\n): SqlMigrationRunner<PostgresPlanTargetDetails> {\n return new PostgresMigrationRunner(family);\n}\n\nclass PostgresMigrationRunner implements SqlMigrationRunner<PostgresPlanTargetDetails> {\n constructor(private readonly family: SqlControlFamilyInstance) {}\n\n /**\n * Body of the migration runner without transaction management. The\n * caller ({@link PostgresMigrationRunner.execute}) owns the\n * `BEGIN`/`COMMIT`/`ROLLBACK` lifecycle.\n */\n async executeOnConnection(\n options: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,\n ): Promise<SqlMigrationRunnerResult> {\n const schema =\n options.schemaName ??\n Object.keys(options.destinationContract.storage.namespaces).find(\n (id) => id !== UNBOUND_NAMESPACE_ID,\n ) ??\n UNBOUND_NAMESPACE_ID;\n const driver = options.driver;\n if (options.space !== undefined && options.space !== options.plan.spaceId) {\n throw new Error(\n `SqlMigrationRunner: options.space (${options.space}) does not match plan.spaceId (${options.plan.spaceId})`,\n );\n }\n const space = options.plan.spaceId;\n const lockKey = `${LOCK_DOMAIN}:${schema}:${space}`;\n\n // Materialize any async ops before running checks or executing.\n const planOps = blindCast<\n readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[],\n 'ops were produced by the PG planner and are SqlMigrationPlanOperation<PostgresPlanTargetDetails>; MigrationPlan.operations uses the wider framework type to accommodate Promise covariance'\n >(await Promise.all(options.plan.operations));\n\n // Static checks (idempotent — safe to run again when the caller is\n // `execute(...)` because the cost is a single object comparison).\n const destinationCheck = this.ensurePlanMatchesDestinationContract(\n options.plan.destination,\n options.destinationContract,\n );\n if (!destinationCheck.ok) return destinationCheck;\n\n const policyCheck = this.enforcePolicyCompatibility(options.policy, planOps);\n if (!policyCheck.ok) return policyCheck;\n\n await this.acquireLock(driver, lockKey);\n const ensureResult = await this.ensureControlTables(driver, options.destinationContract);\n if (!ensureResult.ok) return ensureResult;\n const existingMarker = await this.family.readMarker({ driver, space });\n\n const markerCheck = this.ensureMarkerCompatibility(existingMarker, options.plan);\n if (!markerCheck.ok) return markerCheck;\n\n const markerAtDestination = this.markerMatchesDestination(existingMarker, options.plan);\n const isSelfEdge = options.plan.origin?.storageHash === options.plan.destination.storageHash;\n const skipOperations = markerAtDestination && options.plan.origin != null && !isSelfEdge;\n let applyValue: ApplyPlanSuccessValue;\n\n if (skipOperations) {\n applyValue = { operationsExecuted: 0, executedOperations: [] };\n } else {\n const applyResult = await this.applyPlan(driver, options, planOps);\n if (!applyResult.ok) return applyResult;\n applyValue = applyResult.value;\n }\n\n // Verify the schema on app-space only: extension spaces don't own\n // user-facing tables, so verifying the destination contract against the\n // database would flag every app-space table as \"extra\". Delegates to the\n // family `verifySchema` — the same comparison the CLI verify runs.\n if (space === APP_SPACE_ID) {\n const schemaNode = await this.family.introspect({\n driver,\n contract: options.destinationContract,\n });\n const schemaVerifyResult = this.family.verifySchema({\n contract: options.destinationContract,\n schema: schemaNode,\n strict: options.strictVerification ?? true,\n frameworkComponents: options.frameworkComponents,\n });\n if (!schemaVerifyResult.ok) {\n return runnerFailure('SCHEMA_VERIFY_FAILED', schemaVerifyResult.summary, {\n why: 'The resulting database schema does not satisfy the destination contract.',\n meta: {\n issues: [\n ...schemaVerifyResult.schema.issues,\n ...schemaVerifyResult.schema.schemaDiffIssues,\n ],\n },\n });\n }\n }\n\n const incomingInvariants = options.plan.providedInvariants ?? [];\n const existingInvariants = new Set(existingMarker?.invariants ?? []);\n const incomingIsSubsetOfExisting = incomingInvariants.every((id) => existingInvariants.has(id));\n const isSelfEdgeNoOp =\n isSelfEdge && applyValue.operationsExecuted === 0 && incomingIsSubsetOfExisting;\n\n if (!isSelfEdgeNoOp) {\n const markerResult = await this.upsertMarker(driver, options, existingMarker, space);\n if (!markerResult.ok) return markerResult;\n await this.recordLedgerEntries(\n driver,\n options,\n applyValue.executedOperations,\n planOps.length,\n );\n }\n\n return runnerSuccess({\n operationsPlanned: planOps.length,\n operationsExecuted: applyValue.operationsExecuted,\n });\n }\n\n async execute(options: {\n readonly driver: SqlControlDriverInstance<string>;\n readonly perSpaceOptions: ReadonlyArray<\n SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>\n >;\n }): Promise<MigrationRunnerResult> {\n const driver = options.driver;\n const perSpaceOptions = options.perSpaceOptions;\n\n if (perSpaceOptions.length === 0) {\n return ok({ perSpaceResults: [] });\n }\n\n await this.beginTransaction(driver);\n let committed = false;\n try {\n const perSpaceResults: Array<{\n space: string;\n value: SqlMigrationRunnerSuccessValue;\n }> = [];\n for (const spaceOptions of perSpaceOptions) {\n const space = spaceOptions.space ?? spaceOptions.plan.spaceId;\n const result = await this.executeOnConnection({ ...spaceOptions, driver, space });\n if (!result.ok) {\n return notOk({ ...result.failure, failingSpace: space });\n }\n perSpaceResults.push({ space, value: result.value });\n }\n\n await this.commitTransaction(driver);\n committed = true;\n return ok({ perSpaceResults });\n } finally {\n if (!committed) {\n await this.rollbackTransaction(driver);\n }\n }\n }\n\n private async applyPlan(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n options: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,\n ops: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[],\n ): Promise<Result<ApplyPlanSuccessValue, SqlMigrationRunnerFailure>> {\n const checks = options.executionChecks;\n const runPrechecks = checks?.prechecks !== false; // Default true\n const runPostchecks = checks?.postchecks !== false; // Default true\n const runIdempotency = checks?.idempotencyChecks !== false; // Default true\n\n let operationsExecuted = 0;\n const executedOperations: Array<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> = [];\n for (const operation of ops) {\n options.callbacks?.onOperationStart?.(operation);\n try {\n // Idempotency probe: only run if both postchecks and idempotency checks are enabled\n if (runPostchecks && runIdempotency) {\n const postcheckAlreadySatisfied = await this.expectationsAreSatisfied(\n driver,\n operation.postcheck,\n );\n if (postcheckAlreadySatisfied) {\n executedOperations.push(this.createPostcheckPreSatisfiedSkipRecord(operation));\n continue;\n }\n }\n\n // Prechecks: only run if enabled\n if (runPrechecks) {\n const precheckResult = await this.runExpectationSteps(\n driver,\n operation.precheck,\n operation,\n 'precheck',\n );\n if (!precheckResult.ok) {\n return precheckResult;\n }\n }\n\n const executeResult = await this.runExecuteSteps(driver, operation.execute, operation);\n if (!executeResult.ok) {\n return executeResult;\n }\n\n // Postchecks: only run if enabled\n if (runPostchecks) {\n const postcheckResult = await this.runExpectationSteps(\n driver,\n operation.postcheck,\n operation,\n 'postcheck',\n );\n if (!postcheckResult.ok) {\n return postcheckResult;\n }\n }\n\n executedOperations.push(operation);\n operationsExecuted += 1;\n } finally {\n options.callbacks?.onOperationComplete?.(operation);\n }\n }\n return ok({ operationsExecuted, executedOperations });\n }\n\n private async ensureControlTables(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n contract: Contract<SqlStorage>,\n ): Promise<Result<void, SqlMigrationRunnerFailure>> {\n const lowererContext = { contract };\n const bootstrapQueries = this.family.bootstrapControlTableQueries();\n const [schemaQuery, ...tableQueries] = bootstrapQueries;\n if (schemaQuery === undefined) {\n throw new Error('Postgres control-table bootstrap must include CREATE SCHEMA');\n }\n await this.executeStatement(driver, await this.family.lowerAst(schemaQuery, lowererContext));\n const legacyDetection = await this.detectLegacyMarkerShape(driver);\n if (!legacyDetection.ok) {\n return legacyDetection;\n }\n for (const query of tableQueries) {\n await this.executeStatement(driver, await this.family.lowerAst(query, lowererContext));\n }\n return okVoid();\n }\n\n private async detectLegacyMarkerShape(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n ): Promise<Result<void, SqlMigrationRunnerFailure>> {\n const result = await driver.query<{ column_name: string }>(\n `select column_name\n from information_schema.columns\n where table_schema = 'prisma_contract'\n and table_name = 'marker'`,\n );\n if (result.rows.length === 0) {\n return okVoid();\n }\n const columns = new Set(result.rows.map((row) => row.column_name));\n if (columns.has('space')) {\n return okVoid();\n }\n return runnerFailure(\n 'LEGACY_MARKER_SHAPE',\n 'Legacy marker-table shape detected on prisma_contract.marker (no `space` column). ' +\n 'Prisma Next is in pre-1.0; the previous transitional auto-migration to the per-space-row schema has been removed. ' +\n 'Drop `prisma_contract.marker` and re-run `dbInit` to reinitialise from a clean baseline.',\n {\n meta: {\n table: 'prisma_contract.marker',\n columns: [...columns].sort(),\n },\n },\n );\n }\n\n private async runExpectationSteps(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n steps: readonly SqlMigrationPlanOperationStep[],\n operation: SqlMigrationPlanOperation<PostgresPlanTargetDetails>,\n phase: 'precheck' | 'postcheck',\n ): Promise<Result<void, SqlMigrationRunnerFailure>> {\n for (const step of steps) {\n const result = await driver.query(step.sql, step.params ?? []);\n if (!this.stepResultIsTrue(result.rows)) {\n const code = phase === 'precheck' ? 'PRECHECK_FAILED' : 'POSTCHECK_FAILED';\n return runnerFailure(\n code,\n `Operation ${operation.id} failed during ${phase}: ${step.description}`,\n {\n meta: {\n operationId: operation.id,\n phase,\n stepDescription: step.description,\n },\n },\n );\n }\n }\n return okVoid();\n }\n\n private async runExecuteSteps(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n steps: readonly SqlMigrationPlanOperationStep[],\n operation: SqlMigrationPlanOperation<PostgresPlanTargetDetails>,\n ): Promise<Result<void, SqlMigrationRunnerFailure>> {\n for (const step of steps) {\n try {\n await driver.query(step.sql, step.params ?? []);\n } catch (error: unknown) {\n if (SqlQueryError.is(error)) {\n return runnerFailure(\n 'EXECUTION_FAILED',\n `Operation ${operation.id} failed during execution: ${step.description}`,\n {\n why: error.message,\n meta: {\n operationId: operation.id,\n stepDescription: step.description,\n sql: step.sql,\n sqlState: error.sqlState,\n constraint: error.constraint,\n table: error.table,\n column: error.column,\n detail: error.detail,\n },\n },\n );\n }\n throw error;\n }\n }\n return okVoid();\n }\n\n private stepResultIsTrue(rows: readonly Record<string, unknown>[]): boolean {\n if (!rows || rows.length === 0) {\n return false;\n }\n const firstRow = rows[0];\n const firstValue = firstRow ? Object.values(firstRow)[0] : undefined;\n if (typeof firstValue === 'boolean') {\n return firstValue;\n }\n if (typeof firstValue === 'number') {\n return firstValue !== 0;\n }\n if (typeof firstValue === 'string') {\n const lower = firstValue.toLowerCase();\n // PostgreSQL boolean representations: 't'/'f', 'true'/'false', '1'/'0'\n if (lower === 't' || lower === 'true' || lower === '1') {\n return true;\n }\n if (lower === 'f' || lower === 'false' || lower === '0') {\n return false;\n }\n // For other strings, non-empty is truthy (though this case shouldn't occur for boolean checks)\n return firstValue.length > 0;\n }\n return Boolean(firstValue);\n }\n\n private async expectationsAreSatisfied(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n steps: readonly SqlMigrationPlanOperationStep[],\n ): Promise<boolean> {\n if (steps.length === 0) {\n return false;\n }\n for (const step of steps) {\n const result = await driver.query(step.sql, step.params ?? []);\n if (!this.stepResultIsTrue(result.rows)) {\n return false;\n }\n }\n return true;\n }\n\n private createPostcheckPreSatisfiedSkipRecord(\n operation: SqlMigrationPlanOperation<PostgresPlanTargetDetails>,\n ): SqlMigrationPlanOperation<PostgresPlanTargetDetails> {\n // Clone and freeze existing meta if present\n const clonedMeta = operation.meta ? cloneAndFreezeRecord(operation.meta) : undefined;\n\n // Create frozen runner metadata\n const runnerMeta = Object.freeze({\n skipped: true,\n reason: 'postcheck_pre_satisfied',\n });\n\n // Merge and freeze the combined meta\n const mergedMeta = Object.freeze({\n ...(clonedMeta ?? {}),\n runner: runnerMeta,\n });\n\n // Clone and freeze arrays to prevent mutation\n const frozenPostcheck = Object.freeze([...operation.postcheck]);\n\n return Object.freeze({\n id: operation.id,\n label: operation.label,\n ...ifDefined('summary', operation.summary),\n operationClass: operation.operationClass,\n target: operation.target, // Already frozen from plan creation\n precheck: Object.freeze([]),\n execute: Object.freeze([]),\n postcheck: frozenPostcheck,\n ...ifDefined('meta', operation.meta || mergedMeta ? mergedMeta : undefined),\n });\n }\n\n private markerMatchesDestination(\n marker: ContractMarkerRecord | null,\n plan: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['plan'],\n ): boolean {\n if (!marker) {\n return false;\n }\n if (marker.storageHash !== plan.destination.storageHash) {\n return false;\n }\n if (plan.destination.profileHash && marker.profileHash !== plan.destination.profileHash) {\n return false;\n }\n return true;\n }\n\n private enforcePolicyCompatibility(\n policy: MigrationOperationPolicy,\n operations: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[],\n ): Result<void, SqlMigrationRunnerFailure> {\n const allowedClasses = new Set(policy.allowedOperationClasses);\n for (const operation of operations) {\n if (!allowedClasses.has(operation.operationClass)) {\n return runnerFailure(\n 'POLICY_VIOLATION',\n `Operation ${operation.id} has class \"${operation.operationClass}\" which is not allowed by policy.`,\n {\n why: `Policy only allows: ${policy.allowedOperationClasses.join(', ')}.`,\n meta: {\n operationId: operation.id,\n operationClass: operation.operationClass,\n allowedClasses: policy.allowedOperationClasses,\n },\n },\n );\n }\n }\n return okVoid();\n }\n\n private ensureMarkerCompatibility(\n marker: ContractMarkerRecord | null,\n plan: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['plan'],\n ): Result<void, SqlMigrationRunnerFailure> {\n const origin = plan.origin ?? null;\n if (!origin) {\n // No origin assertion on the plan — the caller does not want origin validation.\n // This is the case for `db update`, which introspects the live schema and does not\n // rely on marker continuity. `db init` handles its own marker checks before the runner.\n return okVoid();\n }\n\n if (!marker) {\n return runnerFailure(\n 'MARKER_ORIGIN_MISMATCH',\n `Missing contract marker: expected origin storage hash ${origin.storageHash}.`,\n {\n meta: {\n expectedOriginStorageHash: origin.storageHash,\n },\n },\n );\n }\n if (marker.storageHash !== origin.storageHash) {\n return runnerFailure(\n 'MARKER_ORIGIN_MISMATCH',\n `Existing contract marker (${marker.storageHash}) does not match plan origin (${origin.storageHash}).`,\n {\n meta: {\n markerStorageHash: marker.storageHash,\n expectedOriginStorageHash: origin.storageHash,\n },\n },\n );\n }\n if (origin.profileHash && marker.profileHash !== origin.profileHash) {\n return runnerFailure(\n 'MARKER_ORIGIN_MISMATCH',\n `Existing contract marker profile hash (${marker.profileHash}) does not match plan origin profile hash (${origin.profileHash}).`,\n {\n meta: {\n markerProfileHash: marker.profileHash,\n expectedOriginProfileHash: origin.profileHash,\n },\n },\n );\n }\n return okVoid();\n }\n\n private ensurePlanMatchesDestinationContract(\n destination: SqlMigrationPlanContractInfo,\n contract: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['destinationContract'],\n ): Result<void, SqlMigrationRunnerFailure> {\n if (destination.storageHash !== contract.storage.storageHash) {\n return runnerFailure(\n 'DESTINATION_CONTRACT_MISMATCH',\n `Plan destination storage hash (${destination.storageHash}) does not match provided contract storage hash (${contract.storage.storageHash}).`,\n {\n meta: {\n planStorageHash: destination.storageHash,\n contractStorageHash: contract.storage.storageHash,\n },\n },\n );\n }\n if (\n destination.profileHash &&\n contract.profileHash &&\n destination.profileHash !== contract.profileHash\n ) {\n return runnerFailure(\n 'DESTINATION_CONTRACT_MISMATCH',\n `Plan destination profile hash (${destination.profileHash}) does not match provided contract profile hash (${contract.profileHash}).`,\n {\n meta: {\n planProfileHash: destination.profileHash,\n contractProfileHash: contract.profileHash,\n },\n },\n );\n }\n return okVoid();\n }\n\n private async upsertMarker(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n options: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,\n existingMarker: ContractMarkerRecord | null,\n space: string,\n ): Promise<Result<void, SqlMigrationRunnerFailure>> {\n const destination = {\n storageHash: options.plan.destination.storageHash,\n profileHash:\n options.plan.destination.profileHash ??\n options.destinationContract.profileHash ??\n options.plan.destination.storageHash,\n invariants: options.plan.providedInvariants ?? [],\n };\n if (!existingMarker) {\n await this.family.initMarker({ driver, space, destination });\n return okVoid();\n }\n const updated = await this.family.updateMarker({\n driver,\n space,\n expectedFrom: existingMarker.storageHash,\n destination,\n });\n if (!updated) {\n return runnerFailure(\n 'MARKER_CAS_FAILURE',\n 'Marker was modified by another process during migration execution.',\n {\n meta: {\n space,\n expectedStorageHash: existingMarker.storageHash,\n destinationStorageHash: options.plan.destination.storageHash,\n },\n },\n );\n }\n return okVoid();\n }\n\n private async recordLedgerEntries(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n options: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>,\n executedOperations: readonly SqlMigrationPlanOperation<PostgresPlanTargetDetails>[],\n planOpsLength: number,\n ): Promise<void> {\n const plan = options.plan;\n const space = plan.spaceId;\n const edges = options.migrationEdges;\n const totalEdgeOps = edges.reduce((sum, edge) => sum + edge.operationCount, 0);\n if (totalEdgeOps !== planOpsLength) {\n throw new Error(\n `Ledger write: plan.operations length (${planOpsLength}) does not match sum of migrationEdges operationCount (${totalEdgeOps})`,\n );\n }\n // The ledger records the operations as executed — idempotency-skipped ops\n // are substituted with skip records (empty `execute`) by `applyPlan`, so the\n // journal reflects what actually ran rather than the raw plan.\n let offset = 0;\n for (const edge of edges) {\n const edgeOps = executedOperations.slice(offset, offset + edge.operationCount);\n offset += edge.operationCount;\n await this.family.writeLedgerEntry({\n driver,\n space,\n entry: {\n edgeId: `${edge.from}->${edge.to}`,\n from: edge.from,\n to: edge.to,\n migrationName: edge.dirName,\n migrationHash: edge.migrationHash,\n operations: edgeOps,\n },\n });\n }\n }\n\n private async acquireLock(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n key: string,\n ): Promise<void> {\n await driver.query('select pg_advisory_xact_lock(hashtext($1))', [key]);\n }\n\n private async beginTransaction(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n ): Promise<void> {\n await driver.query('BEGIN');\n }\n\n private async commitTransaction(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n ): Promise<void> {\n await driver.query('COMMIT');\n }\n\n private async rollbackTransaction(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n ): Promise<void> {\n await driver.query('ROLLBACK');\n }\n\n private async executeStatement(\n driver: SqlMigrationRunnerExecuteOptions<PostgresPlanTargetDetails>['driver'],\n statement: SqlExecuteRequest,\n ): Promise<void> {\n await driver.query(statement.sql, statement.params);\n }\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport { SqlSchemaVerifierBase } from '@prisma-next/family-sql/ir';\nimport type { SchemaIssue, SchemaVerifyOptions } from '@prisma-next/framework-components/control';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\n\n/**\n * Postgres target `SchemaVerifier` concretion. Plugs into the\n * SQL-shared verification surface; production verification today still\n * routes through the legacy `verifySqlSchema` entry point, which\n * carries options (codec hooks, normalizers, framework components)\n * that the framework-level `SchemaVerifyOptions` shape does not yet\n * surface.\n *\n * The hooks return the empty list pending the call-site migration that\n * routes the existing verifier behaviour through the SPI — at that\n * point `verifyCommonSqlSchema` will likely lift onto the family base\n * (mirroring `verifyCommonMongoSchema`) and `verifyTargetExtensions`\n * will house Postgres-only kinds (functions, RLS policies in a future\n * project).\n */\nexport class PostgresSchemaVerifier extends SqlSchemaVerifierBase<\n Contract<SqlStorage>,\n SqlSchemaIR\n> {\n protected verifyCommonSqlSchema(\n _options: SchemaVerifyOptions<Contract<SqlStorage>, SqlSchemaIR>,\n ): readonly SchemaIssue[] {\n return [];\n }\n\n protected verifyTargetExtensions(\n _options: SchemaVerifyOptions<Contract<SqlStorage>, SqlSchemaIR>,\n ): readonly SchemaIssue[] {\n return [];\n }\n}\n","import type { DefaultMappingOptions } from '@prisma-next/family-sql/psl-infer';\n\nconst POSTGRES_FUNCTION_ATTRIBUTES: Readonly<Record<string, string>> = {\n 'gen_random_uuid()': '@default(dbgenerated(\"gen_random_uuid()\"))',\n};\n\nfunction formatDbGeneratedAttribute(expression: string): string {\n return `@default(dbgenerated(${JSON.stringify(expression)}))`;\n}\n\nexport function createPostgresDefaultMapping(): DefaultMappingOptions {\n return {\n functionAttributes: POSTGRES_FUNCTION_ATTRIBUTES,\n fallbackFunctionAttribute: formatDbGeneratedAttribute,\n };\n}\n","import type {\n EnumInfo,\n PslNativeTypeAttribute,\n PslTypeMap,\n PslTypeResolution,\n} from '@prisma-next/family-sql/psl-infer';\n\nconst POSTGRES_TO_PSL: Record<string, string> = {\n text: 'String',\n bool: 'Boolean',\n boolean: 'Boolean',\n int4: 'Int',\n integer: 'Int',\n int8: 'BigInt',\n bigint: 'BigInt',\n float8: 'Float',\n 'double precision': 'Float',\n numeric: 'Decimal',\n decimal: 'Decimal',\n timestamptz: 'DateTime',\n 'timestamp with time zone': 'DateTime',\n jsonb: 'Json',\n bytea: 'Bytes',\n};\n\nconst PRESERVED_NATIVE_TYPES: Record<\n string,\n { readonly pslType: string; readonly attributeName: string }\n> = {\n 'character varying': { pslType: 'String', attributeName: 'db.VarChar' },\n character: { pslType: 'String', attributeName: 'db.Char' },\n char: { pslType: 'String', attributeName: 'db.Char' },\n varchar: { pslType: 'String', attributeName: 'db.VarChar' },\n uuid: { pslType: 'String', attributeName: 'db.Uuid' },\n int2: { pslType: 'Int', attributeName: 'db.SmallInt' },\n smallint: { pslType: 'Int', attributeName: 'db.SmallInt' },\n float4: { pslType: 'Float', attributeName: 'db.Real' },\n real: { pslType: 'Float', attributeName: 'db.Real' },\n timestamp: { pslType: 'DateTime', attributeName: 'db.Timestamp' },\n 'timestamp without time zone': { pslType: 'DateTime', attributeName: 'db.Timestamp' },\n date: { pslType: 'DateTime', attributeName: 'db.Date' },\n time: { pslType: 'DateTime', attributeName: 'db.Time' },\n 'time without time zone': { pslType: 'DateTime', attributeName: 'db.Time' },\n timetz: { pslType: 'DateTime', attributeName: 'db.Timetz' },\n 'time with time zone': { pslType: 'DateTime', attributeName: 'db.Timetz' },\n json: { pslType: 'Json', attributeName: 'db.Json' },\n};\n\nconst PARAMETERIZED_NATIVE_TYPES: Record<\n string,\n { readonly pslType: string; readonly attributeName: string }\n> = {\n 'character varying': { pslType: 'String', attributeName: 'db.VarChar' },\n character: { pslType: 'String', attributeName: 'db.Char' },\n char: { pslType: 'String', attributeName: 'db.Char' },\n varchar: { pslType: 'String', attributeName: 'db.VarChar' },\n numeric: { pslType: 'Decimal', attributeName: 'db.Numeric' },\n timestamp: { pslType: 'DateTime', attributeName: 'db.Timestamp' },\n timestamptz: { pslType: 'DateTime', attributeName: 'db.Timestamptz' },\n time: { pslType: 'DateTime', attributeName: 'db.Time' },\n timetz: { pslType: 'DateTime', attributeName: 'db.Timetz' },\n};\n\nconst PARAMETERIZED_TYPE_PATTERN = /^(.+?)\\((.+)\\)$/;\n\nfunction getOwnMappingValue(map: Record<string, string>, key: string): string | undefined {\n return Object.hasOwn(map, key) ? map[key] : undefined;\n}\n\nfunction getOwnRecordValue<T>(map: Record<string, T>, key: string): T | undefined {\n return Object.hasOwn(map, key) ? map[key] : undefined;\n}\n\nfunction createNativeTypeAttribute(name: string, args?: readonly string[]): PslNativeTypeAttribute {\n return args && args.length > 0 ? { name, args } : { name };\n}\n\nfunction splitTypeParameterList(params: string): readonly string[] {\n return params\n .split(',')\n .map((part) => part.trim())\n .filter((part) => part.length > 0);\n}\n\nexport function createPostgresTypeMap(enumTypeNames?: ReadonlySet<string>): PslTypeMap {\n return {\n resolve(nativeType: string): PslTypeResolution {\n if (enumTypeNames?.has(nativeType)) {\n return { pslType: nativeType, nativeType };\n }\n\n const paramMatch = nativeType.match(PARAMETERIZED_TYPE_PATTERN);\n if (paramMatch) {\n const [, baseType = nativeType, params = ''] = paramMatch;\n const template = getOwnRecordValue(PARAMETERIZED_NATIVE_TYPES, baseType);\n if (template) {\n return {\n pslType: template.pslType,\n nativeType,\n typeParams: { baseType, params },\n nativeTypeAttribute: createNativeTypeAttribute(\n template.attributeName,\n splitTypeParameterList(params),\n ),\n };\n }\n }\n\n const preservedType = getOwnRecordValue(PRESERVED_NATIVE_TYPES, nativeType);\n if (preservedType) {\n return {\n pslType: preservedType.pslType,\n nativeType,\n nativeTypeAttribute: createNativeTypeAttribute(preservedType.attributeName),\n };\n }\n\n const pslType = getOwnMappingValue(POSTGRES_TO_PSL, nativeType);\n if (pslType) {\n return {\n pslType,\n nativeType,\n };\n }\n\n return { unsupported: true, nativeType };\n },\n };\n}\n\nexport function extractEnumInfo(annotations?: Record<string, unknown>): EnumInfo {\n const pgAnnotations = annotations?.['pg'] as Record<string, unknown> | undefined;\n const nativeEnumTypeNames = pgAnnotations?.['nativeEnumTypeNames'];\n\n const typeNames = new Set<string>();\n const definitions = new Map<string, readonly string[]>();\n\n if (Array.isArray(nativeEnumTypeNames)) {\n for (const name of nativeEnumTypeNames) {\n if (typeof name === 'string') {\n typeNames.add(name);\n }\n }\n }\n\n return { typeNames, definitions };\n}\n\nexport function extractEnumTypeNames(annotations?: Record<string, unknown>): ReadonlySet<string> {\n return extractEnumInfo(annotations).typeNames;\n}\n\nexport function extractEnumDefinitions(\n annotations?: Record<string, unknown>,\n): ReadonlyMap<string, readonly string[]> {\n return extractEnumInfo(annotations).definitions;\n}\n","import type { ColumnDefault } from '@prisma-next/contract/types';\nimport type { SqlDescribedContractSpace } from '@prisma-next/family-sql/control';\nimport type {\n DefaultMappingOptions,\n PslNativeTypeAttribute,\n PslPrinterOptions,\n PslTypeMap,\n RelationField,\n} from '@prisma-next/family-sql/psl-infer';\nimport {\n buildChildRelationField,\n deriveRelationFieldName,\n inferRelations,\n mapDefault,\n parseRawDefault,\n toFieldName,\n toModelName,\n toNamedTypeName,\n} from '@prisma-next/family-sql/psl-infer';\nimport { coordinateKey, elementCoordinates } from '@prisma-next/framework-components/ir';\nimport type {\n PslAttribute,\n PslAttributeArgument,\n PslDocumentAst,\n PslField,\n PslFieldAttribute,\n PslModel,\n PslModelAttribute,\n PslNamedTypeDeclaration,\n PslSpan,\n PslTypesBlock,\n} from '@prisma-next/framework-components/psl-ast';\nimport {\n makePslNamespace,\n makePslNamespaceEntries,\n UNSPECIFIED_PSL_NAMESPACE_ID,\n} from '@prisma-next/framework-components/psl-ast';\nimport type { SqlModelStorage } from '@prisma-next/sql-contract/types';\nimport type {\n SqlColumnIR,\n SqlForeignKeyIR,\n SqlSchemaIR,\n SqlTableIR,\n} from '@prisma-next/sql-schema-ir/types';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { PostgresDatabaseSchemaNode } from '../schema-ir/postgres-database-schema-node';\nimport { createPostgresDefaultMapping } from './postgres-default-mapping';\nimport { createPostgresTypeMap } from './postgres-type-map';\n\nconst SYNTHETIC_SPAN: PslSpan = {\n start: { offset: 0, line: 1, column: 1 },\n end: { offset: 0, line: 1, column: 1 },\n};\n\nconst PSL_SCALAR_TYPE_NAMES = new Set([\n 'String',\n 'Boolean',\n 'Int',\n 'BigInt',\n 'Float',\n 'Decimal',\n 'DateTime',\n 'Json',\n 'Bytes',\n]);\n\ntype ResolvedColumnFieldName = {\n readonly fieldName: string;\n readonly fieldMap?: string | undefined;\n};\n\ntype TableColumnFieldNameMap = ReadonlyMap<string, ResolvedColumnFieldName>;\n\ntype NamedTypeRegistryEntry = {\n readonly name: string;\n readonly baseType: string;\n readonly nativeTypeAttribute: PslNativeTypeAttribute;\n};\n\ntype NamedTypeRegistry = {\n readonly entriesByKey: Map<string, NamedTypeRegistryEntry>;\n readonly usedNames: Set<string>;\n};\n\ntype TopLevelNameResult = {\n readonly name: string;\n readonly map?: string | undefined;\n};\n\n/**\n * Coordinates every element a set of already-assembled contracts declare,\n * mapped to the {@link SqlDescribedContractSpace} that owns it and keyed by\n * the shared {@link coordinateKey} helper. `contract infer` uses this to omit\n * database elements a stack extension pack's contract space already\n * describes — reusing the same coordinate walk the contract-space aggregate\n * and cross-space collision check use (`elementCoordinates`), rather than a\n * bespoke per-entity-kind membership test — and, for a foreign key whose\n * referenced table an entry owns, to resolve the qualified cross-space\n * relation it describes.\n */\nfunction describedContractOwners(\n describedContracts: readonly SqlDescribedContractSpace[],\n): ReadonlyMap<string, SqlDescribedContractSpace> {\n const owners = new Map<string, SqlDescribedContractSpace>();\n for (const entry of describedContracts) {\n for (const coordinate of elementCoordinates(entry.contract.storage)) {\n owners.set(coordinateKey(coordinate), entry);\n }\n }\n return owners;\n}\n\n/**\n * The domain model a described contract maps a `(namespaceId, tableName)`\n * storage coordinate to, plus the pack's own space id and column→field-name\n * mapping — everything `buildModel`/`buildRelationField` need to emit the\n * cross-space relation `<spaceId>:<namespaceId>.<modelName>` and resolve its\n * `references` argument to the pack's own field names rather than a generic\n * column-name guess.\n */\ntype CrossSpaceTarget = {\n readonly spaceId: string;\n readonly namespaceId: string;\n readonly modelName: string;\n readonly fieldNamesByColumn: TableColumnFieldNameMap;\n};\n\nfunction resolveCrossSpaceTarget(\n owner: SqlDescribedContractSpace,\n namespaceId: string,\n tableName: string,\n): CrossSpaceTarget | undefined {\n const domainNamespace = owner.contract.domain.namespaces[namespaceId];\n if (domainNamespace === undefined) {\n return undefined;\n }\n\n for (const [modelName, model] of Object.entries(domainNamespace.models)) {\n const storage = blindCast<SqlModelStorage, 'SQL contract model storage'>(model.storage);\n if (storage.namespaceId !== namespaceId || storage.table !== tableName) {\n continue;\n }\n\n const fieldNamesByColumn = new Map<string, ResolvedColumnFieldName>();\n for (const [fieldName, fieldStorage] of Object.entries(storage.fields)) {\n fieldNamesByColumn.set(fieldStorage.column, { fieldName });\n }\n\n return { spaceId: owner.spaceId, namespaceId, modelName, fieldNamesByColumn };\n }\n\n return undefined;\n}\n\ntype ForeignKeyResolution = {\n /** `tables`, with every cross-space or dangling foreign key removed. */\n readonly tables: Record<string, SqlTableIR>;\n /** Cross-space relation fields to merge onto `inferRelations`'s output, keyed by host table name. */\n readonly extraRelationsByTable: ReadonlyMap<string, readonly RelationField[]>;\n /** Synthetic field-name maps for cross-space-referenced pack tables, merged into `fieldNamesByTable`. */\n readonly crossSpaceFieldNamesByTable: ReadonlyMap<string, TableColumnFieldNameMap>;\n};\n\n/**\n * Classifies every foreign key on a surviving table into one of three cases.\n * A foreign key that carries a `referencedSchema` is checked against the\n * pack-owned coordinates first, so a pack-owned target wins even when a local\n * table happens to share its bare name; only foreign keys with no owned\n * coordinate fall through to the local/dangling distinction.\n *\n * - **Cross-space**: `referencedSchema` is set and a described contract owns\n * the coordinate `(referencedSchema, 'table', referencedTable)`. The\n * referenced table is absent from the tree (omitted because the pack\n * describes it, or never introspected — `contract infer` walks a single\n * namespace). Removed from `foreignKeys` (so `inferRelations` never falls\n * back to a bare, unqualified table name for it) and replaced with a\n * `RelationField` qualified with the owning pack's space id and namespace\n * id. `owners` holds only pack-declared coordinates, so an app's own table\n * (e.g. `public.users`) is never owned and cannot be captured here.\n * - **Local**: not a pack-owned coordinate, and the referenced table survived\n * introspection — left untouched, `inferRelations` handles it as before.\n * - **Dangling**: not a pack-owned coordinate, and the referenced table is\n * neither in the tree nor owned by any described contract. Removed from\n * `foreignKeys`, keeping the scalar column, rather than emitting a relation\n * to a model that was never defined.\n *\n * A pack that owns the referenced coordinate but declares no domain model\n * mapped to it is malformed; that case throws rather than degrading to a\n * silent drop, which would contradict the dangling definition above.\n */\nfunction resolveForeignKeys(\n tables: Readonly<Record<string, SqlTableIR>>,\n owners: ReadonlyMap<string, SqlDescribedContractSpace>,\n): ForeignKeyResolution {\n const resultTables: Record<string, SqlTableIR> = {};\n const extraRelationsByTable = new Map<string, RelationField[]>();\n const crossSpaceFieldNamesByTable = new Map<string, TableColumnFieldNameMap>();\n\n for (const [tableName, table] of Object.entries(tables)) {\n const keptForeignKeys: SqlForeignKeyIR[] = [];\n\n for (const fk of table.foreignKeys) {\n if (fk.referencedSchema !== undefined) {\n const owner = owners.get(\n coordinateKey({\n namespaceId: fk.referencedSchema,\n entityKind: 'table',\n entityName: fk.referencedTable,\n }),\n );\n if (owner !== undefined) {\n const target = resolveCrossSpaceTarget(owner, fk.referencedSchema, fk.referencedTable);\n if (target === undefined) {\n throw new Error(\n `contract infer: described contract space \"${owner.spaceId}\" owns storage ` +\n `coordinate \"${fk.referencedSchema}.${fk.referencedTable}\" but declares no ` +\n 'domain model mapped to it. A pack that describes a table must also declare the ' +\n 'domain model it maps to; this pack is malformed.',\n );\n }\n\n if (!crossSpaceFieldNamesByTable.has(fk.referencedTable)) {\n crossSpaceFieldNamesByTable.set(fk.referencedTable, target.fieldNamesByColumn);\n }\n\n const fieldName = deriveRelationFieldName(fk.columns, fk.referencedTable);\n const optional = fk.columns.some(\n (columnName) => table.columns[columnName]?.nullable ?? false,\n );\n const relationField: RelationField = {\n ...buildChildRelationField(fieldName, target.modelName, fk, optional),\n typeNamespaceId: target.namespaceId,\n typeContractSpaceId: target.spaceId,\n };\n\n const existingRelations = extraRelationsByTable.get(tableName);\n if (existingRelations) {\n existingRelations.push(relationField);\n } else {\n extraRelationsByTable.set(tableName, [relationField]);\n }\n continue;\n }\n }\n\n // Not a pack-owned coordinate: keep the foreign key if the referenced\n // table survived introspection (local), otherwise drop it while keeping\n // the scalar column (dangling).\n if (tables[fk.referencedTable] !== undefined) {\n keptForeignKeys.push(fk);\n }\n }\n\n resultTables[tableName] =\n keptForeignKeys.length === table.foreignKeys.length\n ? table\n : { ...table, foreignKeys: keptForeignKeys };\n }\n\n return { tables: resultTables, extraRelationsByTable, crossSpaceFieldNamesByTable };\n}\n\n/**\n * Infers a PSL AST (for `printPsl`) from an introspected Postgres schema tree.\n *\n * Target-owned inference: it walks the `PostgresDatabaseSchemaNode` tree and\n * owns the Postgres dialect knowledge — the native type map and default map.\n * Relation inference, name transforms, generic default mapping, and raw-default\n * parsing are shape-neutral utilities imported from the SQL family.\n *\n * This slice emits relational-only PSL, byte-identical to the prior flat\n * inference: the tree's tables (across its namespaces — `contract infer`\n * introspects a single live namespace) are gathered into the model set and\n * emitted as one `UNSPECIFIED_PSL_NAMESPACE_ID` bucket. Top-level entities\n * (policies/roles → PSL extension blocks) are a later slice.\n *\n * `describedContracts` — the stack's extension packs' already-assembled\n * contracts, each paired with its space id — is consulted while gathering\n * tables: a table whose coordinate `(schemaName, 'table', tableName)` one of\n * those contracts already declares is omitted, before the duplicate-name\n * check below and before relation inference, so it cannot spuriously\n * collide with an app table and never contributes a bare relation field. A\n * surviving table's foreign key into an omitted, pack-owned table is not\n * dropped: {@link resolveForeignKeys} rewrites it into a relation qualified\n * with the pack's space id (`<spaceId>:<namespaceId>.<Model>`) instead.\n */\nexport function inferPostgresPslContract(\n tree: PostgresDatabaseSchemaNode,\n describedContracts?: readonly SqlDescribedContractSpace[],\n): PslDocumentAst {\n const namespaces = Object.values(tree.namespaces);\n const owners = describedContractOwners(describedContracts ?? []);\n\n // Native Postgres enums (CREATE TYPE … AS ENUM) are not adoptable by\n // `contract infer`; throw an actionable diagnostic naming the type(s). Enum\n // names live on each namespace node's `nativeEnumTypeNames`.\n const enumTypeNames = [...new Set(namespaces.flatMap((ns) => ns.nativeEnumTypeNames))];\n if (enumTypeNames.length > 0) {\n const names = enumTypeNames.join(', ');\n throw new Error(\n `contract infer: the database contains native Postgres enum type(s): ${names}. ` +\n 'Native Postgres enums (CREATE TYPE … AS ENUM) are not adoptable by contract infer. ' +\n 'Drop the native type and replace each column with a text column carrying a CHECK constraint, ' +\n `then re-run contract infer. The domain enum (enum Name { @@type(\"pg/text@1\") … }) authoring ` +\n 'surface generates the required check automatically.',\n );\n }\n\n // Stopgap (TML-2958): flatten the schema-IR *tree* into the single `{ tables }`\n // map the PSL writer expects. The writer still walks a flat table map, so this\n // is a read-only projection — it does not reintroduce a stored flat schema.\n // The real fix is to extend the PSL writer to walk the namespace tree and emit\n // per-namespace `namespace { … }` blocks; until then `contract infer` handles a\n // single introspected namespace, and a same-named table in two schemas has no\n // unambiguous single-bucket model, so we throw rather than silently drop one.\n const tables: Record<string, SqlTableIR> = {};\n for (const namespace of namespaces) {\n for (const [tableName, table] of Object.entries(namespace.tables)) {\n if (\n owners.has(\n coordinateKey({\n namespaceId: namespace.schemaName,\n entityKind: 'table',\n entityName: tableName,\n }),\n )\n ) {\n continue;\n }\n if (tables[tableName] !== undefined) {\n throw new Error(\n `contract infer: duplicate table name \"${tableName}\" across schemas is not yet supported ` +\n '(single-namespace PSL inference emits one flat bucket; multi-namespace `namespace { … }` ' +\n 'output is a later slice).',\n );\n }\n tables[tableName] = table;\n }\n }\n\n const {\n tables: resolvedTables,\n extraRelationsByTable,\n crossSpaceFieldNamesByTable,\n } = resolveForeignKeys(tables, owners);\n const schemaIR: SqlSchemaIR = { tables: resolvedTables };\n\n const options: PslPrinterOptions = {\n typeMap: createPostgresTypeMap(new Set()),\n defaultMapping: createPostgresDefaultMapping(),\n parseRawDefault,\n };\n\n return buildPslDocumentAst(schemaIR, options, {\n extraRelationsByTable,\n crossSpaceFieldNamesByTable,\n });\n}\n\nfunction buildPslDocumentAst(\n schemaIR: SqlSchemaIR,\n options: PslPrinterOptions,\n foreignKeyExtras: Pick<\n ForeignKeyResolution,\n 'extraRelationsByTable' | 'crossSpaceFieldNamesByTable'\n >,\n): PslDocumentAst {\n const { typeMap, defaultMapping, parseRawDefault: rawDefaultParser } = options;\n const { extraRelationsByTable, crossSpaceFieldNamesByTable } = foreignKeyExtras;\n\n const modelNames = buildTopLevelNameMap(\n Object.keys(schemaIR.tables),\n toModelName,\n 'model',\n 'table',\n );\n\n const modelNameMap = new Map(\n [...modelNames].map(([tableName, result]) => [tableName, result.name]),\n );\n const reservedNamedTypeNames = createReservedNamedTypeNames(modelNames);\n\n // Cross-space entries are seeded first so a real local table of the same\n // bare name (an existing single-namespace-flat-bucket limitation, not new\n // here) always wins the merge, matching `resolveForeignKeys`'s own\n // precedence: a surviving local table is never treated as cross-space.\n const fieldNamesByTable = new Map([\n ...crossSpaceFieldNamesByTable,\n ...buildFieldNamesByTable(schemaIR.tables),\n ]);\n const { relationsByTable } = inferRelations(schemaIR.tables, modelNameMap);\n const namedTypes = seedNamedTypeRegistry(schemaIR, typeMap, new Map(), reservedNamedTypeNames);\n\n const models: PslModel[] = [];\n for (const table of Object.values(schemaIR.tables)) {\n models.push(\n buildModel(\n table,\n typeMap,\n new Map(),\n fieldNamesByTable,\n namedTypes,\n defaultMapping,\n rawDefaultParser,\n [\n ...(relationsByTable.get(table.name) ?? []),\n ...(extraRelationsByTable.get(table.name) ?? []),\n ],\n ),\n );\n }\n\n const sortedModels = topologicalSort(models, schemaIR.tables, modelNameMap);\n\n const namedTypeEntries = [...namedTypes.entriesByKey.values()].sort((a, b) =>\n a.name.localeCompare(b.name),\n );\n const types: PslTypesBlock | undefined =\n namedTypeEntries.length > 0\n ? {\n kind: 'types',\n declarations: namedTypeEntries.map(buildNamedTypeDeclaration),\n span: SYNTHETIC_SPAN,\n }\n : undefined;\n\n // Inferred PSL nodes will eventually be routed into per-namespace buckets\n // matching the source storage; for now we synthesise a single\n // `__unspecified__` bucket so round-tripping the AST through the framework\n // printer (which emits the synthesised bucket at top level with no\n // `namespace { … }` wrapper) preserves the existing introspection output\n // verbatim.\n const ast: PslDocumentAst = {\n kind: 'document',\n sourceId: '<sql-schema-ir>',\n namespaces: [\n makePslNamespace({\n kind: 'namespace',\n name: UNSPECIFIED_PSL_NAMESPACE_ID,\n entries: makePslNamespaceEntries(sortedModels, [], []),\n span: SYNTHETIC_SPAN,\n }),\n ],\n ...(types ? { types } : {}),\n span: SYNTHETIC_SPAN,\n };\n\n return ast;\n}\n\nfunction buildModel(\n table: SqlTableIR,\n typeMap: PslTypeMap,\n enumNameMap: ReadonlyMap<string, string>,\n fieldNamesByTable: ReadonlyMap<string, TableColumnFieldNameMap>,\n namedTypes: NamedTypeRegistry,\n defaultMapping: DefaultMappingOptions | undefined,\n rawDefaultParser: PslPrinterOptions['parseRawDefault'],\n relationFields: readonly RelationField[],\n): PslModel {\n const { name: modelName, map: mapName } = toModelName(table.name);\n const fieldNameMap = fieldNamesByTable.get(table.name);\n\n const pkColumns = new Set(table.primaryKey?.columns ?? []);\n const isSinglePk = pkColumns.size === 1;\n const singlePkConstraintName = isSinglePk ? table.primaryKey?.name : undefined;\n\n const uniqueColumns = new Map<string, string | undefined>();\n for (const unique of table.uniques) {\n if (unique.columns.length === 1) {\n const [columnName = ''] = unique.columns;\n const existingConstraintName = uniqueColumns.get(columnName);\n if (!uniqueColumns.has(columnName) || (existingConstraintName === undefined && unique.name)) {\n uniqueColumns.set(columnName, unique.name);\n }\n }\n }\n\n const fields: PslField[] = [];\n for (const column of Object.values(table.columns)) {\n fields.push(\n buildScalarField(\n column,\n table,\n typeMap,\n enumNameMap,\n fieldNameMap,\n namedTypes,\n defaultMapping,\n rawDefaultParser,\n pkColumns,\n isSinglePk,\n singlePkConstraintName,\n uniqueColumns,\n ),\n );\n }\n\n const usedFieldNames = new Set(fields.map((field) => field.name));\n for (const rel of relationFields) {\n fields.push(buildRelationField(rel, table.name, fieldNamesByTable, usedFieldNames));\n }\n\n const modelAttributes: PslModelAttribute[] = [];\n\n if (table.primaryKey && table.primaryKey.columns.length > 1) {\n const pkFieldNames = table.primaryKey.columns.map((columnName) =>\n resolveColumnFieldName(fieldNamesByTable, table.name, columnName),\n );\n modelAttributes.push(buildModelConstraintAttribute('id', pkFieldNames, table.primaryKey.name));\n }\n\n for (const unique of table.uniques) {\n if (unique.columns.length > 1) {\n const uniqueFieldNames = unique.columns.map((columnName) =>\n resolveColumnFieldName(fieldNamesByTable, table.name, columnName),\n );\n modelAttributes.push(buildModelConstraintAttribute('unique', uniqueFieldNames, unique.name));\n }\n }\n\n for (const index of table.indexes) {\n if (!index.unique) {\n const indexFieldNames = index.columns.map((columnName) =>\n resolveColumnFieldName(fieldNamesByTable, table.name, columnName),\n );\n modelAttributes.push(buildModelConstraintAttribute('index', indexFieldNames, index.name));\n }\n }\n\n if (mapName) {\n modelAttributes.push(buildMapAttribute('model', mapName));\n }\n\n // Surface introspection advisory: tables without a primary key cannot serve\n // as the right-hand side of a `findUnique`-style query downstream, so the\n // user should add an `@id`. This warning is part of the emitted SQL output\n // and is asserted byte-for-byte, so keep the exact wording.\n const comment = table.primaryKey\n ? undefined\n : '// WARNING: This table has no primary key in the database';\n\n return {\n kind: 'model',\n name: modelName,\n fields,\n attributes: modelAttributes,\n span: SYNTHETIC_SPAN,\n ...(comment !== undefined ? { comment } : {}),\n };\n}\n\nfunction buildScalarField(\n column: SqlColumnIR,\n table: SqlTableIR,\n typeMap: PslTypeMap,\n enumNameMap: ReadonlyMap<string, string>,\n fieldNameMap: TableColumnFieldNameMap | undefined,\n namedTypes: NamedTypeRegistry,\n defaultMapping: DefaultMappingOptions | undefined,\n rawDefaultParser: PslPrinterOptions['parseRawDefault'],\n pkColumns: ReadonlySet<string>,\n isSinglePk: boolean,\n singlePkConstraintName: string | undefined,\n uniqueColumns: ReadonlyMap<string, string | undefined>,\n): PslField {\n const resolvedField = fieldNameMap?.get(column.name);\n const fieldName = resolvedField?.fieldName ?? toFieldName(column.name).name;\n const fieldMap = resolvedField?.fieldMap;\n\n const resolution = typeMap.resolve(column.nativeType, table.annotations);\n\n if ('unsupported' in resolution) {\n const attrs: PslFieldAttribute[] = [];\n if (fieldMap !== undefined) {\n attrs.push(buildMapAttribute('field', fieldMap));\n }\n return {\n kind: 'field',\n name: fieldName,\n typeName: `Unsupported(\"${escapePslString(resolution.nativeType)}\")`,\n optional: column.nullable,\n list: column.many === true,\n attributes: attrs,\n span: SYNTHETIC_SPAN,\n };\n }\n\n let typeName = resolution.pslType;\n const enumPslName = enumNameMap.get(column.nativeType);\n if (enumPslName) {\n typeName = enumPslName;\n }\n if (resolution.nativeTypeAttribute && !enumPslName) {\n typeName = resolveNamedTypeName(namedTypes, resolution);\n }\n\n const attributes: PslFieldAttribute[] = [];\n const isId = isSinglePk && pkColumns.has(column.name);\n if (isId) {\n attributes.push(buildSimpleConstraintFieldAttribute('id', singlePkConstraintName));\n }\n\n if (column.default !== undefined) {\n const parsed = parseColumnDefault(column.default, column.nativeType, rawDefaultParser);\n if (parsed) {\n const result = mapDefault(parsed, defaultMapping);\n if ('attribute' in result) {\n attributes.push(parseDefaultAttributeString(result.attribute));\n }\n // 'comment' fallback (unrecognized raw default) is dropped — the\n // M1 legacy path emitted a `// Raw default: ...` line above the field via\n // `PrinterField.comment`. M2 drops this since it would require comment\n // nodes in the AST.\n }\n }\n\n if (uniqueColumns.has(column.name) && !isId) {\n const uniqueConstraintName = uniqueColumns.get(column.name);\n attributes.push(buildSimpleConstraintFieldAttribute('unique', uniqueConstraintName));\n }\n\n if (fieldMap !== undefined) {\n attributes.push(buildMapAttribute('field', fieldMap));\n }\n\n return {\n kind: 'field',\n name: fieldName,\n typeName,\n optional: column.nullable,\n list: column.many === true,\n attributes,\n span: SYNTHETIC_SPAN,\n };\n}\n\nfunction buildRelationField(\n rel: RelationField,\n hostTableName: string,\n fieldNamesByTable: ReadonlyMap<string, TableColumnFieldNameMap>,\n usedFieldNames: Set<string>,\n): PslField {\n const fieldName = createUniqueFieldName(rel.fieldName, usedFieldNames);\n usedFieldNames.add(fieldName);\n\n const args: PslAttributeArgument[] = [];\n\n if (rel.fields && rel.references) {\n if (rel.relationName) {\n args.push(namedArg('name', `\"${escapePslString(rel.relationName)}\"`));\n }\n args.push(\n namedArg(\n 'fields',\n `[${rel.fields\n .map((columnName) => resolveColumnFieldName(fieldNamesByTable, hostTableName, columnName))\n .join(', ')}]`,\n ),\n );\n args.push(\n namedArg(\n 'references',\n `[${rel.references\n .map((columnName) =>\n resolveColumnFieldName(fieldNamesByTable, rel.referencedTableName ?? '', columnName),\n )\n .join(', ')}]`,\n ),\n );\n if (rel.onDelete) {\n args.push(namedArg('onDelete', rel.onDelete));\n }\n if (rel.onUpdate) {\n args.push(namedArg('onUpdate', rel.onUpdate));\n }\n if (rel.fkName) {\n args.push(namedArg('map', `\"${escapePslString(rel.fkName)}\"`));\n }\n } else if (rel.relationName) {\n args.push(namedArg('name', `\"${escapePslString(rel.relationName)}\"`));\n }\n\n const attrs: PslFieldAttribute[] =\n args.length > 0 ? [buildAttribute('field', 'relation', args)] : [];\n\n return {\n kind: 'field',\n name: fieldName,\n typeName: rel.typeName,\n ...ifDefined('typeNamespaceId', rel.typeNamespaceId),\n ...ifDefined('typeContractSpaceId', rel.typeContractSpaceId),\n optional: rel.optional,\n list: rel.list,\n attributes: attrs,\n span: SYNTHETIC_SPAN,\n };\n}\n\nfunction buildModelConstraintAttribute(\n name: 'id' | 'unique' | 'index',\n fields: readonly string[],\n constraintName?: string,\n): PslModelAttribute {\n const args: PslAttributeArgument[] = [positionalArg(`[${fields.join(', ')}]`)];\n if (constraintName !== undefined) {\n args.push(namedArg('map', `\"${escapePslString(constraintName)}\"`));\n }\n return buildAttribute('model', name, args);\n}\n\nfunction buildSimpleConstraintFieldAttribute(\n name: 'id' | 'unique',\n constraintName: string | undefined,\n): PslFieldAttribute {\n if (constraintName === undefined) {\n return buildAttribute('field', name, []);\n }\n return buildAttribute('field', name, [namedArg('map', `\"${escapePslString(constraintName)}\"`)]);\n}\n\nfunction parseDefaultAttributeString(attributeText: string): PslFieldAttribute {\n // Strip leading \"@default(\" and trailing \")\" — `mapDefault` always returns one\n // top-level positional expression.\n const inner = attributeText.replace(/^@default\\(/, '').replace(/\\)$/, '');\n return buildAttribute('field', 'default', [positionalArg(inner)]);\n}\n\nfunction buildMapAttribute(target: 'model' | 'field' | 'enum', mapName: string): PslAttribute {\n return buildAttribute(target, 'map', [positionalArg(`\"${escapePslString(mapName)}\"`)]);\n}\n\nfunction buildAttribute(\n target: PslAttribute['target'],\n name: string,\n args: readonly PslAttributeArgument[],\n): PslAttribute {\n return {\n kind: 'attribute',\n target,\n name,\n args,\n span: SYNTHETIC_SPAN,\n };\n}\n\nfunction positionalArg(value: string): PslAttributeArgument {\n return { kind: 'positional', value, span: SYNTHETIC_SPAN };\n}\n\nfunction namedArg(name: string, value: string): PslAttributeArgument {\n return { kind: 'named', name, value, span: SYNTHETIC_SPAN };\n}\n\nfunction buildNamedTypeDeclaration(entry: NamedTypeRegistryEntry): PslNamedTypeDeclaration {\n const attribute = buildAttribute(\n 'namedType',\n entry.nativeTypeAttribute.name,\n (entry.nativeTypeAttribute.args ?? []).map(positionalArg),\n );\n return {\n kind: 'namedType',\n name: entry.name,\n baseType: entry.baseType,\n attributes: [attribute],\n span: SYNTHETIC_SPAN,\n };\n}\n\nfunction escapePslString(value: string): string {\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r');\n}\n\n/**\n * Resolves a `SqlColumnIR.default` value into a normalized {@link ColumnDefault}.\n *\n * `SqlSchemaIR` types the column default as `string` (a raw database default\n * expression). Some legacy fixtures and tests still pass already-normalized\n * `ColumnDefault` objects in the same slot, so we accept either shape\n * defensively at runtime.\n */\nfunction parseColumnDefault(\n value: unknown,\n nativeType: string | undefined,\n rawDefaultParser: PslPrinterOptions['parseRawDefault'],\n): ColumnDefault | undefined {\n if (typeof value === 'string') {\n return rawDefaultParser ? rawDefaultParser(value, nativeType) : undefined;\n }\n if (value !== null && typeof value === 'object' && 'kind' in (value as Record<string, unknown>)) {\n return value as ColumnDefault;\n }\n return undefined;\n}\n\nfunction buildFieldNamesByTable(\n tables: Record<string, SqlTableIR>,\n): ReadonlyMap<string, TableColumnFieldNameMap> {\n const fieldNamesByTable = new Map<string, TableColumnFieldNameMap>();\n\n for (const table of Object.values(tables)) {\n const columns = Object.values(table.columns).map((column, index) => {\n const { name, map } = toFieldName(column.name);\n return {\n columnName: column.name,\n desiredFieldName: name,\n fieldMap: map,\n index,\n };\n });\n\n const assignmentOrder = [...columns].sort((left, right) => {\n const mapComparison =\n Number(left.fieldMap !== undefined) - Number(right.fieldMap !== undefined);\n if (mapComparison !== 0) {\n return mapComparison;\n }\n return left.index - right.index;\n });\n\n const usedFieldNames = new Set<string>();\n const tableFieldNames = new Map<string, ResolvedColumnFieldName>();\n\n for (const column of assignmentOrder) {\n const fieldName = createUniqueFieldName(column.desiredFieldName, usedFieldNames);\n usedFieldNames.add(fieldName);\n tableFieldNames.set(column.columnName, {\n fieldName,\n fieldMap: column.fieldMap,\n });\n }\n\n fieldNamesByTable.set(table.name, tableFieldNames);\n }\n\n return fieldNamesByTable;\n}\n\nfunction resolveColumnFieldName(\n fieldNamesByTable: ReadonlyMap<string, TableColumnFieldNameMap>,\n tableName: string,\n columnName: string,\n): string {\n return (\n fieldNamesByTable.get(tableName)?.get(columnName)?.fieldName ?? toFieldName(columnName).name\n );\n}\n\nfunction createUniqueFieldName(desiredName: string, usedFieldNames: ReadonlySet<string>): string {\n if (!usedFieldNames.has(desiredName)) {\n return desiredName;\n }\n\n let counter = 2;\n while (usedFieldNames.has(`${desiredName}${counter}`)) {\n counter++;\n }\n return `${desiredName}${counter}`;\n}\n\nfunction buildTopLevelNameMap(\n sources: Iterable<string>,\n normalize: (source: string) => TopLevelNameResult,\n kind: 'model' | 'enum',\n sourceKind: 'table' | 'enum type',\n): Map<string, TopLevelNameResult> {\n const results = new Map<string, TopLevelNameResult>();\n const normalizedToSources = new Map<string, string[]>();\n\n for (const source of sources) {\n const normalized = normalize(source);\n results.set(source, normalized);\n normalizedToSources.set(normalized.name, [\n ...(normalizedToSources.get(normalized.name) ?? []),\n source,\n ]);\n }\n\n const duplicates = [...normalizedToSources.entries()].filter(\n ([, conflictingSources]) => conflictingSources.length > 1,\n );\n if (duplicates.length > 0) {\n const details = duplicates.map(\n ([normalizedName, conflictingSources]) =>\n `- ${kind} \"${normalizedName}\" from ${sourceKind}s ${conflictingSources\n .map((source) => `\"${source}\"`)\n .join(', ')}`,\n );\n throw new Error(`PSL ${kind} name collisions detected:\\n${details.join('\\n')}`);\n }\n\n return results;\n}\n\nfunction createReservedNamedTypeNames(\n modelNames: ReadonlyMap<string, TopLevelNameResult>,\n): Set<string> {\n const reservedNames = new Set<string>(PSL_SCALAR_TYPE_NAMES);\n\n for (const result of modelNames.values()) {\n reservedNames.add(result.name);\n }\n\n return reservedNames;\n}\n\nfunction seedNamedTypeRegistry(\n schemaIR: SqlSchemaIR,\n typeMap: PslTypeMap,\n enumNameMap: ReadonlyMap<string, string>,\n reservedNames: ReadonlySet<string>,\n): NamedTypeRegistry {\n type Seed = {\n readonly baseType: string;\n readonly desiredName: string;\n readonly nativeTypeAttribute: PslNativeTypeAttribute;\n };\n\n const seeds = new Map<string, Seed>();\n\n for (const tableName of Object.keys(schemaIR.tables).sort()) {\n const table = schemaIR.tables[tableName];\n if (!table) {\n continue;\n }\n\n for (const columnName of Object.keys(table.columns).sort()) {\n const column = table.columns[columnName];\n if (!column) {\n continue;\n }\n\n const resolution = typeMap.resolve(column.nativeType, table.annotations);\n if (\n 'unsupported' in resolution ||\n enumNameMap.has(column.nativeType) ||\n !resolution.nativeTypeAttribute\n ) {\n continue;\n }\n\n const signatureKey = createNamedTypeSignatureKey(resolution);\n if (!seeds.has(signatureKey)) {\n seeds.set(signatureKey, {\n baseType: resolution.pslType,\n desiredName: toNamedTypeName(column.name),\n nativeTypeAttribute: resolution.nativeTypeAttribute,\n });\n }\n }\n }\n\n const registry: NamedTypeRegistry = {\n entriesByKey: new Map<string, NamedTypeRegistryEntry>(),\n usedNames: new Set<string>(reservedNames),\n };\n\n const sortedSeeds = [...seeds.entries()].sort((left, right) => {\n const desiredNameComparison = left[1].desiredName.localeCompare(right[1].desiredName);\n if (desiredNameComparison !== 0) {\n return desiredNameComparison;\n }\n return left[0].localeCompare(right[0]);\n });\n\n for (const [signatureKey, seed] of sortedSeeds) {\n const name = createUniqueFieldName(seed.desiredName, registry.usedNames);\n registry.entriesByKey.set(signatureKey, {\n name,\n baseType: seed.baseType,\n nativeTypeAttribute: seed.nativeTypeAttribute,\n });\n registry.usedNames.add(name);\n }\n\n return registry;\n}\n\nfunction resolveNamedTypeName(\n registry: NamedTypeRegistry,\n resolution: {\n readonly pslType: string;\n readonly nativeType: string;\n readonly typeParams?: Record<string, unknown>;\n readonly nativeTypeAttribute?: PslNativeTypeAttribute;\n },\n): string {\n const key = createNamedTypeSignatureKey(resolution);\n const existing = registry.entriesByKey.get(key);\n if (existing) {\n return existing.name;\n }\n\n throw new Error(`Named type registry was not seeded for native type \"${resolution.nativeType}\"`);\n}\n\nfunction createNamedTypeSignatureKey(resolution: {\n readonly pslType: string;\n readonly nativeType: string;\n readonly typeParams?: Record<string, unknown>;\n readonly nativeTypeAttribute?: PslNativeTypeAttribute;\n}): string {\n return JSON.stringify({\n baseType: resolution.pslType,\n nativeTypeAttribute: resolution.nativeTypeAttribute\n ? {\n name: resolution.nativeTypeAttribute.name,\n args: resolution.nativeTypeAttribute.args ?? null,\n }\n : null,\n });\n}\n\nfunction topologicalSort(\n models: PslModel[],\n tables: Record<string, SqlTableIR>,\n modelNameMap: ReadonlyMap<string, string>,\n): PslModel[] {\n const modelByName = new Map<string, PslModel>();\n for (const model of models) {\n modelByName.set(model.name, model);\n }\n\n const deps = new Map<string, Set<string>>();\n const tableToModel = new Map<string, string>();\n for (const tableName of Object.keys(tables)) {\n const modelName = modelNameMap.get(tableName) as string;\n tableToModel.set(tableName, modelName);\n deps.set(modelName, new Set());\n }\n\n for (const [tableName, table] of Object.entries(tables)) {\n const modelName = tableToModel.get(tableName) as string;\n for (const fk of table.foreignKeys) {\n const refModelName = tableToModel.get(fk.referencedTable);\n if (refModelName && refModelName !== modelName) {\n (deps.get(modelName) as Set<string>).add(refModelName);\n }\n }\n }\n\n const result: PslModel[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n\n const sortedNames = [...deps.keys()].sort();\n\n function visit(name: string): void {\n if (visited.has(name)) return;\n if (visiting.has(name)) return;\n visiting.add(name);\n\n const sortedDeps = [...(deps.get(name) as Set<string>)].sort();\n for (const dep of sortedDeps) {\n visit(dep);\n }\n\n visiting.delete(name);\n visited.add(name);\n result.push(modelByName.get(name) as PslModel);\n }\n\n for (const name of sortedNames) {\n visit(name);\n }\n\n return result;\n}\n","import type { ColumnDefault } from '@prisma-next/contract/types';\nimport type { SqlControlTargetDescriptor } from '@prisma-next/family-sql/control';\nimport { extractCodecControlHooks } from '@prisma-next/family-sql/control';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlTargetInstance,\n MigrationRunner,\n} from '@prisma-next/framework-components/control';\nimport type { StorageColumn } from '@prisma-next/sql-contract/types';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { postgresTargetDescriptorMeta } from '../core/descriptor-meta';\nimport { contractToPostgresDatabaseSchemaNode } from '../core/migrations/contract-to-postgres-database-schema-node';\nimport {\n diffPostgresDatabaseSchema,\n verifyPostgresDatabaseSchema,\n} from '../core/migrations/diff-database-schema';\nimport { createPostgresMigrationPlanner } from '../core/migrations/planner';\nimport { renderDefaultLiteral } from '../core/migrations/planner-ddl-builders';\nimport type { PostgresPlanTargetDetails } from '../core/migrations/planner-target-details';\nimport { createPostgresMigrationRunner } from '../core/migrations/runner';\nimport { PostgresContractSerializer } from '../core/postgres-contract-serializer';\nimport type { PostgresContract } from '../core/postgres-schema';\nimport { PostgresSchemaVerifier } from '../core/postgres-schema-verifier';\nimport { inferPostgresPslContract } from '../core/psl-infer/infer-psl-contract';\nimport { PostgresDatabaseSchemaNode } from '../core/schema-ir/postgres-database-schema-node';\n\nfunction buildNativeTypeExpander(\n frameworkComponents?: ReadonlyArray<TargetBoundComponentDescriptor<'sql', 'postgres'>>,\n) {\n if (!frameworkComponents) {\n return undefined;\n }\n const codecHooks = extractCodecControlHooks(frameworkComponents);\n return (input: {\n readonly nativeType: string;\n readonly codecId?: string;\n readonly typeParams?: Record<string, unknown>;\n }) => {\n if (!input.typeParams) return input.nativeType;\n if (!input.codecId) return input.nativeType;\n const hooks = codecHooks.get(input.codecId);\n if (!hooks?.expandNativeType) return input.nativeType;\n return hooks.expandNativeType(input);\n };\n}\n\nexport function postgresRenderDefault(def: ColumnDefault, column: StorageColumn): string {\n if (def.kind === 'function') {\n return def.expression;\n }\n return renderDefaultLiteral(def.value, column);\n}\n\nconst postgresTargetDescriptor: SqlControlTargetDescriptor<'postgres', PostgresPlanTargetDetails> =\n {\n ...postgresTargetDescriptorMeta,\n contractSerializer: new PostgresContractSerializer(),\n schemaVerifier: new PostgresSchemaVerifier(),\n inferPslContract(schema, describedContracts) {\n PostgresDatabaseSchemaNode.assert(schema);\n return inferPostgresPslContract(schema, describedContracts);\n },\n diffDatabaseSchema(input) {\n return diffPostgresDatabaseSchema({\n contract: input.contract,\n actualSchema: input.schema,\n strict: input.strict,\n typeMetadataRegistry: input.typeMetadataRegistry,\n frameworkComponents: input.frameworkComponents,\n });\n },\n verifyDatabaseSchema(input) {\n return verifyPostgresDatabaseSchema({\n contract: input.contract,\n actualSchema: input.schema,\n strict: input.strict,\n typeMetadataRegistry: input.typeMetadataRegistry,\n frameworkComponents: input.frameworkComponents,\n });\n },\n migrations: {\n createPlanner(adapter: SqlControlAdapter<'postgres'>) {\n return createPostgresMigrationPlanner(adapter);\n },\n createRunner(family) {\n return createPostgresMigrationRunner(family) as MigrationRunner<'sql', 'postgres'>;\n },\n contractToSchema(contract, frameworkComponents) {\n const expander = buildNativeTypeExpander(frameworkComponents);\n const postgresContract = blindCast<\n PostgresContract | null,\n 'the family resolver only binds this hook for a Postgres-target contract'\n >(contract);\n return contractToPostgresDatabaseSchemaNode(postgresContract, {\n annotationNamespace: 'pg',\n ...ifDefined('expandNativeType', expander),\n renderDefault: postgresRenderDefault,\n });\n },\n },\n create(): ControlTargetInstance<'sql', 'postgres'> {\n return {\n familyId: 'sql',\n targetId: 'postgres',\n };\n },\n /**\n * Direct method for SQL-specific usage.\n * @deprecated Use migrations.createPlanner() for CLI compatibility.\n */\n createPlanner(adapter: SqlControlAdapter<'postgres'>) {\n return createPostgresMigrationPlanner(adapter);\n },\n /**\n * Direct method for SQL-specific usage.\n * @deprecated Use migrations.createRunner() for CLI compatibility.\n */\n createRunner(family) {\n return createPostgresMigrationRunner(family);\n },\n };\n\nexport default postgresTargetDescriptor;\n"],"mappings":";;;;;;;;;;;;;;;;AA+BA,MAAM,cAAc;;;;;AAMpB,SAAS,qBAAwD,OAAa;CAC5E,MAAM,SAAkC,CAAC;CACzC,KAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,QAAQ,KAAK,GAC3C,IAAI,QAAQ,QAAQ,QAAQ,KAAA,GAC1B,OAAO,OAAO;MACT,IAAI,MAAM,QAAQ,GAAG,GAC1B,OAAO,OAAO,OAAO,OAAO,CAAC,GAAG,GAAG,CAAC;MAC/B,IAAI,OAAO,QAAQ,UACxB,OAAO,OAAO,qBAAqB,GAA8B;MAEjE,OAAO,OAAO;CAGlB,OAAO,OAAO,OAAO,MAAM;AAC7B;AAEA,SAAgB,8BACd,QAC+C;CAC/C,OAAO,IAAI,wBAAwB,MAAM;AAC3C;AAEA,IAAM,0BAAN,MAAuF;CACxD;CAA7B,YAAY,QAAmD;EAAlC,KAAA,SAAA;CAAmC;;;;;;CAOhE,MAAM,oBACJ,SACmC;EACnC,MAAM,SACJ,QAAQ,cACR,OAAO,KAAK,QAAQ,oBAAoB,QAAQ,UAAU,CAAC,CAAC,MACzD,OAAO,OAAO,oBACjB,KACA;EACF,MAAM,SAAS,QAAQ;EACvB,IAAI,QAAQ,UAAU,KAAA,KAAa,QAAQ,UAAU,QAAQ,KAAK,SAChE,MAAM,IAAI,MACR,sCAAsC,QAAQ,MAAM,iCAAiC,QAAQ,KAAK,QAAQ,EAC5G;EAEF,MAAM,QAAQ,QAAQ,KAAK;EAC3B,MAAM,UAAU,GAAG,YAAY,GAAG,OAAO,GAAG;EAG5C,MAAM,UAAU,UAGd,MAAM,QAAQ,IAAI,QAAQ,KAAK,UAAU,CAAC;EAI5C,MAAM,mBAAmB,KAAK,qCAC5B,QAAQ,KAAK,aACb,QAAQ,mBACV;EACA,IAAI,CAAC,iBAAiB,IAAI,OAAO;EAEjC,MAAM,cAAc,KAAK,2BAA2B,QAAQ,QAAQ,OAAO;EAC3E,IAAI,CAAC,YAAY,IAAI,OAAO;EAE5B,MAAM,KAAK,YAAY,QAAQ,OAAO;EACtC,MAAM,eAAe,MAAM,KAAK,oBAAoB,QAAQ,QAAQ,mBAAmB;EACvF,IAAI,CAAC,aAAa,IAAI,OAAO;EAC7B,MAAM,iBAAiB,MAAM,KAAK,OAAO,WAAW;GAAE;GAAQ;EAAM,CAAC;EAErE,MAAM,cAAc,KAAK,0BAA0B,gBAAgB,QAAQ,IAAI;EAC/E,IAAI,CAAC,YAAY,IAAI,OAAO;EAE5B,MAAM,sBAAsB,KAAK,yBAAyB,gBAAgB,QAAQ,IAAI;EACtF,MAAM,aAAa,QAAQ,KAAK,QAAQ,gBAAgB,QAAQ,KAAK,YAAY;EACjF,MAAM,iBAAiB,uBAAuB,QAAQ,KAAK,UAAU,QAAQ,CAAC;EAC9E,IAAI;EAEJ,IAAI,gBACF,aAAa;GAAE,oBAAoB;GAAG,oBAAoB,CAAC;EAAE;OACxD;GACL,MAAM,cAAc,MAAM,KAAK,UAAU,QAAQ,SAAS,OAAO;GACjE,IAAI,CAAC,YAAY,IAAI,OAAO;GAC5B,aAAa,YAAY;EAC3B;EAMA,IAAI,UAAU,cAAc;GAC1B,MAAM,aAAa,MAAM,KAAK,OAAO,WAAW;IAC9C;IACA,UAAU,QAAQ;GACpB,CAAC;GACD,MAAM,qBAAqB,KAAK,OAAO,aAAa;IAClD,UAAU,QAAQ;IAClB,QAAQ;IACR,QAAQ,QAAQ,sBAAsB;IACtC,qBAAqB,QAAQ;GAC/B,CAAC;GACD,IAAI,CAAC,mBAAmB,IACtB,OAAO,cAAc,wBAAwB,mBAAmB,SAAS;IACvE,KAAK;IACL,MAAM,EACJ,QAAQ,CACN,GAAG,mBAAmB,OAAO,QAC7B,GAAG,mBAAmB,OAAO,gBAC/B,EACF;GACF,CAAC;EAEL;EAEA,MAAM,qBAAqB,QAAQ,KAAK,sBAAsB,CAAC;EAC/D,MAAM,qBAAqB,IAAI,IAAI,gBAAgB,cAAc,CAAC,CAAC;EACnE,MAAM,6BAA6B,mBAAmB,OAAO,OAAO,mBAAmB,IAAI,EAAE,CAAC;EAI9F,IAAI,EAFF,cAAc,WAAW,uBAAuB,KAAK,6BAElC;GACnB,MAAM,eAAe,MAAM,KAAK,aAAa,QAAQ,SAAS,gBAAgB,KAAK;GACnF,IAAI,CAAC,aAAa,IAAI,OAAO;GAC7B,MAAM,KAAK,oBACT,QACA,SACA,WAAW,oBACX,QAAQ,MACV;EACF;EAEA,OAAO,cAAc;GACnB,mBAAmB,QAAQ;GAC3B,oBAAoB,WAAW;EACjC,CAAC;CACH;CAEA,MAAM,QAAQ,SAKqB;EACjC,MAAM,SAAS,QAAQ;EACvB,MAAM,kBAAkB,QAAQ;EAEhC,IAAI,gBAAgB,WAAW,GAC7B,OAAO,GAAG,EAAE,iBAAiB,CAAC,EAAE,CAAC;EAGnC,MAAM,KAAK,iBAAiB,MAAM;EAClC,IAAI,YAAY;EAChB,IAAI;GACF,MAAM,kBAGD,CAAC;GACN,KAAK,MAAM,gBAAgB,iBAAiB;IAC1C,MAAM,QAAQ,aAAa,SAAS,aAAa,KAAK;IACtD,MAAM,SAAS,MAAM,KAAK,oBAAoB;KAAE,GAAG;KAAc;KAAQ;IAAM,CAAC;IAChF,IAAI,CAAC,OAAO,IACV,OAAO,MAAM;KAAE,GAAG,OAAO;KAAS,cAAc;IAAM,CAAC;IAEzD,gBAAgB,KAAK;KAAE;KAAO,OAAO,OAAO;IAAM,CAAC;GACrD;GAEA,MAAM,KAAK,kBAAkB,MAAM;GACnC,YAAY;GACZ,OAAO,GAAG,EAAE,gBAAgB,CAAC;EAC/B,UAAU;GACR,IAAI,CAAC,WACH,MAAM,KAAK,oBAAoB,MAAM;EAEzC;CACF;CAEA,MAAc,UACZ,QACA,SACA,KACmE;EACnE,MAAM,SAAS,QAAQ;EACvB,MAAM,eAAe,QAAQ,cAAc;EAC3C,MAAM,gBAAgB,QAAQ,eAAe;EAC7C,MAAM,iBAAiB,QAAQ,sBAAsB;EAErD,IAAI,qBAAqB;EACzB,MAAM,qBAAkF,CAAC;EACzF,KAAK,MAAM,aAAa,KAAK;GAC3B,QAAQ,WAAW,mBAAmB,SAAS;GAC/C,IAAI;IAEF,IAAI,iBAAiB;SAKf,MAJoC,KAAK,yBAC3C,QACA,UAAU,SACZ,GAC+B;MAC7B,mBAAmB,KAAK,KAAK,sCAAsC,SAAS,CAAC;MAC7E;KACF;;IAIF,IAAI,cAAc;KAChB,MAAM,iBAAiB,MAAM,KAAK,oBAChC,QACA,UAAU,UACV,WACA,UACF;KACA,IAAI,CAAC,eAAe,IAClB,OAAO;IAEX;IAEA,MAAM,gBAAgB,MAAM,KAAK,gBAAgB,QAAQ,UAAU,SAAS,SAAS;IACrF,IAAI,CAAC,cAAc,IACjB,OAAO;IAIT,IAAI,eAAe;KACjB,MAAM,kBAAkB,MAAM,KAAK,oBACjC,QACA,UAAU,WACV,WACA,WACF;KACA,IAAI,CAAC,gBAAgB,IACnB,OAAO;IAEX;IAEA,mBAAmB,KAAK,SAAS;IACjC,sBAAsB;GACxB,UAAU;IACR,QAAQ,WAAW,sBAAsB,SAAS;GACpD;EACF;EACA,OAAO,GAAG;GAAE;GAAoB;EAAmB,CAAC;CACtD;CAEA,MAAc,oBACZ,QACA,UACkD;EAClD,MAAM,iBAAiB,EAAE,SAAS;EAElC,MAAM,CAAC,aAAa,GAAG,gBADE,KAAK,OAAO,6BACiB;EACtD,IAAI,gBAAgB,KAAA,GAClB,MAAM,IAAI,MAAM,6DAA6D;EAE/E,MAAM,KAAK,iBAAiB,QAAQ,MAAM,KAAK,OAAO,SAAS,aAAa,cAAc,CAAC;EAC3F,MAAM,kBAAkB,MAAM,KAAK,wBAAwB,MAAM;EACjE,IAAI,CAAC,gBAAgB,IACnB,OAAO;EAET,KAAK,MAAM,SAAS,cAClB,MAAM,KAAK,iBAAiB,QAAQ,MAAM,KAAK,OAAO,SAAS,OAAO,cAAc,CAAC;EAEvF,OAAO,OAAO;CAChB;CAEA,MAAc,wBACZ,QACkD;EAClD,MAAM,SAAS,MAAM,OAAO,MAC1B;;;oCAIF;EACA,IAAI,OAAO,KAAK,WAAW,GACzB,OAAO,OAAO;EAEhB,MAAM,UAAU,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,WAAW,CAAC;EACjE,IAAI,QAAQ,IAAI,OAAO,GACrB,OAAO,OAAO;EAEhB,OAAO,cACL,uBACA,gSAGA,EACE,MAAM;GACJ,OAAO;GACP,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,KAAK;EAC7B,EACF,CACF;CACF;CAEA,MAAc,oBACZ,QACA,OACA,WACA,OACkD;EAClD,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,SAAS,MAAM,OAAO,MAAM,KAAK,KAAK,KAAK,UAAU,CAAC,CAAC;GAC7D,IAAI,CAAC,KAAK,iBAAiB,OAAO,IAAI,GAEpC,OAAO,cADM,UAAU,aAAa,oBAAoB,oBAGtD,aAAa,UAAU,GAAG,iBAAiB,MAAM,IAAI,KAAK,eAC1D,EACE,MAAM;IACJ,aAAa,UAAU;IACvB;IACA,iBAAiB,KAAK;GACxB,EACF,CACF;EAEJ;EACA,OAAO,OAAO;CAChB;CAEA,MAAc,gBACZ,QACA,OACA,WACkD;EAClD,KAAK,MAAM,QAAQ,OACjB,IAAI;GACF,MAAM,OAAO,MAAM,KAAK,KAAK,KAAK,UAAU,CAAC,CAAC;EAChD,SAAS,OAAgB;GACvB,IAAI,cAAc,GAAG,KAAK,GACxB,OAAO,cACL,oBACA,aAAa,UAAU,GAAG,4BAA4B,KAAK,eAC3D;IACE,KAAK,MAAM;IACX,MAAM;KACJ,aAAa,UAAU;KACvB,iBAAiB,KAAK;KACtB,KAAK,KAAK;KACV,UAAU,MAAM;KAChB,YAAY,MAAM;KAClB,OAAO,MAAM;KACb,QAAQ,MAAM;KACd,QAAQ,MAAM;IAChB;GACF,CACF;GAEF,MAAM;EACR;EAEF,OAAO,OAAO;CAChB;CAEA,iBAAyB,MAAmD;EAC1E,IAAI,CAAC,QAAQ,KAAK,WAAW,GAC3B,OAAO;EAET,MAAM,WAAW,KAAK;EACtB,MAAM,aAAa,WAAW,OAAO,OAAO,QAAQ,CAAC,CAAC,KAAK,KAAA;EAC3D,IAAI,OAAO,eAAe,WACxB,OAAO;EAET,IAAI,OAAO,eAAe,UACxB,OAAO,eAAe;EAExB,IAAI,OAAO,eAAe,UAAU;GAClC,MAAM,QAAQ,WAAW,YAAY;GAErC,IAAI,UAAU,OAAO,UAAU,UAAU,UAAU,KACjD,OAAO;GAET,IAAI,UAAU,OAAO,UAAU,WAAW,UAAU,KAClD,OAAO;GAGT,OAAO,WAAW,SAAS;EAC7B;EACA,OAAO,QAAQ,UAAU;CAC3B;CAEA,MAAc,yBACZ,QACA,OACkB;EAClB,IAAI,MAAM,WAAW,GACnB,OAAO;EAET,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,SAAS,MAAM,OAAO,MAAM,KAAK,KAAK,KAAK,UAAU,CAAC,CAAC;GAC7D,IAAI,CAAC,KAAK,iBAAiB,OAAO,IAAI,GACpC,OAAO;EAEX;EACA,OAAO;CACT;CAEA,sCACE,WACsD;EAEtD,MAAM,aAAa,UAAU,OAAO,qBAAqB,UAAU,IAAI,IAAI,KAAA;EAG3E,MAAM,aAAa,OAAO,OAAO;GAC/B,SAAS;GACT,QAAQ;EACV,CAAC;EAGD,MAAM,aAAa,OAAO,OAAO;GAC/B,GAAI,cAAc,CAAC;GACnB,QAAQ;EACV,CAAC;EAGD,MAAM,kBAAkB,OAAO,OAAO,CAAC,GAAG,UAAU,SAAS,CAAC;EAE9D,OAAO,OAAO,OAAO;GACnB,IAAI,UAAU;GACd,OAAO,UAAU;GACjB,GAAG,UAAU,WAAW,UAAU,OAAO;GACzC,gBAAgB,UAAU;GAC1B,QAAQ,UAAU;GAClB,UAAU,OAAO,OAAO,CAAC,CAAC;GAC1B,SAAS,OAAO,OAAO,CAAC,CAAC;GACzB,WAAW;GACX,GAAG,UAAU,QAAQ,UAAU,QAAQ,aAAa,aAAa,KAAA,CAAS;EAC5E,CAAC;CACH;CAEA,yBACE,QACA,MACS;EACT,IAAI,CAAC,QACH,OAAO;EAET,IAAI,OAAO,gBAAgB,KAAK,YAAY,aAC1C,OAAO;EAET,IAAI,KAAK,YAAY,eAAe,OAAO,gBAAgB,KAAK,YAAY,aAC1E,OAAO;EAET,OAAO;CACT;CAEA,2BACE,QACA,YACyC;EACzC,MAAM,iBAAiB,IAAI,IAAI,OAAO,uBAAuB;EAC7D,KAAK,MAAM,aAAa,YACtB,IAAI,CAAC,eAAe,IAAI,UAAU,cAAc,GAC9C,OAAO,cACL,oBACA,aAAa,UAAU,GAAG,cAAc,UAAU,eAAe,oCACjE;GACE,KAAK,uBAAuB,OAAO,wBAAwB,KAAK,IAAI,EAAE;GACtE,MAAM;IACJ,aAAa,UAAU;IACvB,gBAAgB,UAAU;IAC1B,gBAAgB,OAAO;GACzB;EACF,CACF;EAGJ,OAAO,OAAO;CAChB;CAEA,0BACE,QACA,MACyC;EACzC,MAAM,SAAS,KAAK,UAAU;EAC9B,IAAI,CAAC,QAIH,OAAO,OAAO;EAGhB,IAAI,CAAC,QACH,OAAO,cACL,0BACA,yDAAyD,OAAO,YAAY,IAC5E,EACE,MAAM,EACJ,2BAA2B,OAAO,YACpC,EACF,CACF;EAEF,IAAI,OAAO,gBAAgB,OAAO,aAChC,OAAO,cACL,0BACA,6BAA6B,OAAO,YAAY,gCAAgC,OAAO,YAAY,KACnG,EACE,MAAM;GACJ,mBAAmB,OAAO;GAC1B,2BAA2B,OAAO;EACpC,EACF,CACF;EAEF,IAAI,OAAO,eAAe,OAAO,gBAAgB,OAAO,aACtD,OAAO,cACL,0BACA,0CAA0C,OAAO,YAAY,6CAA6C,OAAO,YAAY,KAC7H,EACE,MAAM;GACJ,mBAAmB,OAAO;GAC1B,2BAA2B,OAAO;EACpC,EACF,CACF;EAEF,OAAO,OAAO;CAChB;CAEA,qCACE,aACA,UACyC;EACzC,IAAI,YAAY,gBAAgB,SAAS,QAAQ,aAC/C,OAAO,cACL,iCACA,kCAAkC,YAAY,YAAY,mDAAmD,SAAS,QAAQ,YAAY,KAC1I,EACE,MAAM;GACJ,iBAAiB,YAAY;GAC7B,qBAAqB,SAAS,QAAQ;EACxC,EACF,CACF;EAEF,IACE,YAAY,eACZ,SAAS,eACT,YAAY,gBAAgB,SAAS,aAErC,OAAO,cACL,iCACA,kCAAkC,YAAY,YAAY,mDAAmD,SAAS,YAAY,KAClI,EACE,MAAM;GACJ,iBAAiB,YAAY;GAC7B,qBAAqB,SAAS;EAChC,EACF,CACF;EAEF,OAAO,OAAO;CAChB;CAEA,MAAc,aACZ,QACA,SACA,gBACA,OACkD;EAClD,MAAM,cAAc;GAClB,aAAa,QAAQ,KAAK,YAAY;GACtC,aACE,QAAQ,KAAK,YAAY,eACzB,QAAQ,oBAAoB,eAC5B,QAAQ,KAAK,YAAY;GAC3B,YAAY,QAAQ,KAAK,sBAAsB,CAAC;EAClD;EACA,IAAI,CAAC,gBAAgB;GACnB,MAAM,KAAK,OAAO,WAAW;IAAE;IAAQ;IAAO;GAAY,CAAC;GAC3D,OAAO,OAAO;EAChB;EAOA,IAAI,CAAC,MANiB,KAAK,OAAO,aAAa;GAC7C;GACA;GACA,cAAc,eAAe;GAC7B;EACF,CAAC,GAEC,OAAO,cACL,sBACA,sEACA,EACE,MAAM;GACJ;GACA,qBAAqB,eAAe;GACpC,wBAAwB,QAAQ,KAAK,YAAY;EACnD,EACF,CACF;EAEF,OAAO,OAAO;CAChB;CAEA,MAAc,oBACZ,QACA,SACA,oBACA,eACe;EAEf,MAAM,QADO,QAAQ,KACF;EACnB,MAAM,QAAQ,QAAQ;EACtB,MAAM,eAAe,MAAM,QAAQ,KAAK,SAAS,MAAM,KAAK,gBAAgB,CAAC;EAC7E,IAAI,iBAAiB,eACnB,MAAM,IAAI,MACR,yCAAyC,cAAc,yDAAyD,aAAa,EAC/H;EAKF,IAAI,SAAS;EACb,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,UAAU,mBAAmB,MAAM,QAAQ,SAAS,KAAK,cAAc;GAC7E,UAAU,KAAK;GACf,MAAM,KAAK,OAAO,iBAAiB;IACjC;IACA;IACA,OAAO;KACL,QAAQ,GAAG,KAAK,KAAK,IAAI,KAAK;KAC9B,MAAM,KAAK;KACX,IAAI,KAAK;KACT,eAAe,KAAK;KACpB,eAAe,KAAK;KACpB,YAAY;IACd;GACF,CAAC;EACH;CACF;CAEA,MAAc,YACZ,QACA,KACe;EACf,MAAM,OAAO,MAAM,8CAA8C,CAAC,GAAG,CAAC;CACxE;CAEA,MAAc,iBACZ,QACe;EACf,MAAM,OAAO,MAAM,OAAO;CAC5B;CAEA,MAAc,kBACZ,QACe;EACf,MAAM,OAAO,MAAM,QAAQ;CAC7B;CAEA,MAAc,oBACZ,QACe;EACf,MAAM,OAAO,MAAM,UAAU;CAC/B;CAEA,MAAc,iBACZ,QACA,WACe;EACf,MAAM,OAAO,MAAM,UAAU,KAAK,UAAU,MAAM;CACpD;AACF;;;;;;;;;;;;;;;;;;ACxqBA,IAAa,yBAAb,cAA4C,sBAG1C;CACA,sBACE,UACwB;EACxB,OAAO,CAAC;CACV;CAEA,uBACE,UACwB;EACxB,OAAO,CAAC;CACV;AACF;;;AClCA,MAAM,+BAAiE,EACrE,qBAAqB,+CACvB;AAEA,SAAS,2BAA2B,YAA4B;CAC9D,OAAO,wBAAwB,KAAK,UAAU,UAAU,EAAE;AAC5D;AAEA,SAAgB,+BAAsD;CACpE,OAAO;EACL,oBAAoB;EACpB,2BAA2B;CAC7B;AACF;;;ACRA,MAAM,kBAA0C;CAC9C,MAAM;CACN,MAAM;CACN,SAAS;CACT,MAAM;CACN,SAAS;CACT,MAAM;CACN,QAAQ;CACR,QAAQ;CACR,oBAAoB;CACpB,SAAS;CACT,SAAS;CACT,aAAa;CACb,4BAA4B;CAC5B,OAAO;CACP,OAAO;AACT;AAEA,MAAM,yBAGF;CACF,qBAAqB;EAAE,SAAS;EAAU,eAAe;CAAa;CACtE,WAAW;EAAE,SAAS;EAAU,eAAe;CAAU;CACzD,MAAM;EAAE,SAAS;EAAU,eAAe;CAAU;CACpD,SAAS;EAAE,SAAS;EAAU,eAAe;CAAa;CAC1D,MAAM;EAAE,SAAS;EAAU,eAAe;CAAU;CACpD,MAAM;EAAE,SAAS;EAAO,eAAe;CAAc;CACrD,UAAU;EAAE,SAAS;EAAO,eAAe;CAAc;CACzD,QAAQ;EAAE,SAAS;EAAS,eAAe;CAAU;CACrD,MAAM;EAAE,SAAS;EAAS,eAAe;CAAU;CACnD,WAAW;EAAE,SAAS;EAAY,eAAe;CAAe;CAChE,+BAA+B;EAAE,SAAS;EAAY,eAAe;CAAe;CACpF,MAAM;EAAE,SAAS;EAAY,eAAe;CAAU;CACtD,MAAM;EAAE,SAAS;EAAY,eAAe;CAAU;CACtD,0BAA0B;EAAE,SAAS;EAAY,eAAe;CAAU;CAC1E,QAAQ;EAAE,SAAS;EAAY,eAAe;CAAY;CAC1D,uBAAuB;EAAE,SAAS;EAAY,eAAe;CAAY;CACzE,MAAM;EAAE,SAAS;EAAQ,eAAe;CAAU;AACpD;AAEA,MAAM,6BAGF;CACF,qBAAqB;EAAE,SAAS;EAAU,eAAe;CAAa;CACtE,WAAW;EAAE,SAAS;EAAU,eAAe;CAAU;CACzD,MAAM;EAAE,SAAS;EAAU,eAAe;CAAU;CACpD,SAAS;EAAE,SAAS;EAAU,eAAe;CAAa;CAC1D,SAAS;EAAE,SAAS;EAAW,eAAe;CAAa;CAC3D,WAAW;EAAE,SAAS;EAAY,eAAe;CAAe;CAChE,aAAa;EAAE,SAAS;EAAY,eAAe;CAAiB;CACpE,MAAM;EAAE,SAAS;EAAY,eAAe;CAAU;CACtD,QAAQ;EAAE,SAAS;EAAY,eAAe;CAAY;AAC5D;AAEA,MAAM,6BAA6B;AAEnC,SAAS,mBAAmB,KAA6B,KAAiC;CACxF,OAAO,OAAO,OAAO,KAAK,GAAG,IAAI,IAAI,OAAO,KAAA;AAC9C;AAEA,SAAS,kBAAqB,KAAwB,KAA4B;CAChF,OAAO,OAAO,OAAO,KAAK,GAAG,IAAI,IAAI,OAAO,KAAA;AAC9C;AAEA,SAAS,0BAA0B,MAAc,MAAkD;CACjG,OAAO,QAAQ,KAAK,SAAS,IAAI;EAAE;EAAM;CAAK,IAAI,EAAE,KAAK;AAC3D;AAEA,SAAS,uBAAuB,QAAmC;CACjE,OAAO,OACJ,MAAM,GAAG,CAAC,CACV,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC,CAC1B,QAAQ,SAAS,KAAK,SAAS,CAAC;AACrC;AAEA,SAAgB,sBAAsB,eAAiD;CACrF,OAAO,EACL,QAAQ,YAAuC;EAC7C,IAAI,eAAe,IAAI,UAAU,GAC/B,OAAO;GAAE,SAAS;GAAY;EAAW;EAG3C,MAAM,aAAa,WAAW,MAAM,0BAA0B;EAC9D,IAAI,YAAY;GACd,MAAM,GAAG,WAAW,YAAY,SAAS,MAAM;GAC/C,MAAM,WAAW,kBAAkB,4BAA4B,QAAQ;GACvE,IAAI,UACF,OAAO;IACL,SAAS,SAAS;IAClB;IACA,YAAY;KAAE;KAAU;IAAO;IAC/B,qBAAqB,0BACnB,SAAS,eACT,uBAAuB,MAAM,CAC/B;GACF;EAEJ;EAEA,MAAM,gBAAgB,kBAAkB,wBAAwB,UAAU;EAC1E,IAAI,eACF,OAAO;GACL,SAAS,cAAc;GACvB;GACA,qBAAqB,0BAA0B,cAAc,aAAa;EAC5E;EAGF,MAAM,UAAU,mBAAmB,iBAAiB,UAAU;EAC9D,IAAI,SACF,OAAO;GACL;GACA;EACF;EAGF,OAAO;GAAE,aAAa;GAAM;EAAW;CACzC,EACF;AACF;;;AC9EA,MAAM,iBAA0B;CAC9B,OAAO;EAAE,QAAQ;EAAG,MAAM;EAAG,QAAQ;CAAE;CACvC,KAAK;EAAE,QAAQ;EAAG,MAAM;EAAG,QAAQ;CAAE;AACvC;AAEA,MAAM,wBAAwB,IAAI,IAAI;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;;;;AAoCD,SAAS,wBACP,oBACgD;CAChD,MAAM,yBAAS,IAAI,IAAuC;CAC1D,KAAK,MAAM,SAAS,oBAClB,KAAK,MAAM,cAAc,mBAAmB,MAAM,SAAS,OAAO,GAChE,OAAO,IAAI,cAAc,UAAU,GAAG,KAAK;CAG/C,OAAO;AACT;AAiBA,SAAS,wBACP,OACA,aACA,WAC8B;CAC9B,MAAM,kBAAkB,MAAM,SAAS,OAAO,WAAW;CACzD,IAAI,oBAAoB,KAAA,GACtB;CAGF,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,gBAAgB,MAAM,GAAG;EACvE,MAAM,UAAU,UAAyD,MAAM,OAAO;EACtF,IAAI,QAAQ,gBAAgB,eAAe,QAAQ,UAAU,WAC3D;EAGF,MAAM,qCAAqB,IAAI,IAAqC;EACpE,KAAK,MAAM,CAAC,WAAW,iBAAiB,OAAO,QAAQ,QAAQ,MAAM,GACnE,mBAAmB,IAAI,aAAa,QAAQ,EAAE,UAAU,CAAC;EAG3D,OAAO;GAAE,SAAS,MAAM;GAAS;GAAa;GAAW;EAAmB;CAC9E;AAGF;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAS,mBACP,QACA,QACsB;CACtB,MAAM,eAA2C,CAAC;CAClD,MAAM,wCAAwB,IAAI,IAA6B;CAC/D,MAAM,8CAA8B,IAAI,IAAqC;CAE7E,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,MAAM,GAAG;EACvD,MAAM,kBAAqC,CAAC;EAE5C,KAAK,MAAM,MAAM,MAAM,aAAa;GAClC,IAAI,GAAG,qBAAqB,KAAA,GAAW;IACrC,MAAM,QAAQ,OAAO,IACnB,cAAc;KACZ,aAAa,GAAG;KAChB,YAAY;KACZ,YAAY,GAAG;IACjB,CAAC,CACH;IACA,IAAI,UAAU,KAAA,GAAW;KACvB,MAAM,SAAS,wBAAwB,OAAO,GAAG,kBAAkB,GAAG,eAAe;KACrF,IAAI,WAAW,KAAA,GACb,MAAM,IAAI,MACR,6CAA6C,MAAM,QAAQ,6BAC1C,GAAG,iBAAiB,GAAG,GAAG,gBAAgB,kJAG7D;KAGF,IAAI,CAAC,4BAA4B,IAAI,GAAG,eAAe,GACrD,4BAA4B,IAAI,GAAG,iBAAiB,OAAO,kBAAkB;KAG/E,MAAM,YAAY,wBAAwB,GAAG,SAAS,GAAG,eAAe;KACxE,MAAM,WAAW,GAAG,QAAQ,MACzB,eAAe,MAAM,QAAQ,WAAW,EAAE,YAAY,KACzD;KACA,MAAM,gBAA+B;MACnC,GAAG,wBAAwB,WAAW,OAAO,WAAW,IAAI,QAAQ;MACpE,iBAAiB,OAAO;MACxB,qBAAqB,OAAO;KAC9B;KAEA,MAAM,oBAAoB,sBAAsB,IAAI,SAAS;KAC7D,IAAI,mBACF,kBAAkB,KAAK,aAAa;UAEpC,sBAAsB,IAAI,WAAW,CAAC,aAAa,CAAC;KAEtD;IACF;GACF;GAKA,IAAI,OAAO,GAAG,qBAAqB,KAAA,GACjC,gBAAgB,KAAK,EAAE;EAE3B;EAEA,aAAa,aACX,gBAAgB,WAAW,MAAM,YAAY,SACzC,QACA;GAAE,GAAG;GAAO,aAAa;EAAgB;CACjD;CAEA,OAAO;EAAE,QAAQ;EAAc;EAAuB;CAA4B;AACpF;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,yBACd,MACA,oBACgB;CAChB,MAAM,aAAa,OAAO,OAAO,KAAK,UAAU;CAChD,MAAM,SAAS,wBAAwB,sBAAsB,CAAC,CAAC;CAK/D,MAAM,gBAAgB,CAAC,GAAG,IAAI,IAAI,WAAW,SAAS,OAAO,GAAG,mBAAmB,CAAC,CAAC;CACrF,IAAI,cAAc,SAAS,GAAG;EAC5B,MAAM,QAAQ,cAAc,KAAK,IAAI;EACrC,MAAM,IAAI,MACR,uEAAuE,MAAM,kUAK/E;CACF;CASA,MAAM,SAAqC,CAAC;CAC5C,KAAK,MAAM,aAAa,YACtB,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,UAAU,MAAM,GAAG;EACjE,IACE,OAAO,IACL,cAAc;GACZ,aAAa,UAAU;GACvB,YAAY;GACZ,YAAY;EACd,CAAC,CACH,GAEA;EAEF,IAAI,OAAO,eAAe,KAAA,GACxB,MAAM,IAAI,MACR,yCAAyC,UAAU,2JAGrD;EAEF,OAAO,aAAa;CACtB;CAGF,MAAM,EACJ,QAAQ,gBACR,uBACA,gCACE,mBAAmB,QAAQ,MAAM;CASrC,OAAO,oBAAoB,EARK,QAAQ,eAQN,GAAG;EALnC,SAAS,sCAAsB,IAAI,IAAI,CAAC;EACxC,gBAAgB,6BAA6B;EAC7C;CAGyC,GAAG;EAC5C;EACA;CACF,CAAC;AACH;AAEA,SAAS,oBACP,UACA,SACA,kBAIgB;CAChB,MAAM,EAAE,SAAS,gBAAgB,iBAAiB,qBAAqB;CACvE,MAAM,EAAE,uBAAuB,gCAAgC;CAE/D,MAAM,aAAa,qBACjB,OAAO,KAAK,SAAS,MAAM,GAC3B,aACA,SACA,OACF;CAEA,MAAM,eAAe,IAAI,IACvB,CAAC,GAAG,UAAU,CAAC,CAAC,KAAK,CAAC,WAAW,YAAY,CAAC,WAAW,OAAO,IAAI,CAAC,CACvE;CACA,MAAM,yBAAyB,6BAA6B,UAAU;CAMtE,MAAM,oBAAoB,IAAI,IAAI,CAChC,GAAG,6BACH,GAAG,uBAAuB,SAAS,MAAM,CAC3C,CAAC;CACD,MAAM,EAAE,qBAAqB,eAAe,SAAS,QAAQ,YAAY;CACzE,MAAM,aAAa,sBAAsB,UAAU,yBAAS,IAAI,IAAI,GAAG,sBAAsB;CAE7F,MAAM,SAAqB,CAAC;CAC5B,KAAK,MAAM,SAAS,OAAO,OAAO,SAAS,MAAM,GAC/C,OAAO,KACL,WACE,OACA,yBACA,IAAI,IAAI,GACR,mBACA,YACA,gBACA,kBACA,CACE,GAAI,iBAAiB,IAAI,MAAM,IAAI,KAAK,CAAC,GACzC,GAAI,sBAAsB,IAAI,MAAM,IAAI,KAAK,CAAC,CAChD,CACF,CACF;CAGF,MAAM,eAAe,gBAAgB,QAAQ,SAAS,QAAQ,YAAY;CAE1E,MAAM,mBAAmB,CAAC,GAAG,WAAW,aAAa,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,MACtE,EAAE,KAAK,cAAc,EAAE,IAAI,CAC7B;CACA,MAAM,QACJ,iBAAiB,SAAS,IACtB;EACE,MAAM;EACN,cAAc,iBAAiB,IAAI,yBAAyB;EAC5D,MAAM;CACR,IACA,KAAA;CAuBN,OAAO;EAdL,MAAM;EACN,UAAU;EACV,YAAY,CACV,iBAAiB;GACf,MAAM;GACN,MAAM;GACN,SAAS,wBAAwB,cAAc,CAAC,GAAG,CAAC,CAAC;GACrD,MAAM;EACR,CAAC,CACH;EACA,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;EACzB,MAAM;CAGC;AACX;AAEA,SAAS,WACP,OACA,SACA,aACA,mBACA,YACA,gBACA,kBACA,gBACU;CACV,MAAM,EAAE,MAAM,WAAW,KAAK,YAAY,YAAY,MAAM,IAAI;CAChE,MAAM,eAAe,kBAAkB,IAAI,MAAM,IAAI;CAErD,MAAM,YAAY,IAAI,IAAI,MAAM,YAAY,WAAW,CAAC,CAAC;CACzD,MAAM,aAAa,UAAU,SAAS;CACtC,MAAM,yBAAyB,aAAa,MAAM,YAAY,OAAO,KAAA;CAErE,MAAM,gCAAgB,IAAI,IAAgC;CAC1D,KAAK,MAAM,UAAU,MAAM,SACzB,IAAI,OAAO,QAAQ,WAAW,GAAG;EAC/B,MAAM,CAAC,aAAa,MAAM,OAAO;EACjC,MAAM,yBAAyB,cAAc,IAAI,UAAU;EAC3D,IAAI,CAAC,cAAc,IAAI,UAAU,KAAM,2BAA2B,KAAA,KAAa,OAAO,MACpF,cAAc,IAAI,YAAY,OAAO,IAAI;CAE7C;CAGF,MAAM,SAAqB,CAAC;CAC5B,KAAK,MAAM,UAAU,OAAO,OAAO,MAAM,OAAO,GAC9C,OAAO,KACL,iBACE,QACA,OACA,SACA,aACA,cACA,YACA,gBACA,kBACA,WACA,YACA,wBACA,aACF,CACF;CAGF,MAAM,iBAAiB,IAAI,IAAI,OAAO,KAAK,UAAU,MAAM,IAAI,CAAC;CAChE,KAAK,MAAM,OAAO,gBAChB,OAAO,KAAK,mBAAmB,KAAK,MAAM,MAAM,mBAAmB,cAAc,CAAC;CAGpF,MAAM,kBAAuC,CAAC;CAE9C,IAAI,MAAM,cAAc,MAAM,WAAW,QAAQ,SAAS,GAAG;EAC3D,MAAM,eAAe,MAAM,WAAW,QAAQ,KAAK,eACjD,uBAAuB,mBAAmB,MAAM,MAAM,UAAU,CAClE;EACA,gBAAgB,KAAK,8BAA8B,MAAM,cAAc,MAAM,WAAW,IAAI,CAAC;CAC/F;CAEA,KAAK,MAAM,UAAU,MAAM,SACzB,IAAI,OAAO,QAAQ,SAAS,GAAG;EAC7B,MAAM,mBAAmB,OAAO,QAAQ,KAAK,eAC3C,uBAAuB,mBAAmB,MAAM,MAAM,UAAU,CAClE;EACA,gBAAgB,KAAK,8BAA8B,UAAU,kBAAkB,OAAO,IAAI,CAAC;CAC7F;CAGF,KAAK,MAAM,SAAS,MAAM,SACxB,IAAI,CAAC,MAAM,QAAQ;EACjB,MAAM,kBAAkB,MAAM,QAAQ,KAAK,eACzC,uBAAuB,mBAAmB,MAAM,MAAM,UAAU,CAClE;EACA,gBAAgB,KAAK,8BAA8B,SAAS,iBAAiB,MAAM,IAAI,CAAC;CAC1F;CAGF,IAAI,SACF,gBAAgB,KAAK,kBAAkB,SAAS,OAAO,CAAC;CAO1D,MAAM,UAAU,MAAM,aAClB,KAAA,IACA;CAEJ,OAAO;EACL,MAAM;EACN,MAAM;EACN;EACA,YAAY;EACZ,MAAM;EACN,GAAI,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;CAC7C;AACF;AAEA,SAAS,iBACP,QACA,OACA,SACA,aACA,cACA,YACA,gBACA,kBACA,WACA,YACA,wBACA,eACU;CACV,MAAM,gBAAgB,cAAc,IAAI,OAAO,IAAI;CACnD,MAAM,YAAY,eAAe,aAAa,YAAY,OAAO,IAAI,CAAC,CAAC;CACvE,MAAM,WAAW,eAAe;CAEhC,MAAM,aAAa,QAAQ,QAAQ,OAAO,YAAY,MAAM,WAAW;CAEvE,IAAI,iBAAiB,YAAY;EAC/B,MAAM,QAA6B,CAAC;EACpC,IAAI,aAAa,KAAA,GACf,MAAM,KAAK,kBAAkB,SAAS,QAAQ,CAAC;EAEjD,OAAO;GACL,MAAM;GACN,MAAM;GACN,UAAU,gBAAgB,gBAAgB,WAAW,UAAU,EAAE;GACjE,UAAU,OAAO;GACjB,MAAM,OAAO,SAAS;GACtB,YAAY;GACZ,MAAM;EACR;CACF;CAEA,IAAI,WAAW,WAAW;CAC1B,MAAM,cAAc,YAAY,IAAI,OAAO,UAAU;CACrD,IAAI,aACF,WAAW;CAEb,IAAI,WAAW,uBAAuB,CAAC,aACrC,WAAW,qBAAqB,YAAY,UAAU;CAGxD,MAAM,aAAkC,CAAC;CACzC,MAAM,OAAO,cAAc,UAAU,IAAI,OAAO,IAAI;CACpD,IAAI,MACF,WAAW,KAAK,oCAAoC,MAAM,sBAAsB,CAAC;CAGnF,IAAI,OAAO,YAAY,KAAA,GAAW;EAChC,MAAM,SAAS,mBAAmB,OAAO,SAAS,OAAO,YAAY,gBAAgB;EACrF,IAAI,QAAQ;GACV,MAAM,SAAS,WAAW,QAAQ,cAAc;GAChD,IAAI,eAAe,QACjB,WAAW,KAAK,4BAA4B,OAAO,SAAS,CAAC;EAMjE;CACF;CAEA,IAAI,cAAc,IAAI,OAAO,IAAI,KAAK,CAAC,MAAM;EAC3C,MAAM,uBAAuB,cAAc,IAAI,OAAO,IAAI;EAC1D,WAAW,KAAK,oCAAoC,UAAU,oBAAoB,CAAC;CACrF;CAEA,IAAI,aAAa,KAAA,GACf,WAAW,KAAK,kBAAkB,SAAS,QAAQ,CAAC;CAGtD,OAAO;EACL,MAAM;EACN,MAAM;EACN;EACA,UAAU,OAAO;EACjB,MAAM,OAAO,SAAS;EACtB;EACA,MAAM;CACR;AACF;AAEA,SAAS,mBACP,KACA,eACA,mBACA,gBACU;CACV,MAAM,YAAY,sBAAsB,IAAI,WAAW,cAAc;CACrE,eAAe,IAAI,SAAS;CAE5B,MAAM,OAA+B,CAAC;CAEtC,IAAI,IAAI,UAAU,IAAI,YAAY;EAChC,IAAI,IAAI,cACN,KAAK,KAAK,SAAS,QAAQ,IAAI,gBAAgB,IAAI,YAAY,EAAE,EAAE,CAAC;EAEtE,KAAK,KACH,SACE,UACA,IAAI,IAAI,OACL,KAAK,eAAe,uBAAuB,mBAAmB,eAAe,UAAU,CAAC,CAAC,CACzF,KAAK,IAAI,EAAE,EAChB,CACF;EACA,KAAK,KACH,SACE,cACA,IAAI,IAAI,WACL,KAAK,eACJ,uBAAuB,mBAAmB,IAAI,uBAAuB,IAAI,UAAU,CACrF,CAAC,CACA,KAAK,IAAI,EAAE,EAChB,CACF;EACA,IAAI,IAAI,UACN,KAAK,KAAK,SAAS,YAAY,IAAI,QAAQ,CAAC;EAE9C,IAAI,IAAI,UACN,KAAK,KAAK,SAAS,YAAY,IAAI,QAAQ,CAAC;EAE9C,IAAI,IAAI,QACN,KAAK,KAAK,SAAS,OAAO,IAAI,gBAAgB,IAAI,MAAM,EAAE,EAAE,CAAC;CAEjE,OAAO,IAAI,IAAI,cACb,KAAK,KAAK,SAAS,QAAQ,IAAI,gBAAgB,IAAI,YAAY,EAAE,EAAE,CAAC;CAGtE,MAAM,QACJ,KAAK,SAAS,IAAI,CAAC,eAAe,SAAS,YAAY,IAAI,CAAC,IAAI,CAAC;CAEnE,OAAO;EACL,MAAM;EACN,MAAM;EACN,UAAU,IAAI;EACd,GAAG,UAAU,mBAAmB,IAAI,eAAe;EACnD,GAAG,UAAU,uBAAuB,IAAI,mBAAmB;EAC3D,UAAU,IAAI;EACd,MAAM,IAAI;EACV,YAAY;EACZ,MAAM;CACR;AACF;AAEA,SAAS,8BACP,MACA,QACA,gBACmB;CACnB,MAAM,OAA+B,CAAC,cAAc,IAAI,OAAO,KAAK,IAAI,EAAE,EAAE,CAAC;CAC7E,IAAI,mBAAmB,KAAA,GACrB,KAAK,KAAK,SAAS,OAAO,IAAI,gBAAgB,cAAc,EAAE,EAAE,CAAC;CAEnE,OAAO,eAAe,SAAS,MAAM,IAAI;AAC3C;AAEA,SAAS,oCACP,MACA,gBACmB;CACnB,IAAI,mBAAmB,KAAA,GACrB,OAAO,eAAe,SAAS,MAAM,CAAC,CAAC;CAEzC,OAAO,eAAe,SAAS,MAAM,CAAC,SAAS,OAAO,IAAI,gBAAgB,cAAc,EAAE,EAAE,CAAC,CAAC;AAChG;AAEA,SAAS,4BAA4B,eAA0C;CAI7E,OAAO,eAAe,SAAS,WAAW,CAAC,cAD7B,cAAc,QAAQ,eAAe,EAAE,CAAC,CAAC,QAAQ,OAAO,EACT,CAAC,CAAC,CAAC;AAClE;AAEA,SAAS,kBAAkB,QAAoC,SAA+B;CAC5F,OAAO,eAAe,QAAQ,OAAO,CAAC,cAAc,IAAI,gBAAgB,OAAO,EAAE,EAAE,CAAC,CAAC;AACvF;AAEA,SAAS,eACP,QACA,MACA,MACc;CACd,OAAO;EACL,MAAM;EACN;EACA;EACA;EACA,MAAM;CACR;AACF;AAEA,SAAS,cAAc,OAAqC;CAC1D,OAAO;EAAE,MAAM;EAAc;EAAO,MAAM;CAAe;AAC3D;AAEA,SAAS,SAAS,MAAc,OAAqC;CACnE,OAAO;EAAE,MAAM;EAAS;EAAM;EAAO,MAAM;CAAe;AAC5D;AAEA,SAAS,0BAA0B,OAAwD;CACzF,MAAM,YAAY,eAChB,aACA,MAAM,oBAAoB,OACzB,MAAM,oBAAoB,QAAQ,CAAC,EAAA,CAAG,IAAI,aAAa,CAC1D;CACA,OAAO;EACL,MAAM;EACN,MAAM,MAAM;EACZ,UAAU,MAAM;EAChB,YAAY,CAAC,SAAS;EACtB,MAAM;CACR;AACF;AAEA,SAAS,gBAAgB,OAAuB;CAC9C,OAAO,MACJ,QAAQ,OAAO,MAAM,CAAC,CACtB,QAAQ,MAAM,MAAK,CAAC,CACpB,QAAQ,OAAO,KAAK,CAAC,CACrB,QAAQ,OAAO,KAAK;AACzB;;;;;;;;;AAUA,SAAS,mBACP,OACA,YACA,kBAC2B;CAC3B,IAAI,OAAO,UAAU,UACnB,OAAO,mBAAmB,iBAAiB,OAAO,UAAU,IAAI,KAAA;CAElE,IAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,UAAW,OAC5D,OAAO;AAGX;AAEA,SAAS,uBACP,QAC8C;CAC9C,MAAM,oCAAoB,IAAI,IAAqC;CAEnE,KAAK,MAAM,SAAS,OAAO,OAAO,MAAM,GAAG;EAWzC,MAAM,kBAAkB,CAAC,GAVT,OAAO,OAAO,MAAM,OAAO,CAAC,CAAC,KAAK,QAAQ,UAAU;GAClE,MAAM,EAAE,MAAM,QAAQ,YAAY,OAAO,IAAI;GAC7C,OAAO;IACL,YAAY,OAAO;IACnB,kBAAkB;IAClB,UAAU;IACV;GACF;EACF,CAEkC,CAAC,CAAC,CAAC,MAAM,MAAM,UAAU;GACzD,MAAM,gBACJ,OAAO,KAAK,aAAa,KAAA,CAAS,IAAI,OAAO,MAAM,aAAa,KAAA,CAAS;GAC3E,IAAI,kBAAkB,GACpB,OAAO;GAET,OAAO,KAAK,QAAQ,MAAM;EAC5B,CAAC;EAED,MAAM,iCAAiB,IAAI,IAAY;EACvC,MAAM,kCAAkB,IAAI,IAAqC;EAEjE,KAAK,MAAM,UAAU,iBAAiB;GACpC,MAAM,YAAY,sBAAsB,OAAO,kBAAkB,cAAc;GAC/E,eAAe,IAAI,SAAS;GAC5B,gBAAgB,IAAI,OAAO,YAAY;IACrC;IACA,UAAU,OAAO;GACnB,CAAC;EACH;EAEA,kBAAkB,IAAI,MAAM,MAAM,eAAe;CACnD;CAEA,OAAO;AACT;AAEA,SAAS,uBACP,mBACA,WACA,YACQ;CACR,OACE,kBAAkB,IAAI,SAAS,CAAC,EAAE,IAAI,UAAU,CAAC,EAAE,aAAa,YAAY,UAAU,CAAC,CAAC;AAE5F;AAEA,SAAS,sBAAsB,aAAqB,gBAA6C;CAC/F,IAAI,CAAC,eAAe,IAAI,WAAW,GACjC,OAAO;CAGT,IAAI,UAAU;CACd,OAAO,eAAe,IAAI,GAAG,cAAc,SAAS,GAClD;CAEF,OAAO,GAAG,cAAc;AAC1B;AAEA,SAAS,qBACP,SACA,WACA,MACA,YACiC;CACjC,MAAM,0BAAU,IAAI,IAAgC;CACpD,MAAM,sCAAsB,IAAI,IAAsB;CAEtD,KAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,aAAa,UAAU,MAAM;EACnC,QAAQ,IAAI,QAAQ,UAAU;EAC9B,oBAAoB,IAAI,WAAW,MAAM,CACvC,GAAI,oBAAoB,IAAI,WAAW,IAAI,KAAK,CAAC,GACjD,MACF,CAAC;CACH;CAEA,MAAM,aAAa,CAAC,GAAG,oBAAoB,QAAQ,CAAC,CAAC,CAAC,QACnD,GAAG,wBAAwB,mBAAmB,SAAS,CAC1D;CACA,IAAI,WAAW,SAAS,GAAG;EACzB,MAAM,UAAU,WAAW,KACxB,CAAC,gBAAgB,wBAChB,KAAK,KAAK,IAAI,eAAe,SAAS,WAAW,IAAI,mBAClD,KAAK,WAAW,IAAI,OAAO,EAAE,CAAC,CAC9B,KAAK,IAAI,GAChB;EACA,MAAM,IAAI,MAAM,OAAO,KAAK,8BAA8B,QAAQ,KAAK,IAAI,GAAG;CAChF;CAEA,OAAO;AACT;AAEA,SAAS,6BACP,YACa;CACb,MAAM,gBAAgB,IAAI,IAAY,qBAAqB;CAE3D,KAAK,MAAM,UAAU,WAAW,OAAO,GACrC,cAAc,IAAI,OAAO,IAAI;CAG/B,OAAO;AACT;AAEA,SAAS,sBACP,UACA,SACA,aACA,eACmB;CAOnB,MAAM,wBAAQ,IAAI,IAAkB;CAEpC,KAAK,MAAM,aAAa,OAAO,KAAK,SAAS,MAAM,CAAC,CAAC,KAAK,GAAG;EAC3D,MAAM,QAAQ,SAAS,OAAO;EAC9B,IAAI,CAAC,OACH;EAGF,KAAK,MAAM,cAAc,OAAO,KAAK,MAAM,OAAO,CAAC,CAAC,KAAK,GAAG;GAC1D,MAAM,SAAS,MAAM,QAAQ;GAC7B,IAAI,CAAC,QACH;GAGF,MAAM,aAAa,QAAQ,QAAQ,OAAO,YAAY,MAAM,WAAW;GACvE,IACE,iBAAiB,cACjB,YAAY,IAAI,OAAO,UAAU,KACjC,CAAC,WAAW,qBAEZ;GAGF,MAAM,eAAe,4BAA4B,UAAU;GAC3D,IAAI,CAAC,MAAM,IAAI,YAAY,GACzB,MAAM,IAAI,cAAc;IACtB,UAAU,WAAW;IACrB,aAAa,gBAAgB,OAAO,IAAI;IACxC,qBAAqB,WAAW;GAClC,CAAC;EAEL;CACF;CAEA,MAAM,WAA8B;EAClC,8BAAc,IAAI,IAAoC;EACtD,WAAW,IAAI,IAAY,aAAa;CAC1C;CAEA,MAAM,cAAc,CAAC,GAAG,MAAM,QAAQ,CAAC,CAAC,CAAC,MAAM,MAAM,UAAU;EAC7D,MAAM,wBAAwB,KAAK,EAAE,CAAC,YAAY,cAAc,MAAM,EAAE,CAAC,WAAW;EACpF,IAAI,0BAA0B,GAC5B,OAAO;EAET,OAAO,KAAK,EAAE,CAAC,cAAc,MAAM,EAAE;CACvC,CAAC;CAED,KAAK,MAAM,CAAC,cAAc,SAAS,aAAa;EAC9C,MAAM,OAAO,sBAAsB,KAAK,aAAa,SAAS,SAAS;EACvE,SAAS,aAAa,IAAI,cAAc;GACtC;GACA,UAAU,KAAK;GACf,qBAAqB,KAAK;EAC5B,CAAC;EACD,SAAS,UAAU,IAAI,IAAI;CAC7B;CAEA,OAAO;AACT;AAEA,SAAS,qBACP,UACA,YAMQ;CACR,MAAM,MAAM,4BAA4B,UAAU;CAClD,MAAM,WAAW,SAAS,aAAa,IAAI,GAAG;CAC9C,IAAI,UACF,OAAO,SAAS;CAGlB,MAAM,IAAI,MAAM,uDAAuD,WAAW,WAAW,EAAE;AACjG;AAEA,SAAS,4BAA4B,YAK1B;CACT,OAAO,KAAK,UAAU;EACpB,UAAU,WAAW;EACrB,qBAAqB,WAAW,sBAC5B;GACE,MAAM,WAAW,oBAAoB;GACrC,MAAM,WAAW,oBAAoB,QAAQ;EAC/C,IACA;CACN,CAAC;AACH;AAEA,SAAS,gBACP,QACA,QACA,cACY;CACZ,MAAM,8BAAc,IAAI,IAAsB;CAC9C,KAAK,MAAM,SAAS,QAClB,YAAY,IAAI,MAAM,MAAM,KAAK;CAGnC,MAAM,uBAAO,IAAI,IAAyB;CAC1C,MAAM,+BAAe,IAAI,IAAoB;CAC7C,KAAK,MAAM,aAAa,OAAO,KAAK,MAAM,GAAG;EAC3C,MAAM,YAAY,aAAa,IAAI,SAAS;EAC5C,aAAa,IAAI,WAAW,SAAS;EACrC,KAAK,IAAI,2BAAW,IAAI,IAAI,CAAC;CAC/B;CAEA,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,MAAM,GAAG;EACvD,MAAM,YAAY,aAAa,IAAI,SAAS;EAC5C,KAAK,MAAM,MAAM,MAAM,aAAa;GAClC,MAAM,eAAe,aAAa,IAAI,GAAG,eAAe;GACxD,IAAI,gBAAgB,iBAAiB,WACnC,KAAM,IAAI,SAAS,CAAC,CAAiB,IAAI,YAAY;EAEzD;CACF;CAEA,MAAM,SAAqB,CAAC;CAC5B,MAAM,0BAAU,IAAI,IAAY;CAChC,MAAM,2BAAW,IAAI,IAAY;CAEjC,MAAM,cAAc,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK;CAE1C,SAAS,MAAM,MAAoB;EACjC,IAAI,QAAQ,IAAI,IAAI,GAAG;EACvB,IAAI,SAAS,IAAI,IAAI,GAAG;EACxB,SAAS,IAAI,IAAI;EAEjB,MAAM,aAAa,CAAC,GAAI,KAAK,IAAI,IAAI,CAAiB,CAAC,CAAC,KAAK;EAC7D,KAAK,MAAM,OAAO,YAChB,MAAM,GAAG;EAGX,SAAS,OAAO,IAAI;EACpB,QAAQ,IAAI,IAAI;EAChB,OAAO,KAAK,YAAY,IAAI,IAAI,CAAa;CAC/C;CAEA,KAAK,MAAM,QAAQ,aACjB,MAAM,IAAI;CAGZ,OAAO;AACT;;;ACphCA,SAAS,wBACP,qBACA;CACA,IAAI,CAAC,qBACH;CAEF,MAAM,aAAa,yBAAyB,mBAAmB;CAC/D,QAAQ,UAIF;EACJ,IAAI,CAAC,MAAM,YAAY,OAAO,MAAM;EACpC,IAAI,CAAC,MAAM,SAAS,OAAO,MAAM;EACjC,MAAM,QAAQ,WAAW,IAAI,MAAM,OAAO;EAC1C,IAAI,CAAC,OAAO,kBAAkB,OAAO,MAAM;EAC3C,OAAO,MAAM,iBAAiB,KAAK;CACrC;AACF;AAEA,SAAgB,sBAAsB,KAAoB,QAA+B;CACvF,IAAI,IAAI,SAAS,YACf,OAAO,IAAI;CAEb,OAAO,qBAAqB,IAAI,OAAO,MAAM;AAC/C;AAEA,MAAM,2BACJ;CACE,GAAG;CACH,oBAAoB,IAAI,2BAA2B;CACnD,gBAAgB,IAAI,uBAAuB;CAC3C,iBAAiB,QAAQ,oBAAoB;EAC3C,2BAA2B,OAAO,MAAM;EACxC,OAAO,yBAAyB,QAAQ,kBAAkB;CAC5D;CACA,mBAAmB,OAAO;EACxB,OAAO,2BAA2B;GAChC,UAAU,MAAM;GAChB,cAAc,MAAM;GACpB,QAAQ,MAAM;GACd,sBAAsB,MAAM;GAC5B,qBAAqB,MAAM;EAC7B,CAAC;CACH;CACA,qBAAqB,OAAO;EAC1B,OAAO,6BAA6B;GAClC,UAAU,MAAM;GAChB,cAAc,MAAM;GACpB,QAAQ,MAAM;GACd,sBAAsB,MAAM;GAC5B,qBAAqB,MAAM;EAC7B,CAAC;CACH;CACA,YAAY;EACV,cAAc,SAAwC;GACpD,OAAO,+BAA+B,OAAO;EAC/C;EACA,aAAa,QAAQ;GACnB,OAAO,8BAA8B,MAAM;EAC7C;EACA,iBAAiB,UAAU,qBAAqB;GAC9C,MAAM,WAAW,wBAAwB,mBAAmB;GAK5D,OAAO,qCAJkB,UAGvB,QACyD,GAAG;IAC5D,qBAAqB;IACrB,GAAG,UAAU,oBAAoB,QAAQ;IACzC,eAAe;GACjB,CAAC;EACH;CACF;CACA,SAAmD;EACjD,OAAO;GACL,UAAU;GACV,UAAU;EACZ;CACF;;;;;CAKA,cAAc,SAAwC;EACpD,OAAO,+BAA+B,OAAO;CAC/C;;;;;CAKA,aAAa,QAAQ;EACnB,OAAO,8BAA8B,MAAM;CAC7C;AACF"}
package/package.json CHANGED
@@ -1,35 +1,35 @@
1
1
  {
2
2
  "name": "@prisma-next/target-postgres",
3
- "version": "0.14.0-dev.43",
3
+ "version": "0.14.0-dev.45",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "description": "Postgres target pack for Prisma Next",
8
8
  "dependencies": {
9
- "@prisma-next/cli": "0.14.0-dev.43",
10
- "@prisma-next/contract": "0.14.0-dev.43",
11
- "@prisma-next/errors": "0.14.0-dev.43",
12
- "@prisma-next/family-sql": "0.14.0-dev.43",
13
- "@prisma-next/framework-components": "0.14.0-dev.43",
14
- "@prisma-next/migration-tools": "0.14.0-dev.43",
15
- "@prisma-next/sql-contract": "0.14.0-dev.43",
16
- "@prisma-next/sql-errors": "0.14.0-dev.43",
17
- "@prisma-next/sql-operations": "0.14.0-dev.43",
18
- "@prisma-next/sql-relational-core": "0.14.0-dev.43",
19
- "@prisma-next/sql-schema-ir": "0.14.0-dev.43",
20
- "@prisma-next/ts-render": "0.14.0-dev.43",
21
- "@prisma-next/utils": "0.14.0-dev.43",
9
+ "@prisma-next/cli": "0.14.0-dev.45",
10
+ "@prisma-next/contract": "0.14.0-dev.45",
11
+ "@prisma-next/errors": "0.14.0-dev.45",
12
+ "@prisma-next/family-sql": "0.14.0-dev.45",
13
+ "@prisma-next/framework-components": "0.14.0-dev.45",
14
+ "@prisma-next/migration-tools": "0.14.0-dev.45",
15
+ "@prisma-next/sql-contract": "0.14.0-dev.45",
16
+ "@prisma-next/sql-errors": "0.14.0-dev.45",
17
+ "@prisma-next/sql-operations": "0.14.0-dev.45",
18
+ "@prisma-next/sql-relational-core": "0.14.0-dev.45",
19
+ "@prisma-next/sql-schema-ir": "0.14.0-dev.45",
20
+ "@prisma-next/ts-render": "0.14.0-dev.45",
21
+ "@prisma-next/utils": "0.14.0-dev.45",
22
22
  "@standard-schema/spec": "^1.1.0",
23
23
  "arktype": "^2.2.0",
24
24
  "pathe": "^2.0.3"
25
25
  },
26
26
  "devDependencies": {
27
- "@prisma-next/psl-parser": "0.14.0-dev.43",
28
- "@prisma-next/psl-printer": "0.14.0-dev.43",
29
- "@prisma-next/sql-contract-psl": "0.14.0-dev.43",
30
- "@prisma-next/test-utils": "0.14.0-dev.43",
31
- "@prisma-next/tsconfig": "0.14.0-dev.43",
32
- "@prisma-next/tsdown": "0.14.0-dev.43",
27
+ "@prisma-next/psl-parser": "0.14.0-dev.45",
28
+ "@prisma-next/psl-printer": "0.14.0-dev.45",
29
+ "@prisma-next/sql-contract-psl": "0.14.0-dev.45",
30
+ "@prisma-next/test-utils": "0.14.0-dev.45",
31
+ "@prisma-next/tsconfig": "0.14.0-dev.45",
32
+ "@prisma-next/tsdown": "0.14.0-dev.45",
33
33
  "tsdown": "0.22.1",
34
34
  "typescript": "5.9.3",
35
35
  "vitest": "4.1.8"
@@ -1,4 +1,5 @@
1
1
  import type { ColumnDefault } from '@prisma-next/contract/types';
2
+ import type { SqlDescribedContractSpace } from '@prisma-next/family-sql/control';
2
3
  import type {
3
4
  DefaultMappingOptions,
4
5
  PslNativeTypeAttribute,
@@ -7,6 +8,8 @@ import type {
7
8
  RelationField,
8
9
  } from '@prisma-next/family-sql/psl-infer';
9
10
  import {
11
+ buildChildRelationField,
12
+ deriveRelationFieldName,
10
13
  inferRelations,
11
14
  mapDefault,
12
15
  parseRawDefault,
@@ -14,6 +17,7 @@ import {
14
17
  toModelName,
15
18
  toNamedTypeName,
16
19
  } from '@prisma-next/family-sql/psl-infer';
20
+ import { coordinateKey, elementCoordinates } from '@prisma-next/framework-components/ir';
17
21
  import type {
18
22
  PslAttribute,
19
23
  PslAttributeArgument,
@@ -31,7 +35,15 @@ import {
31
35
  makePslNamespaceEntries,
32
36
  UNSPECIFIED_PSL_NAMESPACE_ID,
33
37
  } from '@prisma-next/framework-components/psl-ast';
34
- import type { SqlColumnIR, SqlSchemaIR, SqlTableIR } from '@prisma-next/sql-schema-ir/types';
38
+ import type { SqlModelStorage } from '@prisma-next/sql-contract/types';
39
+ import type {
40
+ SqlColumnIR,
41
+ SqlForeignKeyIR,
42
+ SqlSchemaIR,
43
+ SqlTableIR,
44
+ } from '@prisma-next/sql-schema-ir/types';
45
+ import { blindCast } from '@prisma-next/utils/casts';
46
+ import { ifDefined } from '@prisma-next/utils/defined';
35
47
  import type { PostgresDatabaseSchemaNode } from '../schema-ir/postgres-database-schema-node';
36
48
  import { createPostgresDefaultMapping } from './postgres-default-mapping';
37
49
  import { createPostgresTypeMap } from './postgres-type-map';
@@ -76,6 +88,179 @@ type TopLevelNameResult = {
76
88
  readonly map?: string | undefined;
77
89
  };
78
90
 
91
+ /**
92
+ * Coordinates every element a set of already-assembled contracts declare,
93
+ * mapped to the {@link SqlDescribedContractSpace} that owns it and keyed by
94
+ * the shared {@link coordinateKey} helper. `contract infer` uses this to omit
95
+ * database elements a stack extension pack's contract space already
96
+ * describes — reusing the same coordinate walk the contract-space aggregate
97
+ * and cross-space collision check use (`elementCoordinates`), rather than a
98
+ * bespoke per-entity-kind membership test — and, for a foreign key whose
99
+ * referenced table an entry owns, to resolve the qualified cross-space
100
+ * relation it describes.
101
+ */
102
+ function describedContractOwners(
103
+ describedContracts: readonly SqlDescribedContractSpace[],
104
+ ): ReadonlyMap<string, SqlDescribedContractSpace> {
105
+ const owners = new Map<string, SqlDescribedContractSpace>();
106
+ for (const entry of describedContracts) {
107
+ for (const coordinate of elementCoordinates(entry.contract.storage)) {
108
+ owners.set(coordinateKey(coordinate), entry);
109
+ }
110
+ }
111
+ return owners;
112
+ }
113
+
114
+ /**
115
+ * The domain model a described contract maps a `(namespaceId, tableName)`
116
+ * storage coordinate to, plus the pack's own space id and column→field-name
117
+ * mapping — everything `buildModel`/`buildRelationField` need to emit the
118
+ * cross-space relation `<spaceId>:<namespaceId>.<modelName>` and resolve its
119
+ * `references` argument to the pack's own field names rather than a generic
120
+ * column-name guess.
121
+ */
122
+ type CrossSpaceTarget = {
123
+ readonly spaceId: string;
124
+ readonly namespaceId: string;
125
+ readonly modelName: string;
126
+ readonly fieldNamesByColumn: TableColumnFieldNameMap;
127
+ };
128
+
129
+ function resolveCrossSpaceTarget(
130
+ owner: SqlDescribedContractSpace,
131
+ namespaceId: string,
132
+ tableName: string,
133
+ ): CrossSpaceTarget | undefined {
134
+ const domainNamespace = owner.contract.domain.namespaces[namespaceId];
135
+ if (domainNamespace === undefined) {
136
+ return undefined;
137
+ }
138
+
139
+ for (const [modelName, model] of Object.entries(domainNamespace.models)) {
140
+ const storage = blindCast<SqlModelStorage, 'SQL contract model storage'>(model.storage);
141
+ if (storage.namespaceId !== namespaceId || storage.table !== tableName) {
142
+ continue;
143
+ }
144
+
145
+ const fieldNamesByColumn = new Map<string, ResolvedColumnFieldName>();
146
+ for (const [fieldName, fieldStorage] of Object.entries(storage.fields)) {
147
+ fieldNamesByColumn.set(fieldStorage.column, { fieldName });
148
+ }
149
+
150
+ return { spaceId: owner.spaceId, namespaceId, modelName, fieldNamesByColumn };
151
+ }
152
+
153
+ return undefined;
154
+ }
155
+
156
+ type ForeignKeyResolution = {
157
+ /** `tables`, with every cross-space or dangling foreign key removed. */
158
+ readonly tables: Record<string, SqlTableIR>;
159
+ /** Cross-space relation fields to merge onto `inferRelations`'s output, keyed by host table name. */
160
+ readonly extraRelationsByTable: ReadonlyMap<string, readonly RelationField[]>;
161
+ /** Synthetic field-name maps for cross-space-referenced pack tables, merged into `fieldNamesByTable`. */
162
+ readonly crossSpaceFieldNamesByTable: ReadonlyMap<string, TableColumnFieldNameMap>;
163
+ };
164
+
165
+ /**
166
+ * Classifies every foreign key on a surviving table into one of three cases.
167
+ * A foreign key that carries a `referencedSchema` is checked against the
168
+ * pack-owned coordinates first, so a pack-owned target wins even when a local
169
+ * table happens to share its bare name; only foreign keys with no owned
170
+ * coordinate fall through to the local/dangling distinction.
171
+ *
172
+ * - **Cross-space**: `referencedSchema` is set and a described contract owns
173
+ * the coordinate `(referencedSchema, 'table', referencedTable)`. The
174
+ * referenced table is absent from the tree (omitted because the pack
175
+ * describes it, or never introspected — `contract infer` walks a single
176
+ * namespace). Removed from `foreignKeys` (so `inferRelations` never falls
177
+ * back to a bare, unqualified table name for it) and replaced with a
178
+ * `RelationField` qualified with the owning pack's space id and namespace
179
+ * id. `owners` holds only pack-declared coordinates, so an app's own table
180
+ * (e.g. `public.users`) is never owned and cannot be captured here.
181
+ * - **Local**: not a pack-owned coordinate, and the referenced table survived
182
+ * introspection — left untouched, `inferRelations` handles it as before.
183
+ * - **Dangling**: not a pack-owned coordinate, and the referenced table is
184
+ * neither in the tree nor owned by any described contract. Removed from
185
+ * `foreignKeys`, keeping the scalar column, rather than emitting a relation
186
+ * to a model that was never defined.
187
+ *
188
+ * A pack that owns the referenced coordinate but declares no domain model
189
+ * mapped to it is malformed; that case throws rather than degrading to a
190
+ * silent drop, which would contradict the dangling definition above.
191
+ */
192
+ function resolveForeignKeys(
193
+ tables: Readonly<Record<string, SqlTableIR>>,
194
+ owners: ReadonlyMap<string, SqlDescribedContractSpace>,
195
+ ): ForeignKeyResolution {
196
+ const resultTables: Record<string, SqlTableIR> = {};
197
+ const extraRelationsByTable = new Map<string, RelationField[]>();
198
+ const crossSpaceFieldNamesByTable = new Map<string, TableColumnFieldNameMap>();
199
+
200
+ for (const [tableName, table] of Object.entries(tables)) {
201
+ const keptForeignKeys: SqlForeignKeyIR[] = [];
202
+
203
+ for (const fk of table.foreignKeys) {
204
+ if (fk.referencedSchema !== undefined) {
205
+ const owner = owners.get(
206
+ coordinateKey({
207
+ namespaceId: fk.referencedSchema,
208
+ entityKind: 'table',
209
+ entityName: fk.referencedTable,
210
+ }),
211
+ );
212
+ if (owner !== undefined) {
213
+ const target = resolveCrossSpaceTarget(owner, fk.referencedSchema, fk.referencedTable);
214
+ if (target === undefined) {
215
+ throw new Error(
216
+ `contract infer: described contract space "${owner.spaceId}" owns storage ` +
217
+ `coordinate "${fk.referencedSchema}.${fk.referencedTable}" but declares no ` +
218
+ 'domain model mapped to it. A pack that describes a table must also declare the ' +
219
+ 'domain model it maps to; this pack is malformed.',
220
+ );
221
+ }
222
+
223
+ if (!crossSpaceFieldNamesByTable.has(fk.referencedTable)) {
224
+ crossSpaceFieldNamesByTable.set(fk.referencedTable, target.fieldNamesByColumn);
225
+ }
226
+
227
+ const fieldName = deriveRelationFieldName(fk.columns, fk.referencedTable);
228
+ const optional = fk.columns.some(
229
+ (columnName) => table.columns[columnName]?.nullable ?? false,
230
+ );
231
+ const relationField: RelationField = {
232
+ ...buildChildRelationField(fieldName, target.modelName, fk, optional),
233
+ typeNamespaceId: target.namespaceId,
234
+ typeContractSpaceId: target.spaceId,
235
+ };
236
+
237
+ const existingRelations = extraRelationsByTable.get(tableName);
238
+ if (existingRelations) {
239
+ existingRelations.push(relationField);
240
+ } else {
241
+ extraRelationsByTable.set(tableName, [relationField]);
242
+ }
243
+ continue;
244
+ }
245
+ }
246
+
247
+ // Not a pack-owned coordinate: keep the foreign key if the referenced
248
+ // table survived introspection (local), otherwise drop it while keeping
249
+ // the scalar column (dangling).
250
+ if (tables[fk.referencedTable] !== undefined) {
251
+ keptForeignKeys.push(fk);
252
+ }
253
+ }
254
+
255
+ resultTables[tableName] =
256
+ keptForeignKeys.length === table.foreignKeys.length
257
+ ? table
258
+ : { ...table, foreignKeys: keptForeignKeys };
259
+ }
260
+
261
+ return { tables: resultTables, extraRelationsByTable, crossSpaceFieldNamesByTable };
262
+ }
263
+
79
264
  /**
80
265
  * Infers a PSL AST (for `printPsl`) from an introspected Postgres schema tree.
81
266
  *
@@ -89,9 +274,23 @@ type TopLevelNameResult = {
89
274
  * introspects a single live namespace) are gathered into the model set and
90
275
  * emitted as one `UNSPECIFIED_PSL_NAMESPACE_ID` bucket. Top-level entities
91
276
  * (policies/roles → PSL extension blocks) are a later slice.
277
+ *
278
+ * `describedContracts` — the stack's extension packs' already-assembled
279
+ * contracts, each paired with its space id — is consulted while gathering
280
+ * tables: a table whose coordinate `(schemaName, 'table', tableName)` one of
281
+ * those contracts already declares is omitted, before the duplicate-name
282
+ * check below and before relation inference, so it cannot spuriously
283
+ * collide with an app table and never contributes a bare relation field. A
284
+ * surviving table's foreign key into an omitted, pack-owned table is not
285
+ * dropped: {@link resolveForeignKeys} rewrites it into a relation qualified
286
+ * with the pack's space id (`<spaceId>:<namespaceId>.<Model>`) instead.
92
287
  */
93
- export function inferPostgresPslContract(tree: PostgresDatabaseSchemaNode): PslDocumentAst {
288
+ export function inferPostgresPslContract(
289
+ tree: PostgresDatabaseSchemaNode,
290
+ describedContracts?: readonly SqlDescribedContractSpace[],
291
+ ): PslDocumentAst {
94
292
  const namespaces = Object.values(tree.namespaces);
293
+ const owners = describedContractOwners(describedContracts ?? []);
95
294
 
96
295
  // Native Postgres enums (CREATE TYPE … AS ENUM) are not adoptable by
97
296
  // `contract infer`; throw an actionable diagnostic naming the type(s). Enum
@@ -118,6 +317,17 @@ export function inferPostgresPslContract(tree: PostgresDatabaseSchemaNode): PslD
118
317
  const tables: Record<string, SqlTableIR> = {};
119
318
  for (const namespace of namespaces) {
120
319
  for (const [tableName, table] of Object.entries(namespace.tables)) {
320
+ if (
321
+ owners.has(
322
+ coordinateKey({
323
+ namespaceId: namespace.schemaName,
324
+ entityKind: 'table',
325
+ entityName: tableName,
326
+ }),
327
+ )
328
+ ) {
329
+ continue;
330
+ }
121
331
  if (tables[tableName] !== undefined) {
122
332
  throw new Error(
123
333
  `contract infer: duplicate table name "${tableName}" across schemas is not yet supported ` +
@@ -128,7 +338,13 @@ export function inferPostgresPslContract(tree: PostgresDatabaseSchemaNode): PslD
128
338
  tables[tableName] = table;
129
339
  }
130
340
  }
131
- const schemaIR: SqlSchemaIR = { tables };
341
+
342
+ const {
343
+ tables: resolvedTables,
344
+ extraRelationsByTable,
345
+ crossSpaceFieldNamesByTable,
346
+ } = resolveForeignKeys(tables, owners);
347
+ const schemaIR: SqlSchemaIR = { tables: resolvedTables };
132
348
 
133
349
  const options: PslPrinterOptions = {
134
350
  typeMap: createPostgresTypeMap(new Set()),
@@ -136,11 +352,22 @@ export function inferPostgresPslContract(tree: PostgresDatabaseSchemaNode): PslD
136
352
  parseRawDefault,
137
353
  };
138
354
 
139
- return buildPslDocumentAst(schemaIR, options);
355
+ return buildPslDocumentAst(schemaIR, options, {
356
+ extraRelationsByTable,
357
+ crossSpaceFieldNamesByTable,
358
+ });
140
359
  }
141
360
 
142
- function buildPslDocumentAst(schemaIR: SqlSchemaIR, options: PslPrinterOptions): PslDocumentAst {
361
+ function buildPslDocumentAst(
362
+ schemaIR: SqlSchemaIR,
363
+ options: PslPrinterOptions,
364
+ foreignKeyExtras: Pick<
365
+ ForeignKeyResolution,
366
+ 'extraRelationsByTable' | 'crossSpaceFieldNamesByTable'
367
+ >,
368
+ ): PslDocumentAst {
143
369
  const { typeMap, defaultMapping, parseRawDefault: rawDefaultParser } = options;
370
+ const { extraRelationsByTable, crossSpaceFieldNamesByTable } = foreignKeyExtras;
144
371
 
145
372
  const modelNames = buildTopLevelNameMap(
146
373
  Object.keys(schemaIR.tables),
@@ -154,7 +381,14 @@ function buildPslDocumentAst(schemaIR: SqlSchemaIR, options: PslPrinterOptions):
154
381
  );
155
382
  const reservedNamedTypeNames = createReservedNamedTypeNames(modelNames);
156
383
 
157
- const fieldNamesByTable = buildFieldNamesByTable(schemaIR.tables);
384
+ // Cross-space entries are seeded first so a real local table of the same
385
+ // bare name (an existing single-namespace-flat-bucket limitation, not new
386
+ // here) always wins the merge, matching `resolveForeignKeys`'s own
387
+ // precedence: a surviving local table is never treated as cross-space.
388
+ const fieldNamesByTable = new Map([
389
+ ...crossSpaceFieldNamesByTable,
390
+ ...buildFieldNamesByTable(schemaIR.tables),
391
+ ]);
158
392
  const { relationsByTable } = inferRelations(schemaIR.tables, modelNameMap);
159
393
  const namedTypes = seedNamedTypeRegistry(schemaIR, typeMap, new Map(), reservedNamedTypeNames);
160
394
 
@@ -169,7 +403,10 @@ function buildPslDocumentAst(schemaIR: SqlSchemaIR, options: PslPrinterOptions):
169
403
  namedTypes,
170
404
  defaultMapping,
171
405
  rawDefaultParser,
172
- relationsByTable.get(table.name) ?? [],
406
+ [
407
+ ...(relationsByTable.get(table.name) ?? []),
408
+ ...(extraRelationsByTable.get(table.name) ?? []),
409
+ ],
173
410
  ),
174
411
  );
175
412
  }
@@ -452,6 +689,8 @@ function buildRelationField(
452
689
  kind: 'field',
453
690
  name: fieldName,
454
691
  typeName: rel.typeName,
692
+ ...ifDefined('typeNamespaceId', rel.typeNamespaceId),
693
+ ...ifDefined('typeContractSpaceId', rel.typeContractSpaceId),
455
694
  optional: rel.optional,
456
695
  list: rel.list,
457
696
  attributes: attrs,
@@ -58,9 +58,9 @@ const postgresTargetDescriptor: SqlControlTargetDescriptor<'postgres', PostgresP
58
58
  ...postgresTargetDescriptorMeta,
59
59
  contractSerializer: new PostgresContractSerializer(),
60
60
  schemaVerifier: new PostgresSchemaVerifier(),
61
- inferPslContract(schema) {
61
+ inferPslContract(schema, describedContracts) {
62
62
  PostgresDatabaseSchemaNode.assert(schema);
63
- return inferPostgresPslContract(schema);
63
+ return inferPostgresPslContract(schema, describedContracts);
64
64
  },
65
65
  diffDatabaseSchema(input) {
66
66
  return diffPostgresDatabaseSchema({