@prisma-next/target-postgres 0.12.0-dev.67 → 0.12.0-dev.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/control.d.mts +1 -1
  2. package/dist/control.mjs +1 -1
  3. package/dist/{data-transform-lq3NGdIt.d.mts → data-transform-DGOqcLrf.d.mts} +2 -2
  4. package/dist/{data-transform-lq3NGdIt.d.mts.map → data-transform-DGOqcLrf.d.mts.map} +1 -1
  5. package/dist/data-transform.d.mts +1 -1
  6. package/dist/{issue-planner-QUBRwSq8.mjs → issue-planner-SHnDHfoQ.mjs} +97 -4
  7. package/dist/issue-planner-SHnDHfoQ.mjs.map +1 -0
  8. package/dist/issue-planner.d.mts +1 -1
  9. package/dist/issue-planner.d.mts.map +1 -1
  10. package/dist/issue-planner.mjs +1 -1
  11. package/dist/migration.d.mts +6 -4
  12. package/dist/migration.d.mts.map +1 -1
  13. package/dist/migration.mjs +3 -3
  14. package/dist/{op-factory-call-B4LIiPwu.mjs → op-factory-call-D2aAUhmS.mjs} +93 -2
  15. package/dist/op-factory-call-D2aAUhmS.mjs.map +1 -0
  16. package/dist/{op-factory-call-Bj1jPDpD.d.mts → op-factory-call-DMA86_2D.d.mts} +29 -5
  17. package/dist/{op-factory-call-Bj1jPDpD.d.mts.map → op-factory-call-DMA86_2D.d.mts.map} +1 -1
  18. package/dist/op-factory-call.d.mts +2 -2
  19. package/dist/op-factory-call.mjs +2 -2
  20. package/dist/{planner-BU0He_3s.mjs → planner-Bv5LV2A-.mjs} +3 -3
  21. package/dist/{planner-BU0He_3s.mjs.map → planner-Bv5LV2A-.mjs.map} +1 -1
  22. package/dist/{planner-produced-postgres-migration-B11fjNTx.d.mts → planner-produced-postgres-migration-B4EDvLdz.d.mts} +3 -3
  23. package/dist/{planner-produced-postgres-migration-B11fjNTx.d.mts.map → planner-produced-postgres-migration-B4EDvLdz.d.mts.map} +1 -1
  24. package/dist/{planner-produced-postgres-migration-DkQoyxIu.mjs → planner-produced-postgres-migration-NSEhWL0L.mjs} +2 -2
  25. package/dist/{planner-produced-postgres-migration-DkQoyxIu.mjs.map → planner-produced-postgres-migration-NSEhWL0L.mjs.map} +1 -1
  26. package/dist/planner-produced-postgres-migration.d.mts +1 -1
  27. package/dist/planner-produced-postgres-migration.mjs +1 -1
  28. package/dist/{planner-target-details-DyUHJ7MY.d.mts → planner-target-details-CIY6tLeo.d.mts} +2 -2
  29. package/dist/planner-target-details-CIY6tLeo.d.mts.map +1 -0
  30. package/dist/planner-target-details.d.mts +1 -1
  31. package/dist/planner.d.mts +1 -1
  32. package/dist/planner.mjs +1 -1
  33. package/dist/{postgres-migration-mYtmFD_K.mjs → postgres-migration-COore9Mz.mjs} +2 -2
  34. package/dist/{postgres-migration-mYtmFD_K.mjs.map → postgres-migration-COore9Mz.mjs.map} +1 -1
  35. package/dist/{postgres-migration-B6rKNT4N.d.mts → postgres-migration-DZ_gLUOW.d.mts} +3 -3
  36. package/dist/{postgres-migration-B6rKNT4N.d.mts.map → postgres-migration-DZ_gLUOW.d.mts.map} +1 -1
  37. package/dist/render-ops.d.mts +1 -1
  38. package/dist/{shared-C6QxSU0W.d.mts → shared-DarONYBZ.d.mts} +2 -2
  39. package/dist/{shared-C6QxSU0W.d.mts.map → shared-DarONYBZ.d.mts.map} +1 -1
  40. package/package.json +17 -17
  41. package/src/core/migrations/issue-planner.ts +51 -0
  42. package/src/core/migrations/op-factory-call.ts +78 -1
  43. package/src/core/migrations/operations/constraints.ts +78 -1
  44. package/src/core/migrations/planner-strategies.ts +132 -1
  45. package/src/core/migrations/planner-target-details.ts +2 -1
  46. package/src/exports/migration.ts +2 -0
  47. package/src/exports/op-factory-call.ts +2 -0
  48. package/dist/issue-planner-QUBRwSq8.mjs.map +0 -1
  49. package/dist/op-factory-call-B4LIiPwu.mjs.map +0 -1
  50. package/dist/planner-target-details-DyUHJ7MY.d.mts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"planner-BU0He_3s.mjs","names":["#lowerer"],"sources":["../src/core/migrations/control-policy.ts","../src/core/migrations/verify-postgres-namespaces.ts","../src/core/migrations/planner.ts"],"sourcesContent":["import type { Contract } from '@prisma-next/contract/types';\nimport type { ControlPolicySubject } from '@prisma-next/family-sql/control';\nimport type { SchemaIssue } from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport {\n isPostgresEnumStorageEntry,\n type SqlStorage,\n storageTableAt,\n} from '@prisma-next/sql-contract/types';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { isPostgresSchema } from '../postgres-schema';\nimport type { PostgresOpFactoryCall } from './op-factory-call';\n\n/**\n * Factory calls that create a whole, previously-absent top-level storage\n * object. Used to decide whether `tolerated` permits a call (it only allows\n * creating absent objects, never modifying existing ones).\n *\n * Deliberately an explicit, closed set rather than a `factoryName`\n * create/alter/drop classification: it answers exactly one yes/no question\n * and is fail-closed. Any call not listed here — including future or\n * extension-contributed factories — is treated as NOT object-creation, so it\n * is suppressed under `tolerated` rather than permissively emitted.\n */\nconst OBJECT_CREATION_FACTORIES: ReadonlySet<string> = new Set<string>([\n 'createTable',\n 'createEnumType',\n 'createSchema',\n]);\n\nfunction createsNewTopLevelObject(call: PostgresOpFactoryCall): boolean {\n return OBJECT_CREATION_FACTORIES.has(call.factoryName);\n}\n\nfunction ddlSchemaNameForNamespace(contract: Contract<SqlStorage>, namespaceId: string): string {\n const namespace = contract.storage.namespaces[namespaceId];\n return isPostgresSchema(namespace) ? namespace.ddlSchemaName(contract.storage) : namespaceId;\n}\n\nfunction resolveNamespaceIdForTable(\n contract: Contract<SqlStorage>,\n tableName: string,\n ddlSchemaName: string | undefined,\n): string {\n for (const namespaceId of Object.keys(contract.storage.namespaces)) {\n const table = storageTableAt(contract.storage, namespaceId, tableName);\n if (!table) continue;\n if (\n ddlSchemaName === undefined ||\n ddlSchemaNameForNamespace(contract, namespaceId) === ddlSchemaName\n ) {\n return namespaceId;\n }\n }\n return UNBOUND_NAMESPACE_ID;\n}\n\nfunction resolveNamespaceIdForDdlSchema(\n contract: Contract<SqlStorage>,\n ddlSchemaName: string,\n): string {\n for (const namespaceId of Object.keys(contract.storage.namespaces)) {\n const ns = contract.storage.namespaces[namespaceId];\n if (isPostgresSchema(ns) && ns.ddlSchemaName(contract.storage) === ddlSchemaName) {\n return namespaceId;\n }\n if (namespaceId === ddlSchemaName) {\n return namespaceId;\n }\n }\n return UNBOUND_NAMESPACE_ID;\n}\n\ninterface PostgresCallFields {\n readonly schemaName?: string;\n readonly tableName?: string;\n readonly columnName?: string;\n readonly typeName?: string;\n}\n\nfunction postgresCallFields(call: PostgresOpFactoryCall): PostgresCallFields {\n return {\n ...ifDefined('schemaName', 'schemaName' in call ? call.schemaName : undefined),\n ...ifDefined('tableName', 'tableName' in call ? call.tableName : undefined),\n ...ifDefined('columnName', 'columnName' in call ? call.columnName : undefined),\n ...ifDefined('typeName', 'typeName' in call ? call.typeName : undefined),\n };\n}\n\nexport function formatPostgresControlPolicySubjectLabel(\n factoryName: string,\n subject: ControlPolicySubject | undefined,\n contract: Contract<SqlStorage>,\n): string {\n if (subject?.table) {\n const ddlSchema = ddlSchemaNameForNamespace(contract, subject.namespaceId);\n return `${factoryName}(${ddlSchema}.${subject.table})`;\n }\n if (subject?.typeName) {\n const ddlSchema = ddlSchemaNameForNamespace(contract, subject.namespaceId);\n return `${factoryName}(${ddlSchema}.${subject.typeName})`;\n }\n return factoryName;\n}\n\nexport function resolvePostgresCallControlPolicySubject(\n call: PostgresOpFactoryCall,\n contract: Contract<SqlStorage>,\n): ControlPolicySubject | undefined {\n const callFields = postgresCallFields(call);\n const createsNewObject = createsNewTopLevelObject(call);\n\n if (call.factoryName === 'createSchema' && callFields.schemaName) {\n return {\n namespaceId: resolveNamespaceIdForDdlSchema(contract, callFields.schemaName),\n createsNewObject,\n };\n }\n\n if (callFields.typeName && call.factoryName !== 'addColumn') {\n const namespaceId = callFields.schemaName\n ? resolveNamespaceIdForDdlSchema(contract, callFields.schemaName)\n : UNBOUND_NAMESPACE_ID;\n const ns = contract.storage.namespaces[namespaceId];\n const rawEnum = isPostgresSchema(ns) ? ns.entries.type[callFields.typeName] : undefined;\n const controlPolicy = isPostgresEnumStorageEntry(rawEnum) ? rawEnum.control : undefined;\n return {\n namespaceId,\n ...ifDefined('explicitNodeControlPolicy', controlPolicy),\n typeName: callFields.typeName,\n createsNewObject,\n };\n }\n\n if (callFields.tableName) {\n const namespaceId = resolveNamespaceIdForTable(\n contract,\n callFields.tableName,\n callFields.schemaName,\n );\n const table = storageTableAt(contract.storage, namespaceId, callFields.tableName);\n const tableControlPolicy = table?.control;\n return {\n namespaceId,\n ...ifDefined('explicitNodeControlPolicy', tableControlPolicy),\n table: callFields.tableName,\n ...ifDefined('column', callFields.columnName),\n createsNewObject,\n };\n }\n\n if (callFields.schemaName) {\n return {\n namespaceId: resolveNamespaceIdForDdlSchema(contract, callFields.schemaName),\n createsNewObject,\n };\n }\n\n return undefined;\n}\n\n/**\n * Issue kinds that describe the absence of a whole, top-level Postgres\n * object — the same kinds `createsNewTopLevelObject` recognises for calls.\n * Used by {@link resolvePostgresIssueCreationFactoryName} to decide whether\n * a `tolerated` subject permits the issue to flow into the planner\n * (create-if-absent) and to seed the suppressed-subject warning's\n * `factoryName` when the planner is skipped.\n */\nconst POSTGRES_ISSUE_CREATION_FACTORY: Readonly<Record<string, string>> = Object.freeze({\n missing_schema: 'createSchema',\n missing_table: 'createTable',\n type_missing: 'createEnumType',\n});\n\nexport function resolvePostgresIssueCreationFactoryName(issue: SchemaIssue): string | undefined {\n return POSTGRES_ISSUE_CREATION_FACTORY[issue.kind];\n}\n\n/**\n * Resolve the control-policy subject coordinate for a single\n * {@link SchemaIssue}. Mirrors the resolution `resolvePostgresCallControlPolicySubject`\n * performs for a generated DDL call, but works *off the issue* — so the\n * planner can partition issues by effective policy before the diff engine\n * runs. `createsNewObject` is derived from the issue's kind: schema/table/\n * type-missing issues describe a brand-new top-level object; everything else\n * touches an existing object.\n *\n * An `extra_table` issue carries no contract namespace coordinate (the table\n * isn't in any contract namespace), so the subject's `namespaceId` falls\n * back to {@link UNBOUND_NAMESPACE_ID}; the call-side resolver does the same\n * for the `DropTableCall` it produces.\n */\nexport function resolvePostgresIssueControlPolicySubject(\n issue: SchemaIssue,\n contract: Contract<SqlStorage>,\n): ControlPolicySubject | undefined {\n const createsNewObject = POSTGRES_ISSUE_CREATION_FACTORY[issue.kind] !== undefined;\n\n if (issue.kind === 'missing_schema' && issue.namespaceId) {\n return { namespaceId: issue.namespaceId, createsNewObject };\n }\n\n if ('typeName' in issue && issue.typeName) {\n const namespaceId =\n 'namespaceId' in issue && issue.namespaceId ? issue.namespaceId : UNBOUND_NAMESPACE_ID;\n const ns = contract.storage.namespaces[namespaceId];\n const rawEnum = isPostgresSchema(ns) ? ns.entries.type[issue.typeName] : undefined;\n const controlPolicy = isPostgresEnumStorageEntry(rawEnum) ? rawEnum.control : undefined;\n return {\n namespaceId,\n ...ifDefined('explicitNodeControlPolicy', controlPolicy),\n typeName: issue.typeName,\n createsNewObject,\n };\n }\n\n if ('table' in issue && issue.table) {\n const namespaceId =\n 'namespaceId' in issue && issue.namespaceId\n ? issue.namespaceId\n : resolveNamespaceIdForTable(contract, issue.table, undefined);\n const table = storageTableAt(contract.storage, namespaceId, issue.table);\n return {\n namespaceId,\n ...ifDefined('explicitNodeControlPolicy', table?.control),\n table: issue.table,\n ...ifDefined('column', 'column' in issue ? issue.column : undefined),\n createsNewObject,\n };\n }\n\n return undefined;\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type { SchemaIssue } from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { isPostgresSchema } from '../postgres-schema';\n\n/**\n * Resolves the live-database schema name for a given namespace\n * coordinate. Mirrors `resolveDdlSchemaForNamespace` in\n * `planner-strategies.ts` so the verifier's projection and the\n * planner's projection always agree — Postgres-aware namespaces (the\n * production path) dispatch to `ddlSchemaName(storage)`, and bare\n * object payloads (used by some tests) fall back to the coordinate\n * itself.\n */\nfunction resolveDdlSchemaName(storage: SqlStorage, namespaceId: string): string {\n const namespace = storage.namespaces[namespaceId];\n if (isPostgresSchema(namespace)) {\n return namespace.ddlSchemaName(storage);\n }\n return namespaceId;\n}\n\n/**\n * Reads the introspected list of schema names from the Postgres-flavoured\n * annotations slot on the schema IR. Defaults to the always-present\n * `public` schema when introspection did not populate the slot — a fresh\n * Postgres database always carries `public` (unless an operator dropped\n * it manually), so any verifier path that runs without an enriched\n * introspection still suppresses the redundant `CREATE SCHEMA \"public\"`.\n *\n * Production introspection (`PostgresControlAdapter.introspect`) is the\n * authoritative source: it queries `pg_namespace` and writes every\n * non-system schema into `annotations.pg.existingSchemas`. Tests that\n * want to assert against a richer initial state pass the slot\n * explicitly via the schema IR.\n */\nfunction existingSchemasFromSchema(schema: SqlSchemaIR): readonly string[] {\n const annotations = (schema as { annotations?: { pg?: { existingSchemas?: unknown } } })\n .annotations;\n const slot = annotations?.pg?.existingSchemas;\n if (Array.isArray(slot)) {\n return slot.filter((s): s is string => typeof s === 'string');\n }\n return ['public'];\n}\n\n/**\n * Emits a `missing_schema` issue for every contract-declared Postgres\n * namespace whose live container does not yet exist.\n *\n * A namespace's live container is the schema returned by its\n * polymorphic `ddlSchemaName(storage)` method — named schemas resolve\n * to their own id; the unbound singleton returns `UNBOUND_NAMESPACE_ID`\n * and is skipped explicitly (late-bound namespaces have no fixed DDL\n * schema). Issues are emitted only when the resolved name is a real,\n * creatable schema (not the unbound sentinel) and is missing from the\n * introspected list. `public` is suppressed implicitly because the\n * introspection (or its sensible default) always carries it.\n *\n * Each emitted issue stamps `namespaceId` with the contract namespace\n * coordinate so the downstream `mapIssueToCall` re-resolves the DDL\n * schema name through the same polymorphic path — keeping the\n * coordinate, not the resolved name, as the issue's stable identity.\n */\nexport function verifyPostgresNamespacePresence(input: {\n readonly contract: Contract<SqlStorage>;\n readonly schema: SqlSchemaIR;\n}): readonly SchemaIssue[] {\n const { contract, schema } = input;\n const existing = new Set(existingSchemasFromSchema(schema));\n const issues: SchemaIssue[] = [];\n const namespaceIds = Object.keys(contract.storage.namespaces).sort();\n for (const namespaceId of namespaceIds) {\n if (namespaceId === UNBOUND_NAMESPACE_ID) continue;\n const ddlName = resolveDdlSchemaName(contract.storage, namespaceId);\n if (ddlName === UNBOUND_NAMESPACE_ID) continue;\n if (existing.has(ddlName)) continue;\n issues.push({\n kind: 'missing_schema',\n namespaceId,\n message: `Schema \"${ddlName}\" is missing from database`,\n });\n }\n return issues;\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type {\n MigrationOperationPolicy,\n SqlMigrationPlannerPlanOptions,\n SqlPlannerConflict,\n SqlPlannerFailureResult,\n} from '@prisma-next/family-sql/control';\nimport {\n extractCodecControlHooks,\n partitionCallsByControlPolicy,\n partitionIssuesByControlPolicy,\n planFieldEventOperations,\n plannerFailure,\n} from '@prisma-next/family-sql/control';\nimport type { Lowerer } from '@prisma-next/family-sql/control-adapter';\nimport { verifySqlSchema } from '@prisma-next/family-sql/schema-verify';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n MigrationPlanner,\n MigrationPlanWithAuthoringSurface,\n MigrationScaffoldContext,\n SchemaIssue,\n} from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { parsePostgresDefault } from '../default-normalizer';\nimport { normalizeSchemaNativeType } from '../native-type-normalizer';\nimport {\n formatPostgresControlPolicySubjectLabel,\n resolvePostgresCallControlPolicySubject,\n resolvePostgresIssueControlPolicySubject,\n resolvePostgresIssueCreationFactoryName,\n} from './control-policy';\nimport { createResolveExistingEnumValues } from './enum-planning';\nimport { planIssues } from './issue-planner';\nimport type { PostgresOpFactoryCall } from './op-factory-call';\nimport { TypeScriptRenderablePostgresMigration } from './planner-produced-postgres-migration';\nimport { postgresPlannerStrategies } from './planner-strategies';\nimport { verifyPostgresNamespacePresence } from './verify-postgres-namespaces';\n\ntype PlannerFrameworkComponents = SqlMigrationPlannerPlanOptions extends {\n readonly frameworkComponents: infer T;\n}\n ? T\n : ReadonlyArray<unknown>;\n\ntype PlannerOptionsWithComponents = SqlMigrationPlannerPlanOptions & {\n readonly frameworkComponents: PlannerFrameworkComponents;\n};\n\ntype VerifySqlSchemaOptionsWithComponents = Parameters<typeof verifySqlSchema>[0] & {\n readonly frameworkComponents: PlannerFrameworkComponents;\n};\n\nexport function createPostgresMigrationPlanner(lowerer: Lowerer): PostgresMigrationPlanner {\n return new PostgresMigrationPlanner(lowerer);\n}\n\n/**\n * Result of `PostgresMigrationPlanner.plan()`. A discriminated union whose\n * success variant carries a `TypeScriptRenderablePostgresMigration` — a\n * migration object that both the CLI (via `renderTypeScript()`) and the\n * SQL-typed callers (via `operations`, `describe()`, etc.) consume\n * uniformly.\n */\nexport type PostgresPlanResult =\n | {\n readonly kind: 'success';\n readonly plan: TypeScriptRenderablePostgresMigration;\n readonly warnings?: readonly SqlPlannerConflict[];\n }\n | SqlPlannerFailureResult;\n\n/**\n * Postgres migration planner — a thin wrapper over `planIssues`.\n *\n * `plan()` verifies the live schema against the target contract (producing\n * `SchemaIssue[]`) and delegates to `planIssues` with the unified\n * `postgresPlannerStrategies` list: enum-change, NOT-NULL backfill,\n * type-change, nullable-tightening, codec-hook storage types,\n * component-declared dependency installs, and shared-temp-default /\n * empty-table-guarded NOT-NULL add-column. The same strategy list runs for\n * `migration plan`, `db update`, and `db init`; behavior diverges purely on\n * `policy.allowedOperationClasses` (the data-safe strategies short-circuit\n * when `'data'` is excluded). The issue planner applies operation-class\n * policy gates and emits a single `PostgresOpFactoryCall[]` that drives both\n * the runtime-ops view (via `renderOps`) and the `renderTypeScript()`\n * authoring surface.\n */\nexport class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgres'> {\n readonly #lowerer: Lowerer | undefined;\n\n constructor(lowerer?: Lowerer) {\n this.#lowerer = lowerer;\n }\n\n plan(options: {\n readonly contract: unknown;\n readonly schema: unknown;\n readonly policy: MigrationOperationPolicy;\n /**\n * The \"from\" contract (state the planner assumes the database starts\n * at), or `null` for reconciliation flows. Only `migration plan` ever\n * supplies a non-null value; `db update` / `db init` reconcile against\n * the live schema and pass `null`. When present alongside the\n * `'data'` operation class, strategies that need from/to column-shape\n * comparisons (unsafe type change, nullability tightening) activate.\n *\n * Typed as the framework `Contract | null` to satisfy the\n * `MigrationPlanner` interface contract; `planSql` narrows to the SQL\n * shape via `SqlMigrationPlannerPlanOptions`. Used to populate\n * `describe().from` on the produced plan as\n * `fromContract?.storage.storageHash ?? null`.\n */\n readonly fromContract: Contract | null;\n readonly schemaName?: string;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;\n /**\n * Contract space this plan applies to. Stamped onto the produced\n * {@link TypeScriptRenderablePostgresMigration.spaceId} so the runner keys\n * the marker row by the right space.\n */\n readonly spaceId: string;\n }): PostgresPlanResult {\n return this.planSql(options as SqlMigrationPlannerPlanOptions);\n }\n\n emptyMigration(\n context: MigrationScaffoldContext,\n spaceId: string,\n ): MigrationPlanWithAuthoringSurface {\n return new TypeScriptRenderablePostgresMigration(\n [],\n {\n from: context.fromHash,\n to: context.toHash,\n },\n spaceId,\n this.#lowerer,\n );\n }\n\n private planSql(options: SqlMigrationPlannerPlanOptions): PostgresPlanResult {\n const schemaName =\n options.schemaName ??\n Object.keys(options.contract.storage.namespaces).find((id) => id !== UNBOUND_NAMESPACE_ID) ??\n UNBOUND_NAMESPACE_ID;\n const policyResult = this.ensureAdditivePolicy(options.policy);\n if (policyResult) {\n return policyResult;\n }\n\n const schemaIssues = this.collectSchemaIssues(options);\n const codecHooks = extractCodecControlHooks(options.frameworkComponents);\n const storageTypes = options.contract.storage.types ?? {};\n\n // Input-side control-policy partition. `external` / `observed` subjects\n // — and non-creation issues for `tolerated` subjects — are dropped from\n // the planner's input entirely; the planner never observes them, never\n // diffs them, never generates DDL for them. Suppression warnings are\n // built directly from the suppressed partition (one per subject), so the\n // user-visible message survives even when the planner would have failed\n // to model the subject's live shape.\n const issuePartition = partitionIssuesByControlPolicy({\n issues: schemaIssues,\n contract: options.contract,\n resolveControlPolicySubject: (issue) =>\n resolvePostgresIssueControlPolicySubject(issue, options.contract),\n resolveCreationFactoryName: resolvePostgresIssueCreationFactoryName,\n formatSubjectLabel: (factoryName, subject) =>\n formatPostgresControlPolicySubjectLabel(factoryName, subject, options.contract),\n });\n\n const result = planIssues({\n issues: issuePartition.plannable,\n toContract: options.contract,\n // `fromContract` is only supplied by `migration plan`. It is `null` for\n // `db update` / `db init`, which means data-safety strategies needing\n // from/to comparisons (unsafe type change, nullable tightening) are\n // inapplicable there — reconciliation falls through to\n // `mapIssueToCall`'s direct destructive handlers.\n fromContract: options.fromContract,\n schemaName,\n codecHooks,\n storageTypes,\n schema: options.schema,\n policy: options.policy,\n frameworkComponents: options.frameworkComponents,\n strategies: postgresPlannerStrategies,\n });\n\n if (!result.ok) {\n return plannerFailure(result.failure);\n }\n\n // Inline `onFieldEvent`-emitted ops after structural DDL. The fixed\n // ordering is `structural → added → dropped → altered`, with\n // within-group sorting by `(tableName, fieldName)` so re-emits are\n // byte-stable. The hook fires only at the application emitter —\n // extension-space planning never reaches this helper.\n const fieldEventOps = planFieldEventOperations({\n priorContract: options.fromContract,\n newContract: options.contract,\n codecHooks,\n });\n // Codec hook ops are target-agnostic `OpFactoryCall`; Postgres planning\n // lifts them at this integration boundary (see field-event-planner JSDoc).\n const fieldEventPostgresCalls = blindCast<\n readonly PostgresOpFactoryCall[],\n 'Codec hook ops conform to PostgresOpFactoryCall at the app emitter boundary'\n >(fieldEventOps);\n const fieldEventPartition = partitionCallsByControlPolicy({\n calls: fieldEventPostgresCalls,\n contract: options.contract,\n resolveControlPolicySubject: (call) =>\n resolvePostgresCallControlPolicySubject(call, options.contract),\n resolveFactoryName: (call) => call.factoryName,\n formatSubjectLabel: (factoryName, subject) =>\n formatPostgresControlPolicySubjectLabel(factoryName, subject, options.contract),\n });\n const calls = [...result.value.calls, ...fieldEventPartition.kept];\n const warnings: SqlPlannerConflict[] = [\n ...issuePartition.warnings,\n ...fieldEventPartition.warnings,\n ];\n\n return Object.freeze({\n kind: 'success' as const,\n plan: new TypeScriptRenderablePostgresMigration(\n calls,\n {\n from: options.fromContract?.storage.storageHash ?? null,\n to: options.contract.storage.storageHash,\n },\n options.spaceId,\n this.#lowerer,\n ),\n ...(warnings.length > 0 ? { warnings: Object.freeze(warnings) } : {}),\n });\n }\n\n private ensureAdditivePolicy(policy: MigrationOperationPolicy) {\n if (!policy.allowedOperationClasses.includes('additive')) {\n return plannerFailure([\n {\n kind: 'unsupportedOperation',\n summary: 'Migration planner requires additive operations be allowed',\n why: 'The planner requires the \"additive\" operation class to be allowed in the policy.',\n },\n ]);\n }\n return null;\n }\n\n private collectSchemaIssues(options: PlannerOptionsWithComponents): readonly SchemaIssue[] {\n // `db init` uses additive-only policy and intentionally ignores extra\n // schema objects. Any reconciliation-capable policy (widening or\n // destructive) must inspect extras to reconcile strict equality.\n const allowed = options.policy.allowedOperationClasses;\n const strict = allowed.includes('widening') || allowed.includes('destructive');\n const verifyOptions: VerifySqlSchemaOptionsWithComponents = {\n contract: options.contract,\n schema: options.schema,\n strict,\n typeMetadataRegistry: new Map(),\n frameworkComponents: options.frameworkComponents,\n normalizeDefault: parsePostgresDefault,\n normalizeNativeType: normalizeSchemaNativeType,\n resolveExistingEnumValues: createResolveExistingEnumValues(options.contract.storage),\n };\n const verifyResult = verifySqlSchema(verifyOptions);\n // Schema presence is a Postgres-specific concern (no equivalent in\n // SQLite / Mongo), so the issue emission lives in the target layer\n // rather than in the family verifier. Stitch it in here so a single\n // `SchemaIssue[]` flows through `planIssues` and the planner emits\n // CREATE SCHEMA in the dep bucket before any CreateTableCall.\n const namespaceIssues = verifyPostgresNamespacePresence({\n contract: options.contract,\n schema: options.schema,\n });\n if (namespaceIssues.length === 0) {\n return verifyResult.schema.issues;\n }\n return [...namespaceIssues, ...verifyResult.schema.issues];\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"planner-Bv5LV2A-.mjs","names":["#lowerer"],"sources":["../src/core/migrations/control-policy.ts","../src/core/migrations/verify-postgres-namespaces.ts","../src/core/migrations/planner.ts"],"sourcesContent":["import type { Contract } from '@prisma-next/contract/types';\nimport type { ControlPolicySubject } from '@prisma-next/family-sql/control';\nimport type { SchemaIssue } from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport {\n isPostgresEnumStorageEntry,\n type SqlStorage,\n storageTableAt,\n} from '@prisma-next/sql-contract/types';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { isPostgresSchema } from '../postgres-schema';\nimport type { PostgresOpFactoryCall } from './op-factory-call';\n\n/**\n * Factory calls that create a whole, previously-absent top-level storage\n * object. Used to decide whether `tolerated` permits a call (it only allows\n * creating absent objects, never modifying existing ones).\n *\n * Deliberately an explicit, closed set rather than a `factoryName`\n * create/alter/drop classification: it answers exactly one yes/no question\n * and is fail-closed. Any call not listed here — including future or\n * extension-contributed factories — is treated as NOT object-creation, so it\n * is suppressed under `tolerated` rather than permissively emitted.\n */\nconst OBJECT_CREATION_FACTORIES: ReadonlySet<string> = new Set<string>([\n 'createTable',\n 'createEnumType',\n 'createSchema',\n]);\n\nfunction createsNewTopLevelObject(call: PostgresOpFactoryCall): boolean {\n return OBJECT_CREATION_FACTORIES.has(call.factoryName);\n}\n\nfunction ddlSchemaNameForNamespace(contract: Contract<SqlStorage>, namespaceId: string): string {\n const namespace = contract.storage.namespaces[namespaceId];\n return isPostgresSchema(namespace) ? namespace.ddlSchemaName(contract.storage) : namespaceId;\n}\n\nfunction resolveNamespaceIdForTable(\n contract: Contract<SqlStorage>,\n tableName: string,\n ddlSchemaName: string | undefined,\n): string {\n for (const namespaceId of Object.keys(contract.storage.namespaces)) {\n const table = storageTableAt(contract.storage, namespaceId, tableName);\n if (!table) continue;\n if (\n ddlSchemaName === undefined ||\n ddlSchemaNameForNamespace(contract, namespaceId) === ddlSchemaName\n ) {\n return namespaceId;\n }\n }\n return UNBOUND_NAMESPACE_ID;\n}\n\nfunction resolveNamespaceIdForDdlSchema(\n contract: Contract<SqlStorage>,\n ddlSchemaName: string,\n): string {\n for (const namespaceId of Object.keys(contract.storage.namespaces)) {\n const ns = contract.storage.namespaces[namespaceId];\n if (isPostgresSchema(ns) && ns.ddlSchemaName(contract.storage) === ddlSchemaName) {\n return namespaceId;\n }\n if (namespaceId === ddlSchemaName) {\n return namespaceId;\n }\n }\n return UNBOUND_NAMESPACE_ID;\n}\n\ninterface PostgresCallFields {\n readonly schemaName?: string;\n readonly tableName?: string;\n readonly columnName?: string;\n readonly typeName?: string;\n}\n\nfunction postgresCallFields(call: PostgresOpFactoryCall): PostgresCallFields {\n return {\n ...ifDefined('schemaName', 'schemaName' in call ? call.schemaName : undefined),\n ...ifDefined('tableName', 'tableName' in call ? call.tableName : undefined),\n ...ifDefined('columnName', 'columnName' in call ? call.columnName : undefined),\n ...ifDefined('typeName', 'typeName' in call ? call.typeName : undefined),\n };\n}\n\nexport function formatPostgresControlPolicySubjectLabel(\n factoryName: string,\n subject: ControlPolicySubject | undefined,\n contract: Contract<SqlStorage>,\n): string {\n if (subject?.table) {\n const ddlSchema = ddlSchemaNameForNamespace(contract, subject.namespaceId);\n return `${factoryName}(${ddlSchema}.${subject.table})`;\n }\n if (subject?.typeName) {\n const ddlSchema = ddlSchemaNameForNamespace(contract, subject.namespaceId);\n return `${factoryName}(${ddlSchema}.${subject.typeName})`;\n }\n return factoryName;\n}\n\nexport function resolvePostgresCallControlPolicySubject(\n call: PostgresOpFactoryCall,\n contract: Contract<SqlStorage>,\n): ControlPolicySubject | undefined {\n const callFields = postgresCallFields(call);\n const createsNewObject = createsNewTopLevelObject(call);\n\n if (call.factoryName === 'createSchema' && callFields.schemaName) {\n return {\n namespaceId: resolveNamespaceIdForDdlSchema(contract, callFields.schemaName),\n createsNewObject,\n };\n }\n\n if (callFields.typeName && call.factoryName !== 'addColumn') {\n const namespaceId = callFields.schemaName\n ? resolveNamespaceIdForDdlSchema(contract, callFields.schemaName)\n : UNBOUND_NAMESPACE_ID;\n const ns = contract.storage.namespaces[namespaceId];\n const rawEnum = isPostgresSchema(ns) ? ns.entries.type[callFields.typeName] : undefined;\n const controlPolicy = isPostgresEnumStorageEntry(rawEnum) ? rawEnum.control : undefined;\n return {\n namespaceId,\n ...ifDefined('explicitNodeControlPolicy', controlPolicy),\n typeName: callFields.typeName,\n createsNewObject,\n };\n }\n\n if (callFields.tableName) {\n const namespaceId = resolveNamespaceIdForTable(\n contract,\n callFields.tableName,\n callFields.schemaName,\n );\n const table = storageTableAt(contract.storage, namespaceId, callFields.tableName);\n const tableControlPolicy = table?.control;\n return {\n namespaceId,\n ...ifDefined('explicitNodeControlPolicy', tableControlPolicy),\n table: callFields.tableName,\n ...ifDefined('column', callFields.columnName),\n createsNewObject,\n };\n }\n\n if (callFields.schemaName) {\n return {\n namespaceId: resolveNamespaceIdForDdlSchema(contract, callFields.schemaName),\n createsNewObject,\n };\n }\n\n return undefined;\n}\n\n/**\n * Issue kinds that describe the absence of a whole, top-level Postgres\n * object — the same kinds `createsNewTopLevelObject` recognises for calls.\n * Used by {@link resolvePostgresIssueCreationFactoryName} to decide whether\n * a `tolerated` subject permits the issue to flow into the planner\n * (create-if-absent) and to seed the suppressed-subject warning's\n * `factoryName` when the planner is skipped.\n */\nconst POSTGRES_ISSUE_CREATION_FACTORY: Readonly<Record<string, string>> = Object.freeze({\n missing_schema: 'createSchema',\n missing_table: 'createTable',\n type_missing: 'createEnumType',\n});\n\nexport function resolvePostgresIssueCreationFactoryName(issue: SchemaIssue): string | undefined {\n return POSTGRES_ISSUE_CREATION_FACTORY[issue.kind];\n}\n\n/**\n * Resolve the control-policy subject coordinate for a single\n * {@link SchemaIssue}. Mirrors the resolution `resolvePostgresCallControlPolicySubject`\n * performs for a generated DDL call, but works *off the issue* — so the\n * planner can partition issues by effective policy before the diff engine\n * runs. `createsNewObject` is derived from the issue's kind: schema/table/\n * type-missing issues describe a brand-new top-level object; everything else\n * touches an existing object.\n *\n * An `extra_table` issue carries no contract namespace coordinate (the table\n * isn't in any contract namespace), so the subject's `namespaceId` falls\n * back to {@link UNBOUND_NAMESPACE_ID}; the call-side resolver does the same\n * for the `DropTableCall` it produces.\n */\nexport function resolvePostgresIssueControlPolicySubject(\n issue: SchemaIssue,\n contract: Contract<SqlStorage>,\n): ControlPolicySubject | undefined {\n const createsNewObject = POSTGRES_ISSUE_CREATION_FACTORY[issue.kind] !== undefined;\n\n if (issue.kind === 'missing_schema' && issue.namespaceId) {\n return { namespaceId: issue.namespaceId, createsNewObject };\n }\n\n if ('typeName' in issue && issue.typeName) {\n const namespaceId =\n 'namespaceId' in issue && issue.namespaceId ? issue.namespaceId : UNBOUND_NAMESPACE_ID;\n const ns = contract.storage.namespaces[namespaceId];\n const rawEnum = isPostgresSchema(ns) ? ns.entries.type[issue.typeName] : undefined;\n const controlPolicy = isPostgresEnumStorageEntry(rawEnum) ? rawEnum.control : undefined;\n return {\n namespaceId,\n ...ifDefined('explicitNodeControlPolicy', controlPolicy),\n typeName: issue.typeName,\n createsNewObject,\n };\n }\n\n if ('table' in issue && issue.table) {\n const namespaceId =\n 'namespaceId' in issue && issue.namespaceId\n ? issue.namespaceId\n : resolveNamespaceIdForTable(contract, issue.table, undefined);\n const table = storageTableAt(contract.storage, namespaceId, issue.table);\n return {\n namespaceId,\n ...ifDefined('explicitNodeControlPolicy', table?.control),\n table: issue.table,\n ...ifDefined('column', 'column' in issue ? issue.column : undefined),\n createsNewObject,\n };\n }\n\n return undefined;\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type { SchemaIssue } from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { isPostgresSchema } from '../postgres-schema';\n\n/**\n * Resolves the live-database schema name for a given namespace\n * coordinate. Mirrors `resolveDdlSchemaForNamespace` in\n * `planner-strategies.ts` so the verifier's projection and the\n * planner's projection always agree — Postgres-aware namespaces (the\n * production path) dispatch to `ddlSchemaName(storage)`, and bare\n * object payloads (used by some tests) fall back to the coordinate\n * itself.\n */\nfunction resolveDdlSchemaName(storage: SqlStorage, namespaceId: string): string {\n const namespace = storage.namespaces[namespaceId];\n if (isPostgresSchema(namespace)) {\n return namespace.ddlSchemaName(storage);\n }\n return namespaceId;\n}\n\n/**\n * Reads the introspected list of schema names from the Postgres-flavoured\n * annotations slot on the schema IR. Defaults to the always-present\n * `public` schema when introspection did not populate the slot — a fresh\n * Postgres database always carries `public` (unless an operator dropped\n * it manually), so any verifier path that runs without an enriched\n * introspection still suppresses the redundant `CREATE SCHEMA \"public\"`.\n *\n * Production introspection (`PostgresControlAdapter.introspect`) is the\n * authoritative source: it queries `pg_namespace` and writes every\n * non-system schema into `annotations.pg.existingSchemas`. Tests that\n * want to assert against a richer initial state pass the slot\n * explicitly via the schema IR.\n */\nfunction existingSchemasFromSchema(schema: SqlSchemaIR): readonly string[] {\n const annotations = (schema as { annotations?: { pg?: { existingSchemas?: unknown } } })\n .annotations;\n const slot = annotations?.pg?.existingSchemas;\n if (Array.isArray(slot)) {\n return slot.filter((s): s is string => typeof s === 'string');\n }\n return ['public'];\n}\n\n/**\n * Emits a `missing_schema` issue for every contract-declared Postgres\n * namespace whose live container does not yet exist.\n *\n * A namespace's live container is the schema returned by its\n * polymorphic `ddlSchemaName(storage)` method — named schemas resolve\n * to their own id; the unbound singleton returns `UNBOUND_NAMESPACE_ID`\n * and is skipped explicitly (late-bound namespaces have no fixed DDL\n * schema). Issues are emitted only when the resolved name is a real,\n * creatable schema (not the unbound sentinel) and is missing from the\n * introspected list. `public` is suppressed implicitly because the\n * introspection (or its sensible default) always carries it.\n *\n * Each emitted issue stamps `namespaceId` with the contract namespace\n * coordinate so the downstream `mapIssueToCall` re-resolves the DDL\n * schema name through the same polymorphic path — keeping the\n * coordinate, not the resolved name, as the issue's stable identity.\n */\nexport function verifyPostgresNamespacePresence(input: {\n readonly contract: Contract<SqlStorage>;\n readonly schema: SqlSchemaIR;\n}): readonly SchemaIssue[] {\n const { contract, schema } = input;\n const existing = new Set(existingSchemasFromSchema(schema));\n const issues: SchemaIssue[] = [];\n const namespaceIds = Object.keys(contract.storage.namespaces).sort();\n for (const namespaceId of namespaceIds) {\n if (namespaceId === UNBOUND_NAMESPACE_ID) continue;\n const ddlName = resolveDdlSchemaName(contract.storage, namespaceId);\n if (ddlName === UNBOUND_NAMESPACE_ID) continue;\n if (existing.has(ddlName)) continue;\n issues.push({\n kind: 'missing_schema',\n namespaceId,\n message: `Schema \"${ddlName}\" is missing from database`,\n });\n }\n return issues;\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type {\n MigrationOperationPolicy,\n SqlMigrationPlannerPlanOptions,\n SqlPlannerConflict,\n SqlPlannerFailureResult,\n} from '@prisma-next/family-sql/control';\nimport {\n extractCodecControlHooks,\n partitionCallsByControlPolicy,\n partitionIssuesByControlPolicy,\n planFieldEventOperations,\n plannerFailure,\n} from '@prisma-next/family-sql/control';\nimport type { Lowerer } from '@prisma-next/family-sql/control-adapter';\nimport { verifySqlSchema } from '@prisma-next/family-sql/schema-verify';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n MigrationPlanner,\n MigrationPlanWithAuthoringSurface,\n MigrationScaffoldContext,\n SchemaIssue,\n} from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport { parsePostgresDefault } from '../default-normalizer';\nimport { normalizeSchemaNativeType } from '../native-type-normalizer';\nimport {\n formatPostgresControlPolicySubjectLabel,\n resolvePostgresCallControlPolicySubject,\n resolvePostgresIssueControlPolicySubject,\n resolvePostgresIssueCreationFactoryName,\n} from './control-policy';\nimport { createResolveExistingEnumValues } from './enum-planning';\nimport { planIssues } from './issue-planner';\nimport type { PostgresOpFactoryCall } from './op-factory-call';\nimport { TypeScriptRenderablePostgresMigration } from './planner-produced-postgres-migration';\nimport { postgresPlannerStrategies } from './planner-strategies';\nimport { verifyPostgresNamespacePresence } from './verify-postgres-namespaces';\n\ntype PlannerFrameworkComponents = SqlMigrationPlannerPlanOptions extends {\n readonly frameworkComponents: infer T;\n}\n ? T\n : ReadonlyArray<unknown>;\n\ntype PlannerOptionsWithComponents = SqlMigrationPlannerPlanOptions & {\n readonly frameworkComponents: PlannerFrameworkComponents;\n};\n\ntype VerifySqlSchemaOptionsWithComponents = Parameters<typeof verifySqlSchema>[0] & {\n readonly frameworkComponents: PlannerFrameworkComponents;\n};\n\nexport function createPostgresMigrationPlanner(lowerer: Lowerer): PostgresMigrationPlanner {\n return new PostgresMigrationPlanner(lowerer);\n}\n\n/**\n * Result of `PostgresMigrationPlanner.plan()`. A discriminated union whose\n * success variant carries a `TypeScriptRenderablePostgresMigration` — a\n * migration object that both the CLI (via `renderTypeScript()`) and the\n * SQL-typed callers (via `operations`, `describe()`, etc.) consume\n * uniformly.\n */\nexport type PostgresPlanResult =\n | {\n readonly kind: 'success';\n readonly plan: TypeScriptRenderablePostgresMigration;\n readonly warnings?: readonly SqlPlannerConflict[];\n }\n | SqlPlannerFailureResult;\n\n/**\n * Postgres migration planner — a thin wrapper over `planIssues`.\n *\n * `plan()` verifies the live schema against the target contract (producing\n * `SchemaIssue[]`) and delegates to `planIssues` with the unified\n * `postgresPlannerStrategies` list: enum-change, NOT-NULL backfill,\n * type-change, nullable-tightening, codec-hook storage types,\n * component-declared dependency installs, and shared-temp-default /\n * empty-table-guarded NOT-NULL add-column. The same strategy list runs for\n * `migration plan`, `db update`, and `db init`; behavior diverges purely on\n * `policy.allowedOperationClasses` (the data-safe strategies short-circuit\n * when `'data'` is excluded). The issue planner applies operation-class\n * policy gates and emits a single `PostgresOpFactoryCall[]` that drives both\n * the runtime-ops view (via `renderOps`) and the `renderTypeScript()`\n * authoring surface.\n */\nexport class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgres'> {\n readonly #lowerer: Lowerer | undefined;\n\n constructor(lowerer?: Lowerer) {\n this.#lowerer = lowerer;\n }\n\n plan(options: {\n readonly contract: unknown;\n readonly schema: unknown;\n readonly policy: MigrationOperationPolicy;\n /**\n * The \"from\" contract (state the planner assumes the database starts\n * at), or `null` for reconciliation flows. Only `migration plan` ever\n * supplies a non-null value; `db update` / `db init` reconcile against\n * the live schema and pass `null`. When present alongside the\n * `'data'` operation class, strategies that need from/to column-shape\n * comparisons (unsafe type change, nullability tightening) activate.\n *\n * Typed as the framework `Contract | null` to satisfy the\n * `MigrationPlanner` interface contract; `planSql` narrows to the SQL\n * shape via `SqlMigrationPlannerPlanOptions`. Used to populate\n * `describe().from` on the produced plan as\n * `fromContract?.storage.storageHash ?? null`.\n */\n readonly fromContract: Contract | null;\n readonly schemaName?: string;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;\n /**\n * Contract space this plan applies to. Stamped onto the produced\n * {@link TypeScriptRenderablePostgresMigration.spaceId} so the runner keys\n * the marker row by the right space.\n */\n readonly spaceId: string;\n }): PostgresPlanResult {\n return this.planSql(options as SqlMigrationPlannerPlanOptions);\n }\n\n emptyMigration(\n context: MigrationScaffoldContext,\n spaceId: string,\n ): MigrationPlanWithAuthoringSurface {\n return new TypeScriptRenderablePostgresMigration(\n [],\n {\n from: context.fromHash,\n to: context.toHash,\n },\n spaceId,\n this.#lowerer,\n );\n }\n\n private planSql(options: SqlMigrationPlannerPlanOptions): PostgresPlanResult {\n const schemaName =\n options.schemaName ??\n Object.keys(options.contract.storage.namespaces).find((id) => id !== UNBOUND_NAMESPACE_ID) ??\n UNBOUND_NAMESPACE_ID;\n const policyResult = this.ensureAdditivePolicy(options.policy);\n if (policyResult) {\n return policyResult;\n }\n\n const schemaIssues = this.collectSchemaIssues(options);\n const codecHooks = extractCodecControlHooks(options.frameworkComponents);\n const storageTypes = options.contract.storage.types ?? {};\n\n // Input-side control-policy partition. `external` / `observed` subjects\n // — and non-creation issues for `tolerated` subjects — are dropped from\n // the planner's input entirely; the planner never observes them, never\n // diffs them, never generates DDL for them. Suppression warnings are\n // built directly from the suppressed partition (one per subject), so the\n // user-visible message survives even when the planner would have failed\n // to model the subject's live shape.\n const issuePartition = partitionIssuesByControlPolicy({\n issues: schemaIssues,\n contract: options.contract,\n resolveControlPolicySubject: (issue) =>\n resolvePostgresIssueControlPolicySubject(issue, options.contract),\n resolveCreationFactoryName: resolvePostgresIssueCreationFactoryName,\n formatSubjectLabel: (factoryName, subject) =>\n formatPostgresControlPolicySubjectLabel(factoryName, subject, options.contract),\n });\n\n const result = planIssues({\n issues: issuePartition.plannable,\n toContract: options.contract,\n // `fromContract` is only supplied by `migration plan`. It is `null` for\n // `db update` / `db init`, which means data-safety strategies needing\n // from/to comparisons (unsafe type change, nullable tightening) are\n // inapplicable there — reconciliation falls through to\n // `mapIssueToCall`'s direct destructive handlers.\n fromContract: options.fromContract,\n schemaName,\n codecHooks,\n storageTypes,\n schema: options.schema,\n policy: options.policy,\n frameworkComponents: options.frameworkComponents,\n strategies: postgresPlannerStrategies,\n });\n\n if (!result.ok) {\n return plannerFailure(result.failure);\n }\n\n // Inline `onFieldEvent`-emitted ops after structural DDL. The fixed\n // ordering is `structural → added → dropped → altered`, with\n // within-group sorting by `(tableName, fieldName)` so re-emits are\n // byte-stable. The hook fires only at the application emitter —\n // extension-space planning never reaches this helper.\n const fieldEventOps = planFieldEventOperations({\n priorContract: options.fromContract,\n newContract: options.contract,\n codecHooks,\n });\n // Codec hook ops are target-agnostic `OpFactoryCall`; Postgres planning\n // lifts them at this integration boundary (see field-event-planner JSDoc).\n const fieldEventPostgresCalls = blindCast<\n readonly PostgresOpFactoryCall[],\n 'Codec hook ops conform to PostgresOpFactoryCall at the app emitter boundary'\n >(fieldEventOps);\n const fieldEventPartition = partitionCallsByControlPolicy({\n calls: fieldEventPostgresCalls,\n contract: options.contract,\n resolveControlPolicySubject: (call) =>\n resolvePostgresCallControlPolicySubject(call, options.contract),\n resolveFactoryName: (call) => call.factoryName,\n formatSubjectLabel: (factoryName, subject) =>\n formatPostgresControlPolicySubjectLabel(factoryName, subject, options.contract),\n });\n const calls = [...result.value.calls, ...fieldEventPartition.kept];\n const warnings: SqlPlannerConflict[] = [\n ...issuePartition.warnings,\n ...fieldEventPartition.warnings,\n ];\n\n return Object.freeze({\n kind: 'success' as const,\n plan: new TypeScriptRenderablePostgresMigration(\n calls,\n {\n from: options.fromContract?.storage.storageHash ?? null,\n to: options.contract.storage.storageHash,\n },\n options.spaceId,\n this.#lowerer,\n ),\n ...(warnings.length > 0 ? { warnings: Object.freeze(warnings) } : {}),\n });\n }\n\n private ensureAdditivePolicy(policy: MigrationOperationPolicy) {\n if (!policy.allowedOperationClasses.includes('additive')) {\n return plannerFailure([\n {\n kind: 'unsupportedOperation',\n summary: 'Migration planner requires additive operations be allowed',\n why: 'The planner requires the \"additive\" operation class to be allowed in the policy.',\n },\n ]);\n }\n return null;\n }\n\n private collectSchemaIssues(options: PlannerOptionsWithComponents): readonly SchemaIssue[] {\n // `db init` uses additive-only policy and intentionally ignores extra\n // schema objects. Any reconciliation-capable policy (widening or\n // destructive) must inspect extras to reconcile strict equality.\n const allowed = options.policy.allowedOperationClasses;\n const strict = allowed.includes('widening') || allowed.includes('destructive');\n const verifyOptions: VerifySqlSchemaOptionsWithComponents = {\n contract: options.contract,\n schema: options.schema,\n strict,\n typeMetadataRegistry: new Map(),\n frameworkComponents: options.frameworkComponents,\n normalizeDefault: parsePostgresDefault,\n normalizeNativeType: normalizeSchemaNativeType,\n resolveExistingEnumValues: createResolveExistingEnumValues(options.contract.storage),\n };\n const verifyResult = verifySqlSchema(verifyOptions);\n // Schema presence is a Postgres-specific concern (no equivalent in\n // SQLite / Mongo), so the issue emission lives in the target layer\n // rather than in the family verifier. Stitch it in here so a single\n // `SchemaIssue[]` flows through `planIssues` and the planner emits\n // CREATE SCHEMA in the dep bucket before any CreateTableCall.\n const namespaceIssues = verifyPostgresNamespacePresence({\n contract: options.contract,\n schema: options.schema,\n });\n if (namespaceIssues.length === 0) {\n return verifyResult.schema.issues;\n }\n return [...namespaceIssues, ...verifyResult.schema.issues];\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { t as PostgresPlanTargetDetails } from "./planner-target-details-DyUHJ7MY.mjs";
2
- import { t as PostgresMigration } from "./postgres-migration-B6rKNT4N.mjs";
1
+ import { t as PostgresPlanTargetDetails } from "./planner-target-details-CIY6tLeo.mjs";
2
+ import { t as PostgresMigration } from "./postgres-migration-DZ_gLUOW.mjs";
3
3
  import { SqlMigrationPlanOperation } from "@prisma-next/family-sql/control";
4
4
  import { MigrationPlanWithAuthoringSurface, OpFactoryCall } from "@prisma-next/framework-components/control";
5
5
  import { Lowerer } from "@prisma-next/family-sql/control-adapter";
@@ -22,4 +22,4 @@ declare class TypeScriptRenderablePostgresMigration extends PostgresMigration im
22
22
  }
23
23
  //#endregion
24
24
  export { TypeScriptRenderablePostgresMigration as t };
25
- //# sourceMappingURL=planner-produced-postgres-migration-B11fjNTx.d.mts.map
25
+ //# sourceMappingURL=planner-produced-postgres-migration-B4EDvLdz.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"planner-produced-postgres-migration-B11fjNTx.d.mts","names":[],"sources":["../src/core/migrations/planner-produced-postgres-migration.ts"],"mappings":";;;;;;;;KAqCK,EAAA,GAAK,yBAAyB,CAAC,yBAAA;AAAA,cAEvB,qCAAA,SACH,iBAAA,YACG,iCAAA;EAAA;cAQT,KAAA,WAAgB,aAAA,IAChB,IAAA,EAAM,aAAA,EACN,OAAA,UACA,OAAA,GAAU,OAAA;EAAA,IASC,UAAA,aAAuB,EAAA;EAI3B,QAAA,IAAY,aAAA;EAJR;;;;;EAAA,IAaT,OAAA;EAIJ,gBAAA;AAAA"}
1
+ {"version":3,"file":"planner-produced-postgres-migration-B4EDvLdz.d.mts","names":[],"sources":["../src/core/migrations/planner-produced-postgres-migration.ts"],"mappings":";;;;;;;;KAqCK,EAAA,GAAK,yBAAyB,CAAC,yBAAA;AAAA,cAEvB,qCAAA,SACH,iBAAA,YACG,iCAAA;EAAA;cAQT,KAAA,WAAgB,aAAA,IAChB,IAAA,EAAM,aAAA,EACN,OAAA,UACA,OAAA,GAAU,OAAA;EAAA,IASC,UAAA,aAAuB,EAAA;EAI3B,QAAA,IAAY,aAAA;EAJR;;;;;EAAA,IAaT,OAAA;EAIJ,gBAAA;AAAA"}
@@ -1,4 +1,4 @@
1
- import { t as PostgresMigration } from "./postgres-migration-mYtmFD_K.mjs";
1
+ import { t as PostgresMigration } from "./postgres-migration-COore9Mz.mjs";
2
2
  import { t as renderOps } from "./render-ops-BpjstrKQ.mjs";
3
3
  import { t as renderCallsToTypeScript } from "./render-typescript-KMgosran.mjs";
4
4
  //#region src/core/migrations/planner-produced-postgres-migration.ts
@@ -38,4 +38,4 @@ var TypeScriptRenderablePostgresMigration = class extends PostgresMigration {
38
38
  //#endregion
39
39
  export { TypeScriptRenderablePostgresMigration as t };
40
40
 
41
- //# sourceMappingURL=planner-produced-postgres-migration-DkQoyxIu.mjs.map
41
+ //# sourceMappingURL=planner-produced-postgres-migration-NSEhWL0L.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"planner-produced-postgres-migration-DkQoyxIu.mjs","names":["#calls","#meta","#spaceId","#lowerer"],"sources":["../src/core/migrations/planner-produced-postgres-migration.ts"],"sourcesContent":["/**\n * Planner-produced Postgres migration.\n *\n * Returned by `PostgresMigrationPlanner.plan(...)` and `emptyMigration(...)`.\n * Holds the migration IR (`PostgresOpFactoryCall[]`) alongside\n * `MigrationMeta` and exposes both the runtime-ops view (`get operations`)\n * and the TypeScript authoring view (`renderTypeScript()`). Satisfies\n * `MigrationPlanWithAuthoringSurface` so the CLI can uniformly serialize any\n * planner result back to `migration.ts`.\n *\n * Extends the family-level `SqlMigration` alias rather than the target-local\n * migration base directly — mirrors Mongo's `PlannerProducedMongoMigration`\n * shape and keeps CLI wiring one step removed from target internals.\n *\n * Placeholder-bearing plans: `renderTypeScript()` always succeeds and embeds\n * `() => placeholder(\"slot\")` at each stub. `operations`, in contrast, is\n * _not safe to enumerate_ on a stub-bearing plan — `DataTransformCall.toOp()`\n * throws `PN-MIG-2001` because a planner-stubbed closure cannot be lowered\n * to a runtime op. Callers that know a plan may carry stubs must render to\n * `migration.ts`, let the user fill the slots, and re-load the edited\n * migration before enumerating ops. The walk-schema planner does not emit\n * `DataTransformCall`s today, so this asymmetry is invisible until the\n * issue-planner integration lands in Phase 2.\n */\n\nimport type { SqlMigrationPlanOperation } from '@prisma-next/family-sql/control';\nimport type { Lowerer } from '@prisma-next/family-sql/control-adapter';\nimport type {\n MigrationPlanWithAuthoringSurface,\n OpFactoryCall,\n} from '@prisma-next/framework-components/control';\nimport type { MigrationMeta } from '@prisma-next/migration-tools/migration';\nimport type { PostgresPlanTargetDetails } from './planner-target-details';\nimport { PostgresMigration } from './postgres-migration';\nimport { renderOps } from './render-ops';\nimport { renderCallsToTypeScript } from './render-typescript';\n\ntype Op = SqlMigrationPlanOperation<PostgresPlanTargetDetails>;\n\nexport class TypeScriptRenderablePostgresMigration\n extends PostgresMigration\n implements MigrationPlanWithAuthoringSurface\n{\n readonly #calls: readonly OpFactoryCall[];\n readonly #meta: MigrationMeta;\n readonly #spaceId: string;\n readonly #lowerer: Lowerer | undefined;\n\n constructor(\n calls: readonly OpFactoryCall[],\n meta: MigrationMeta,\n spaceId: string,\n lowerer?: Lowerer,\n ) {\n super();\n this.#calls = calls;\n this.#meta = meta;\n this.#spaceId = spaceId;\n this.#lowerer = lowerer;\n }\n\n override get operations(): readonly Op[] {\n return renderOps(this.#calls, this.#lowerer);\n }\n\n override describe(): MigrationMeta {\n return this.#meta;\n }\n\n /**\n * Contract space this planner-produced plan applies to. Threaded\n * from the planner options so the runner keys the marker row by\n * the right space when executing the plan.\n */\n get spaceId(): string {\n return this.#spaceId;\n }\n\n renderTypeScript(): string {\n return renderCallsToTypeScript(this.#calls, { from: this.#meta.from, to: this.#meta.to });\n }\n}\n"],"mappings":";;;;AAuCA,IAAa,wCAAb,cACU,kBAEV;CACE;CACA;CACA;CACA;CAEA,YACE,OACA,MACA,SACA,SACA;EACA,MAAM;EACN,KAAKA,SAAS;EACd,KAAKC,QAAQ;EACb,KAAKC,WAAW;EAChB,KAAKC,WAAW;CAClB;CAEA,IAAa,aAA4B;EACvC,OAAO,UAAU,KAAKH,QAAQ,KAAKG,QAAQ;CAC7C;CAEA,WAAmC;EACjC,OAAO,KAAKF;CACd;;;;;;CAOA,IAAI,UAAkB;EACpB,OAAO,KAAKC;CACd;CAEA,mBAA2B;EACzB,OAAO,wBAAwB,KAAKF,QAAQ;GAAE,MAAM,KAAKC,MAAM;GAAM,IAAI,KAAKA,MAAM;EAAG,CAAC;CAC1F;AACF"}
1
+ {"version":3,"file":"planner-produced-postgres-migration-NSEhWL0L.mjs","names":["#calls","#meta","#spaceId","#lowerer"],"sources":["../src/core/migrations/planner-produced-postgres-migration.ts"],"sourcesContent":["/**\n * Planner-produced Postgres migration.\n *\n * Returned by `PostgresMigrationPlanner.plan(...)` and `emptyMigration(...)`.\n * Holds the migration IR (`PostgresOpFactoryCall[]`) alongside\n * `MigrationMeta` and exposes both the runtime-ops view (`get operations`)\n * and the TypeScript authoring view (`renderTypeScript()`). Satisfies\n * `MigrationPlanWithAuthoringSurface` so the CLI can uniformly serialize any\n * planner result back to `migration.ts`.\n *\n * Extends the family-level `SqlMigration` alias rather than the target-local\n * migration base directly — mirrors Mongo's `PlannerProducedMongoMigration`\n * shape and keeps CLI wiring one step removed from target internals.\n *\n * Placeholder-bearing plans: `renderTypeScript()` always succeeds and embeds\n * `() => placeholder(\"slot\")` at each stub. `operations`, in contrast, is\n * _not safe to enumerate_ on a stub-bearing plan — `DataTransformCall.toOp()`\n * throws `PN-MIG-2001` because a planner-stubbed closure cannot be lowered\n * to a runtime op. Callers that know a plan may carry stubs must render to\n * `migration.ts`, let the user fill the slots, and re-load the edited\n * migration before enumerating ops. The walk-schema planner does not emit\n * `DataTransformCall`s today, so this asymmetry is invisible until the\n * issue-planner integration lands in Phase 2.\n */\n\nimport type { SqlMigrationPlanOperation } from '@prisma-next/family-sql/control';\nimport type { Lowerer } from '@prisma-next/family-sql/control-adapter';\nimport type {\n MigrationPlanWithAuthoringSurface,\n OpFactoryCall,\n} from '@prisma-next/framework-components/control';\nimport type { MigrationMeta } from '@prisma-next/migration-tools/migration';\nimport type { PostgresPlanTargetDetails } from './planner-target-details';\nimport { PostgresMigration } from './postgres-migration';\nimport { renderOps } from './render-ops';\nimport { renderCallsToTypeScript } from './render-typescript';\n\ntype Op = SqlMigrationPlanOperation<PostgresPlanTargetDetails>;\n\nexport class TypeScriptRenderablePostgresMigration\n extends PostgresMigration\n implements MigrationPlanWithAuthoringSurface\n{\n readonly #calls: readonly OpFactoryCall[];\n readonly #meta: MigrationMeta;\n readonly #spaceId: string;\n readonly #lowerer: Lowerer | undefined;\n\n constructor(\n calls: readonly OpFactoryCall[],\n meta: MigrationMeta,\n spaceId: string,\n lowerer?: Lowerer,\n ) {\n super();\n this.#calls = calls;\n this.#meta = meta;\n this.#spaceId = spaceId;\n this.#lowerer = lowerer;\n }\n\n override get operations(): readonly Op[] {\n return renderOps(this.#calls, this.#lowerer);\n }\n\n override describe(): MigrationMeta {\n return this.#meta;\n }\n\n /**\n * Contract space this planner-produced plan applies to. Threaded\n * from the planner options so the runner keys the marker row by\n * the right space when executing the plan.\n */\n get spaceId(): string {\n return this.#spaceId;\n }\n\n renderTypeScript(): string {\n return renderCallsToTypeScript(this.#calls, { from: this.#meta.from, to: this.#meta.to });\n }\n}\n"],"mappings":";;;;AAuCA,IAAa,wCAAb,cACU,kBAEV;CACE;CACA;CACA;CACA;CAEA,YACE,OACA,MACA,SACA,SACA;EACA,MAAM;EACN,KAAKA,SAAS;EACd,KAAKC,QAAQ;EACb,KAAKC,WAAW;EAChB,KAAKC,WAAW;CAClB;CAEA,IAAa,aAA4B;EACvC,OAAO,UAAU,KAAKH,QAAQ,KAAKG,QAAQ;CAC7C;CAEA,WAAmC;EACjC,OAAO,KAAKF;CACd;;;;;;CAOA,IAAI,UAAkB;EACpB,OAAO,KAAKC;CACd;CAEA,mBAA2B;EACzB,OAAO,wBAAwB,KAAKF,QAAQ;GAAE,MAAM,KAAKC,MAAM;GAAM,IAAI,KAAKA,MAAM;EAAG,CAAC;CAC1F;AACF"}
@@ -1,2 +1,2 @@
1
- import { t as TypeScriptRenderablePostgresMigration } from "./planner-produced-postgres-migration-B11fjNTx.mjs";
1
+ import { t as TypeScriptRenderablePostgresMigration } from "./planner-produced-postgres-migration-B4EDvLdz.mjs";
2
2
  export { TypeScriptRenderablePostgresMigration };
@@ -1,2 +1,2 @@
1
- import { t as TypeScriptRenderablePostgresMigration } from "./planner-produced-postgres-migration-DkQoyxIu.mjs";
1
+ import { t as TypeScriptRenderablePostgresMigration } from "./planner-produced-postgres-migration-NSEhWL0L.mjs";
2
2
  export { TypeScriptRenderablePostgresMigration };
@@ -1,5 +1,5 @@
1
1
  //#region src/core/migrations/planner-target-details.d.ts
2
- type OperationClass = 'dependency' | 'type' | 'table' | 'column' | 'primaryKey' | 'unique' | 'index' | 'foreignKey';
2
+ type OperationClass = 'dependency' | 'type' | 'table' | 'column' | 'primaryKey' | 'unique' | 'index' | 'foreignKey' | 'checkConstraint';
3
3
  interface PostgresPlanTargetDetails {
4
4
  readonly schema: string;
5
5
  readonly objectType: OperationClass;
@@ -8,4 +8,4 @@ interface PostgresPlanTargetDetails {
8
8
  }
9
9
  //#endregion
10
10
  export { PostgresPlanTargetDetails as t };
11
- //# sourceMappingURL=planner-target-details-DyUHJ7MY.d.mts.map
11
+ //# sourceMappingURL=planner-target-details-CIY6tLeo.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner-target-details-CIY6tLeo.d.mts","names":[],"sources":["../src/core/migrations/planner-target-details.ts"],"mappings":";KAEY,cAAA;AAAA,UAWK,yBAAA;EAAA,SACN,MAAA;EAAA,SACA,UAAA,EAAY,cAAc;EAAA,SAC1B,IAAA;EAAA,SACA,KAAA;AAAA"}
@@ -1,2 +1,2 @@
1
- import { t as PostgresPlanTargetDetails } from "./planner-target-details-DyUHJ7MY.mjs";
1
+ import { t as PostgresPlanTargetDetails } from "./planner-target-details-CIY6tLeo.mjs";
2
2
  export type { PostgresPlanTargetDetails };
@@ -1,4 +1,4 @@
1
- import { t as TypeScriptRenderablePostgresMigration } from "./planner-produced-postgres-migration-B11fjNTx.mjs";
1
+ import { t as TypeScriptRenderablePostgresMigration } from "./planner-produced-postgres-migration-B4EDvLdz.mjs";
2
2
  import { MigrationOperationPolicy, SqlPlannerConflict, SqlPlannerFailureResult } from "@prisma-next/family-sql/control";
3
3
  import { MigrationPlanWithAuthoringSurface, MigrationPlanner, MigrationScaffoldContext } from "@prisma-next/framework-components/control";
4
4
  import { Contract } from "@prisma-next/contract/types";
package/dist/planner.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as createPostgresMigrationPlanner } from "./planner-BU0He_3s.mjs";
1
+ import { t as createPostgresMigrationPlanner } from "./planner-Bv5LV2A-.mjs";
2
2
  export { createPostgresMigrationPlanner };
@@ -1,4 +1,4 @@
1
- import { d as CreateTableCall, u as CreateSchemaCall } from "./op-factory-call-B4LIiPwu.mjs";
1
+ import { d as CreateSchemaCall, f as CreateTableCall } from "./op-factory-call-D2aAUhmS.mjs";
2
2
  import { t as errorPostgresMigrationStackMissing } from "./errors-CUk87ByX.mjs";
3
3
  import { t as dataTransform } from "./data-transform-D25tLeYU.mjs";
4
4
  import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
@@ -68,4 +68,4 @@ var PostgresMigration = class extends Migration {
68
68
  //#endregion
69
69
  export { PostgresMigration as t };
70
70
 
71
- //# sourceMappingURL=postgres-migration-mYtmFD_K.mjs.map
71
+ //# sourceMappingURL=postgres-migration-COore9Mz.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-migration-mYtmFD_K.mjs","names":["SqlMigration"],"sources":["../src/core/migrations/postgres-migration.ts"],"sourcesContent":["import type { Contract } from '@prisma-next/contract/types';\nimport type { SqlMigrationPlanOperation } from '@prisma-next/family-sql/control';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport { Migration as SqlMigration } from '@prisma-next/family-sql/migration';\nimport type { ControlStack } from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { DdlColumn, DdlTableConstraint } from '@prisma-next/sql-relational-core/ast';\nimport { errorPostgresMigrationStackMissing } from '../errors';\nimport { CreateSchemaCall, CreateTableCall } from './op-factory-call';\nimport { type DataTransformOptions, dataTransform } from './operations/data-transform';\nimport type { PostgresPlanTargetDetails } from './planner-target-details';\n\n/**\n * Target-owned base class for Postgres migrations.\n *\n * Fixes the `SqlMigration` generic to `PostgresPlanTargetDetails` and the\n * abstract `targetId` to the Postgres target-id string literal, so both\n * user-authored migrations and renderer-generated scaffolds (the output of\n * `renderCallsToTypeScript`) can extend `PostgresMigration` directly without\n * redeclaring target-local identity.\n *\n * Mirrors `MongoMigration` in `@prisma-next/family-mongo`: the renderer\n * emits `extends Migration` against a facade re-export of this class\n * from `@prisma-next/postgres/migration`, keeping the authoring surface\n * target-scoped rather than family-scoped.\n *\n * The constructor materializes a single Postgres `SqlControlAdapter` from\n * `stack.adapter.create(stack)` and stores it; the protected `dataTransform`\n * instance method forwards to the free `dataTransform` factory with that\n * stored adapter, so user migrations can write `this.dataTransform(...)`\n * without threading the adapter through every call.\n */\nexport abstract class PostgresMigration extends SqlMigration<\n PostgresPlanTargetDetails,\n 'postgres'\n> {\n readonly targetId = 'postgres' as const;\n\n /**\n * Materialized Postgres control adapter, created once per migration\n * instance from the injected stack. `undefined` only when the migration\n * was instantiated without a stack (test fixtures); `dataTransform`\n * throws in that case to surface the misuse.\n */\n protected readonly controlAdapter: SqlControlAdapter<'postgres'> | undefined;\n\n constructor(stack?: ControlStack<'sql', 'postgres'>) {\n super(stack);\n // The descriptor `create()` is typed as the wider `ControlAdapterInstance`;\n // the Postgres descriptor concretely returns a `SqlControlAdapter<'postgres'>`,\n // so the cast holds for any Postgres-target stack assembled at runtime.\n this.controlAdapter = stack?.adapter\n ? (stack.adapter.create(stack) as SqlControlAdapter<'postgres'>)\n : undefined;\n }\n\n /**\n * Instance-method wrapper around the free `dataTransform` factory that\n * supplies the stored control adapter. Authors call this from inside\n * `get operations()`; the adapter argument is hidden from the call site.\n */\n protected dataTransform<TContract extends Contract<SqlStorage>>(\n contract: TContract,\n name: string,\n options: DataTransformOptions,\n ): SqlMigrationPlanOperation<PostgresPlanTargetDetails> {\n if (!this.controlAdapter) {\n throw errorPostgresMigrationStackMissing();\n }\n return dataTransform(contract, name, options, this.controlAdapter);\n }\n\n /**\n * Emit a `CREATE TABLE` migration operation. Builds a typed DDL node from\n * the supplied options and lowers it through the stored control adapter.\n * Throws if no adapter is present (i.e. migration instantiated without a stack).\n */\n protected createTable(options: {\n readonly schema?: string;\n readonly table: string;\n readonly ifNotExists?: boolean;\n readonly columns: readonly DdlColumn[];\n readonly constraints?: readonly DdlTableConstraint[];\n }): SqlMigrationPlanOperation<PostgresPlanTargetDetails> {\n if (!this.controlAdapter) {\n throw errorPostgresMigrationStackMissing();\n }\n return new CreateTableCall(\n options.schema ?? UNBOUND_NAMESPACE_ID,\n options.table,\n options.columns,\n options.constraints,\n ).toOp(this.controlAdapter);\n }\n\n /**\n * Emit a `CREATE SCHEMA` migration operation. Builds a typed DDL node from\n * the supplied options and lowers it through the stored control adapter.\n * Throws if no adapter is present (i.e. migration instantiated without a stack).\n */\n protected createSchema(options: {\n readonly schema: string;\n readonly ifNotExists?: boolean;\n }): SqlMigrationPlanOperation<PostgresPlanTargetDetails> {\n if (!this.controlAdapter) {\n throw errorPostgresMigrationStackMissing();\n }\n return new CreateSchemaCall(options.schema).toOp(this.controlAdapter);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAsB,oBAAtB,cAAgDA,UAG9C;CACA,WAAoB;;;;;;;CAQpB;CAEA,YAAY,OAAyC;EACnD,MAAM,KAAK;EAIX,KAAK,iBAAiB,OAAO,UACxB,MAAM,QAAQ,OAAO,KAAK,IAC3B,KAAA;CACN;;;;;;CAOA,cACE,UACA,MACA,SACsD;EACtD,IAAI,CAAC,KAAK,gBACR,MAAM,mCAAmC;EAE3C,OAAO,cAAc,UAAU,MAAM,SAAS,KAAK,cAAc;CACnE;;;;;;CAOA,YAAsB,SAMmC;EACvD,IAAI,CAAC,KAAK,gBACR,MAAM,mCAAmC;EAE3C,OAAO,IAAI,gBACT,QAAQ,UAAU,sBAClB,QAAQ,OACR,QAAQ,SACR,QAAQ,WACV,CAAC,CAAC,KAAK,KAAK,cAAc;CAC5B;;;;;;CAOA,aAAuB,SAGkC;EACvD,IAAI,CAAC,KAAK,gBACR,MAAM,mCAAmC;EAE3C,OAAO,IAAI,iBAAiB,QAAQ,MAAM,CAAC,CAAC,KAAK,KAAK,cAAc;CACtE;AACF"}
1
+ {"version":3,"file":"postgres-migration-COore9Mz.mjs","names":["SqlMigration"],"sources":["../src/core/migrations/postgres-migration.ts"],"sourcesContent":["import type { Contract } from '@prisma-next/contract/types';\nimport type { SqlMigrationPlanOperation } from '@prisma-next/family-sql/control';\nimport type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';\nimport { Migration as SqlMigration } from '@prisma-next/family-sql/migration';\nimport type { ControlStack } from '@prisma-next/framework-components/control';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type { SqlStorage } from '@prisma-next/sql-contract/types';\nimport type { DdlColumn, DdlTableConstraint } from '@prisma-next/sql-relational-core/ast';\nimport { errorPostgresMigrationStackMissing } from '../errors';\nimport { CreateSchemaCall, CreateTableCall } from './op-factory-call';\nimport { type DataTransformOptions, dataTransform } from './operations/data-transform';\nimport type { PostgresPlanTargetDetails } from './planner-target-details';\n\n/**\n * Target-owned base class for Postgres migrations.\n *\n * Fixes the `SqlMigration` generic to `PostgresPlanTargetDetails` and the\n * abstract `targetId` to the Postgres target-id string literal, so both\n * user-authored migrations and renderer-generated scaffolds (the output of\n * `renderCallsToTypeScript`) can extend `PostgresMigration` directly without\n * redeclaring target-local identity.\n *\n * Mirrors `MongoMigration` in `@prisma-next/family-mongo`: the renderer\n * emits `extends Migration` against a facade re-export of this class\n * from `@prisma-next/postgres/migration`, keeping the authoring surface\n * target-scoped rather than family-scoped.\n *\n * The constructor materializes a single Postgres `SqlControlAdapter` from\n * `stack.adapter.create(stack)` and stores it; the protected `dataTransform`\n * instance method forwards to the free `dataTransform` factory with that\n * stored adapter, so user migrations can write `this.dataTransform(...)`\n * without threading the adapter through every call.\n */\nexport abstract class PostgresMigration extends SqlMigration<\n PostgresPlanTargetDetails,\n 'postgres'\n> {\n readonly targetId = 'postgres' as const;\n\n /**\n * Materialized Postgres control adapter, created once per migration\n * instance from the injected stack. `undefined` only when the migration\n * was instantiated without a stack (test fixtures); `dataTransform`\n * throws in that case to surface the misuse.\n */\n protected readonly controlAdapter: SqlControlAdapter<'postgres'> | undefined;\n\n constructor(stack?: ControlStack<'sql', 'postgres'>) {\n super(stack);\n // The descriptor `create()` is typed as the wider `ControlAdapterInstance`;\n // the Postgres descriptor concretely returns a `SqlControlAdapter<'postgres'>`,\n // so the cast holds for any Postgres-target stack assembled at runtime.\n this.controlAdapter = stack?.adapter\n ? (stack.adapter.create(stack) as SqlControlAdapter<'postgres'>)\n : undefined;\n }\n\n /**\n * Instance-method wrapper around the free `dataTransform` factory that\n * supplies the stored control adapter. Authors call this from inside\n * `get operations()`; the adapter argument is hidden from the call site.\n */\n protected dataTransform<TContract extends Contract<SqlStorage>>(\n contract: TContract,\n name: string,\n options: DataTransformOptions,\n ): SqlMigrationPlanOperation<PostgresPlanTargetDetails> {\n if (!this.controlAdapter) {\n throw errorPostgresMigrationStackMissing();\n }\n return dataTransform(contract, name, options, this.controlAdapter);\n }\n\n /**\n * Emit a `CREATE TABLE` migration operation. Builds a typed DDL node from\n * the supplied options and lowers it through the stored control adapter.\n * Throws if no adapter is present (i.e. migration instantiated without a stack).\n */\n protected createTable(options: {\n readonly schema?: string;\n readonly table: string;\n readonly ifNotExists?: boolean;\n readonly columns: readonly DdlColumn[];\n readonly constraints?: readonly DdlTableConstraint[];\n }): SqlMigrationPlanOperation<PostgresPlanTargetDetails> {\n if (!this.controlAdapter) {\n throw errorPostgresMigrationStackMissing();\n }\n return new CreateTableCall(\n options.schema ?? UNBOUND_NAMESPACE_ID,\n options.table,\n options.columns,\n options.constraints,\n ).toOp(this.controlAdapter);\n }\n\n /**\n * Emit a `CREATE SCHEMA` migration operation. Builds a typed DDL node from\n * the supplied options and lowers it through the stored control adapter.\n * Throws if no adapter is present (i.e. migration instantiated without a stack).\n */\n protected createSchema(options: {\n readonly schema: string;\n readonly ifNotExists?: boolean;\n }): SqlMigrationPlanOperation<PostgresPlanTargetDetails> {\n if (!this.controlAdapter) {\n throw errorPostgresMigrationStackMissing();\n }\n return new CreateSchemaCall(options.schema).toOp(this.controlAdapter);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAsB,oBAAtB,cAAgDA,UAG9C;CACA,WAAoB;;;;;;;CAQpB;CAEA,YAAY,OAAyC;EACnD,MAAM,KAAK;EAIX,KAAK,iBAAiB,OAAO,UACxB,MAAM,QAAQ,OAAO,KAAK,IAC3B,KAAA;CACN;;;;;;CAOA,cACE,UACA,MACA,SACsD;EACtD,IAAI,CAAC,KAAK,gBACR,MAAM,mCAAmC;EAE3C,OAAO,cAAc,UAAU,MAAM,SAAS,KAAK,cAAc;CACnE;;;;;;CAOA,YAAsB,SAMmC;EACvD,IAAI,CAAC,KAAK,gBACR,MAAM,mCAAmC;EAE3C,OAAO,IAAI,gBACT,QAAQ,UAAU,sBAClB,QAAQ,OACR,QAAQ,SACR,QAAQ,WACV,CAAC,CAAC,KAAK,KAAK,cAAc;CAC5B;;;;;;CAOA,aAAuB,SAGkC;EACvD,IAAI,CAAC,KAAK,gBACR,MAAM,mCAAmC;EAE3C,OAAO,IAAI,iBAAiB,QAAQ,MAAM,CAAC,CAAC,KAAK,KAAK,cAAc;CACtE;AACF"}
@@ -1,5 +1,5 @@
1
- import { t as PostgresPlanTargetDetails } from "./planner-target-details-DyUHJ7MY.mjs";
2
- import { n as DataTransformOptions } from "./data-transform-lq3NGdIt.mjs";
1
+ import { t as PostgresPlanTargetDetails } from "./planner-target-details-CIY6tLeo.mjs";
2
+ import { n as DataTransformOptions } from "./data-transform-DGOqcLrf.mjs";
3
3
  import { DdlColumn, DdlTableConstraint } from "@prisma-next/sql-relational-core/ast";
4
4
  import { SqlMigrationPlanOperation } from "@prisma-next/family-sql/control";
5
5
  import { SqlStorage } from "@prisma-next/sql-contract/types";
@@ -69,4 +69,4 @@ declare abstract class PostgresMigration extends Migration<PostgresPlanTargetDet
69
69
  }
70
70
  //#endregion
71
71
  export { PostgresMigration as t };
72
- //# sourceMappingURL=postgres-migration-B6rKNT4N.d.mts.map
72
+ //# sourceMappingURL=postgres-migration-DZ_gLUOW.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-migration-B6rKNT4N.d.mts","names":[],"sources":["../src/core/migrations/postgres-migration.ts"],"mappings":";;;;;;;;;;;;;AAiCA;;;;;;;;;;;;;;;;;;uBAAsB,iBAAA,SAA0B,SAAA,CAC9C,yBAAA;EAAA,SAGS,QAAA;EAJiD;;;;;;EAAA,mBAYvC,cAAA,EAAgB,iBAAA;cAEvB,KAAA,GAAQ,YAAA;EAAR;;;;;EAAA,UAeF,aAAA,mBAAgC,QAAA,CAAS,UAAA,GACjD,QAAA,EAAU,SAAA,EACV,IAAA,UACA,OAAA,EAAS,oBAAA,GACR,yBAAA,CAA0B,yBAAA;EAH3B;;;;;EAAA,UAeQ,WAAA,CAAY,OAAA;IAAA,SACX,MAAA;IAAA,SACA,KAAA;IAAA,SACA,WAAA;IAAA,SACA,OAAA,WAAkB,SAAA;IAAA,SAClB,WAAA,YAAuB,kBAAA;EAAA,IAC9B,yBAAA,CAA0B,yBAAA;EADnB;;;;;EAAA,UAkBD,YAAA,CAAa,OAAA;IAAA,SACZ,MAAA;IAAA,SACA,WAAA;EAAA,IACP,yBAAA,CAA0B,yBAAA;AAAA"}
1
+ {"version":3,"file":"postgres-migration-DZ_gLUOW.d.mts","names":[],"sources":["../src/core/migrations/postgres-migration.ts"],"mappings":";;;;;;;;;;;;;AAiCA;;;;;;;;;;;;;;;;;;uBAAsB,iBAAA,SAA0B,SAAA,CAC9C,yBAAA;EAAA,SAGS,QAAA;EAJiD;;;;;;EAAA,mBAYvC,cAAA,EAAgB,iBAAA;cAEvB,KAAA,GAAQ,YAAA;EAAR;;;;;EAAA,UAeF,aAAA,mBAAgC,QAAA,CAAS,UAAA,GACjD,QAAA,EAAU,SAAA,EACV,IAAA,UACA,OAAA,EAAS,oBAAA,GACR,yBAAA,CAA0B,yBAAA;EAH3B;;;;;EAAA,UAeQ,WAAA,CAAY,OAAA;IAAA,SACX,MAAA;IAAA,SACA,KAAA;IAAA,SACA,WAAA;IAAA,SACA,OAAA,WAAkB,SAAA;IAAA,SAClB,WAAA,YAAuB,kBAAA;EAAA,IAC9B,yBAAA,CAA0B,yBAAA;EADnB;;;;;EAAA,UAkBD,YAAA,CAAa,OAAA;IAAA,SACZ,MAAA;IAAA,SACA,WAAA;EAAA,IACP,yBAAA,CAA0B,yBAAA;AAAA"}
@@ -1,4 +1,4 @@
1
- import { t as PostgresPlanTargetDetails } from "./planner-target-details-DyUHJ7MY.mjs";
1
+ import { t as PostgresPlanTargetDetails } from "./planner-target-details-CIY6tLeo.mjs";
2
2
  import { SqlMigrationPlanOperation } from "@prisma-next/family-sql/control";
3
3
  import { OpFactoryCall } from "@prisma-next/framework-components/control";
4
4
  import { Lowerer } from "@prisma-next/family-sql/control-adapter";
@@ -1,4 +1,4 @@
1
- import { t as PostgresPlanTargetDetails } from "./planner-target-details-DyUHJ7MY.mjs";
1
+ import { t as PostgresPlanTargetDetails } from "./planner-target-details-CIY6tLeo.mjs";
2
2
  import { SqlMigrationPlanOperation } from "@prisma-next/family-sql/control";
3
3
  import { ReferentialAction } from "@prisma-next/sql-contract/types";
4
4
 
@@ -40,4 +40,4 @@ interface ForeignKeySpec {
40
40
  }
41
41
  //#endregion
42
42
  export { ForeignKeySpec as n, Op as r, ColumnSpec as t };
43
- //# sourceMappingURL=shared-C6QxSU0W.d.mts.map
43
+ //# sourceMappingURL=shared-DarONYBZ.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared-C6QxSU0W.d.mts","names":[],"sources":["../src/core/migrations/operations/shared.ts"],"mappings":";;;;;KAMY,EAAA,GAAK,yBAAyB,CAAC,yBAAA;;AAA3C;;;;AAAoE;AAcpE;;;;;;UAAiB,UAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,UAAA;EAAA,SACA,QAAA;AAAA;;;;;;UAQM,cAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,UAAA;IAAA,SACE,MAAA;IAAA,SACA,KAAA;IAAA,SACA,OAAA;EAAA;EAAA,SAEF,QAAA,GAAW,iBAAA;EAAA,SACX,QAAA,GAAW,iBAAiB;AAAA"}
1
+ {"version":3,"file":"shared-DarONYBZ.d.mts","names":[],"sources":["../src/core/migrations/operations/shared.ts"],"mappings":";;;;;KAMY,EAAA,GAAK,yBAAyB,CAAC,yBAAA;;AAA3C;;;;AAAoE;AAcpE;;;;;;UAAiB,UAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,UAAA;EAAA,SACA,QAAA;AAAA;;;;;;UAQM,cAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,UAAA;IAAA,SACE,MAAA;IAAA,SACA,KAAA;IAAA,SACA,OAAA;EAAA;EAAA,SAEF,QAAA,GAAW,iBAAA;EAAA,SACX,QAAA,GAAW,iBAAiB;AAAA"}
package/package.json CHANGED
@@ -1,32 +1,32 @@
1
1
  {
2
2
  "name": "@prisma-next/target-postgres",
3
- "version": "0.12.0-dev.67",
3
+ "version": "0.12.0-dev.69",
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.12.0-dev.67",
10
- "@prisma-next/contract": "0.12.0-dev.67",
11
- "@prisma-next/errors": "0.12.0-dev.67",
12
- "@prisma-next/family-sql": "0.12.0-dev.67",
13
- "@prisma-next/framework-components": "0.12.0-dev.67",
14
- "@prisma-next/migration-tools": "0.12.0-dev.67",
15
- "@prisma-next/ts-render": "0.12.0-dev.67",
16
- "@prisma-next/sql-contract": "0.12.0-dev.67",
17
- "@prisma-next/sql-errors": "0.12.0-dev.67",
18
- "@prisma-next/sql-operations": "0.12.0-dev.67",
19
- "@prisma-next/sql-relational-core": "0.12.0-dev.67",
20
- "@prisma-next/sql-schema-ir": "0.12.0-dev.67",
21
- "@prisma-next/utils": "0.12.0-dev.67",
9
+ "@prisma-next/cli": "0.12.0-dev.69",
10
+ "@prisma-next/contract": "0.12.0-dev.69",
11
+ "@prisma-next/errors": "0.12.0-dev.69",
12
+ "@prisma-next/family-sql": "0.12.0-dev.69",
13
+ "@prisma-next/framework-components": "0.12.0-dev.69",
14
+ "@prisma-next/migration-tools": "0.12.0-dev.69",
15
+ "@prisma-next/ts-render": "0.12.0-dev.69",
16
+ "@prisma-next/sql-contract": "0.12.0-dev.69",
17
+ "@prisma-next/sql-errors": "0.12.0-dev.69",
18
+ "@prisma-next/sql-operations": "0.12.0-dev.69",
19
+ "@prisma-next/sql-relational-core": "0.12.0-dev.69",
20
+ "@prisma-next/sql-schema-ir": "0.12.0-dev.69",
21
+ "@prisma-next/utils": "0.12.0-dev.69",
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/test-utils": "0.12.0-dev.67",
28
- "@prisma-next/tsconfig": "0.12.0-dev.67",
29
- "@prisma-next/tsdown": "0.12.0-dev.67",
27
+ "@prisma-next/test-utils": "0.12.0-dev.69",
28
+ "@prisma-next/tsconfig": "0.12.0-dev.69",
29
+ "@prisma-next/tsdown": "0.12.0-dev.69",
30
30
  "tsdown": "0.22.1",
31
31
  "typescript": "5.9.3",
32
32
  "vitest": "4.1.7"
@@ -42,6 +42,7 @@ import {
42
42
  CreateIndexCall,
43
43
  CreateSchemaCall,
44
44
  CreateTableCall,
45
+ DropCheckConstraintCall,
45
46
  DropColumnCall,
46
47
  DropConstraintCall,
47
48
  DropDefaultCall,
@@ -121,6 +122,11 @@ const ISSUE_KIND_ORDER: Record<string, number> = {
121
122
  unique_constraint_mismatch: 51,
122
123
  index_mismatch: 52,
123
124
  foreign_key_mismatch: 60,
125
+
126
+ // Check constraints
127
+ check_missing: 53,
128
+ check_mismatch: 54,
129
+ check_removed: 55,
124
130
  };
125
131
 
126
132
  function issueOrder(issue: SchemaIssue): number {
@@ -572,6 +578,48 @@ function mapIssueToCall(
572
578
  ),
573
579
  );
574
580
 
581
+ case 'check_missing': {
582
+ if (!issue.table || !issue.indexOrConstraint)
583
+ return notOk(
584
+ issueConflict('unsupportedOperation', 'Check missing issue has no table/constraint name'),
585
+ );
586
+ // check_missing is normally consumed by checkConstraintPlanCallStrategy.
587
+ // This case handles any that arrive here (e.g. in tests that invoke
588
+ // mapIssueToCall directly or skip the strategy).
589
+ return notOk(
590
+ issueConflict(
591
+ 'unsupportedOperation',
592
+ `Check constraint "${issue.indexOrConstraint}" missing on "${issue.table}" — handled by checkConstraintPlanCallStrategy`,
593
+ ),
594
+ );
595
+ }
596
+
597
+ case 'check_mismatch': {
598
+ if (!issue.table || !issue.indexOrConstraint)
599
+ return notOk(
600
+ issueConflict(
601
+ 'unsupportedOperation',
602
+ 'Check mismatch issue has no table/constraint name',
603
+ ),
604
+ );
605
+ return notOk(
606
+ issueConflict(
607
+ 'unsupportedOperation',
608
+ `Check constraint "${issue.indexOrConstraint}" values mismatch on "${issue.table}" — handled by checkConstraintPlanCallStrategy`,
609
+ ),
610
+ );
611
+ }
612
+
613
+ case 'check_removed': {
614
+ if (!issue.table || !issue.indexOrConstraint)
615
+ return notOk(
616
+ issueConflict('unsupportedOperation', 'Check removed issue has no table/constraint name'),
617
+ );
618
+ return ok([
619
+ new DropCheckConstraintCall(tableSchema(issue), issue.table, issue.indexOrConstraint),
620
+ ]);
621
+ }
622
+
575
623
  case 'foreign_key_mismatch':
576
624
  if (!issue.table)
577
625
  return notOk(issueConflict('foreignKeyConflict', 'Foreign key issue has no table name'));
@@ -704,9 +752,12 @@ function classifyCall(call: PostgresOpFactoryCall): CallCategory {
704
752
  case 'dropTable':
705
753
  case 'dropColumn':
706
754
  case 'dropConstraint':
755
+ case 'dropCheckConstraint':
707
756
  case 'dropIndex':
708
757
  case 'dropDefault':
709
758
  return 'drop';
759
+ case 'addCheckConstraint':
760
+ return 'unique'; // after uniques, before indexes
710
761
  case 'createTable':
711
762
  return 'table';
712
763
  case 'addColumn':
@@ -48,7 +48,14 @@ import {
48
48
  setDefault,
49
49
  setNotNull,
50
50
  } from './operations/columns';
51
- import { addForeignKey, addPrimaryKey, addUnique, dropConstraint } from './operations/constraints';
51
+ import {
52
+ addCheckConstraint,
53
+ addForeignKey,
54
+ addPrimaryKey,
55
+ addUnique,
56
+ dropCheckConstraint,
57
+ dropConstraint,
58
+ } from './operations/constraints';
52
59
  import { createExtension } from './operations/dependencies';
53
60
  import { addEnumValues, createEnumType, dropEnumType, renameType } from './operations/enums';
54
61
  import { createIndex, dropIndex } from './operations/indexes';
@@ -660,6 +667,74 @@ export class DropConstraintCall extends PostgresOpFactoryCallNode {
660
667
  }
661
668
  }
662
669
 
670
+ export class AddCheckConstraintCall extends PostgresOpFactoryCallNode {
671
+ readonly factoryName = 'addCheckConstraint' as const;
672
+ readonly operationClass = 'additive' as const;
673
+ readonly schemaName: string;
674
+ readonly tableName: string;
675
+ readonly constraintName: string;
676
+ readonly column: string;
677
+ readonly values: readonly string[];
678
+ readonly label: string;
679
+
680
+ constructor(
681
+ schemaName: string,
682
+ tableName: string,
683
+ constraintName: string,
684
+ column: string,
685
+ values: readonly string[],
686
+ ) {
687
+ super();
688
+ this.schemaName = schemaName;
689
+ this.tableName = tableName;
690
+ this.constraintName = constraintName;
691
+ this.column = column;
692
+ this.values = values;
693
+ this.label = `Add check constraint "${constraintName}" on "${tableName}"."${column}"`;
694
+ this.freeze();
695
+ }
696
+
697
+ toOp(): Op {
698
+ return addCheckConstraint(
699
+ this.schemaName,
700
+ this.tableName,
701
+ this.constraintName,
702
+ this.column,
703
+ this.values,
704
+ );
705
+ }
706
+
707
+ renderTypeScript(): string {
708
+ return `addCheckConstraint(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.constraintName)}, ${jsonToTsSource(this.column)}, ${jsonToTsSource(this.values)})`;
709
+ }
710
+ }
711
+
712
+ export class DropCheckConstraintCall extends PostgresOpFactoryCallNode {
713
+ readonly factoryName = 'dropCheckConstraint' as const;
714
+ readonly operationClass = 'destructive' as const;
715
+ readonly schemaName: string;
716
+ readonly tableName: string;
717
+ readonly constraintName: string;
718
+ readonly label: string;
719
+
720
+ constructor(schemaName: string, tableName: string, constraintName: string) {
721
+ super();
722
+ this.schemaName = schemaName;
723
+ this.tableName = tableName;
724
+ this.constraintName = constraintName;
725
+ this.label = `Drop check constraint "${constraintName}" on "${tableName}"`;
726
+ this.freeze();
727
+ }
728
+
729
+ toOp(): Op {
730
+ return dropCheckConstraint(this.schemaName, this.tableName, this.constraintName);
731
+ }
732
+
733
+ renderTypeScript(): string {
734
+ return `dropCheckConstraint(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.constraintName)})`;
735
+ }
736
+ }
737
+
663
738
  // ============================================================================
664
739
  // Indexes
665
740
  // ============================================================================
@@ -1041,6 +1116,8 @@ export type PostgresOpFactoryCall =
1041
1116
  | AddPrimaryKeyCall
1042
1117
  | AddForeignKeyCall
1043
1118
  | AddUniqueCall
1119
+ | AddCheckConstraintCall
1120
+ | DropCheckConstraintCall
1044
1121
  | CreateIndexCall
1045
1122
  | DropIndexCall
1046
1123
  | DropConstraintCall