@prisma-next/target-postgres 0.4.0-dev.8 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/control.d.mts +1 -9
  2. package/dist/control.d.mts.map +1 -1
  3. package/dist/control.mjs +1693 -4798
  4. package/dist/control.mjs.map +1 -1
  5. package/dist/migration.d.mts +164 -0
  6. package/dist/migration.d.mts.map +1 -0
  7. package/dist/migration.mjs +446 -0
  8. package/dist/migration.mjs.map +1 -0
  9. package/dist/planner-target-details-MXb3oeul.d.mts +11 -0
  10. package/dist/planner-target-details-MXb3oeul.d.mts.map +1 -0
  11. package/dist/postgres-migration-BsHJHV9O.mjs +2793 -0
  12. package/dist/postgres-migration-BsHJHV9O.mjs.map +1 -0
  13. package/package.json +21 -19
  14. package/src/core/migrations/issue-planner.ts +832 -0
  15. package/src/core/migrations/op-factory-call.ts +862 -0
  16. package/src/core/migrations/operations/columns.ts +285 -0
  17. package/src/core/migrations/operations/constraints.ts +191 -0
  18. package/src/core/migrations/operations/data-transform.ts +113 -0
  19. package/src/core/migrations/operations/dependencies.ts +36 -0
  20. package/src/core/migrations/operations/enums.ts +113 -0
  21. package/src/core/migrations/operations/indexes.ts +61 -0
  22. package/src/core/migrations/operations/raw.ts +15 -0
  23. package/src/core/migrations/operations/shared.ts +67 -0
  24. package/src/core/migrations/operations/tables.ts +63 -0
  25. package/src/core/migrations/planner-produced-postgres-migration.ts +67 -0
  26. package/src/core/migrations/planner-strategies.ts +592 -151
  27. package/src/core/migrations/planner-target-details.ts +0 -6
  28. package/src/core/migrations/planner.ts +63 -781
  29. package/src/core/migrations/postgres-migration.ts +20 -0
  30. package/src/core/migrations/render-ops.ts +9 -0
  31. package/src/core/migrations/render-typescript.ts +95 -0
  32. package/src/exports/control.ts +9 -142
  33. package/src/exports/migration.ts +40 -0
  34. package/dist/migration-builders.d.mts +0 -88
  35. package/dist/migration-builders.d.mts.map +0 -1
  36. package/dist/migration-builders.mjs +0 -3
  37. package/dist/operation-descriptors-CxymFSgK.mjs +0 -52
  38. package/dist/operation-descriptors-CxymFSgK.mjs.map +0 -1
  39. package/src/core/migrations/descriptor-planner.ts +0 -464
  40. package/src/core/migrations/operation-descriptors.ts +0 -166
  41. package/src/core/migrations/operation-resolver.ts +0 -929
  42. package/src/core/migrations/planner-reconciliation.ts +0 -798
  43. package/src/core/migrations/scaffolding.ts +0 -140
  44. package/src/exports/migration-builders.ts +0 -56
@@ -0,0 +1,164 @@
1
+ import { t as PostgresPlanTargetDetails } from "./planner-target-details-MXb3oeul.mjs";
2
+ import { SqlMigrationPlanOperation } from "@prisma-next/family-sql/control";
3
+ import { placeholder } from "@prisma-next/errors/migration";
4
+ import { Migration } from "@prisma-next/family-sql/migration";
5
+ import { Contract } from "@prisma-next/contract/types";
6
+ import { ReferentialAction, SqlStorage } from "@prisma-next/sql-contract/types";
7
+ import { DataTransformOperation } from "@prisma-next/framework-components/control";
8
+ import { SqlQueryPlan } from "@prisma-next/sql-relational-core/plan";
9
+
10
+ //#region src/core/migrations/operations/shared.d.ts
11
+ type Op = SqlMigrationPlanOperation<PostgresPlanTargetDetails>;
12
+ /**
13
+ * Literal-args shape for a column definition consumed by `createTable` and
14
+ * `addColumn`. Fully materialized: codec expansion and default rendering have
15
+ * already happened in the wrapper.
16
+ *
17
+ * - `typeSql` is the column's DDL type string (e.g. `"integer"`, `"SERIAL"`,
18
+ * `"varchar(100)"`), already produced by `buildColumnTypeSql` in the
19
+ * call-factory wrapper.
20
+ * - `defaultSql` is the full `DEFAULT …` clause (e.g. `"DEFAULT 42"`) or an
21
+ * empty string when the column has no default, matching
22
+ * `buildColumnDefaultSql`'s output.
23
+ */
24
+ interface ColumnSpec {
25
+ readonly name: string;
26
+ readonly typeSql: string;
27
+ readonly defaultSql: string;
28
+ readonly nullable: boolean;
29
+ }
30
+ /**
31
+ * Literal-args shape for a foreign key definition. The referenced table is
32
+ * assumed to live in the same schema as the constrained table.
33
+ */
34
+ interface ForeignKeySpec {
35
+ readonly name: string;
36
+ readonly columns: readonly string[];
37
+ readonly references: {
38
+ readonly table: string;
39
+ readonly columns: readonly string[];
40
+ };
41
+ readonly onDelete?: ReferentialAction;
42
+ readonly onUpdate?: ReferentialAction;
43
+ }
44
+ //#endregion
45
+ //#region src/core/migrations/operations/columns.d.ts
46
+ declare function addColumn(schemaName: string, tableName: string, column: ColumnSpec): Op;
47
+ declare function dropColumn(schemaName: string, tableName: string, columnName: string): Op;
48
+ /**
49
+ * `qualifiedTargetType` is the new column type as it appears in the
50
+ * `ALTER COLUMN TYPE` clause (schema-qualified for user-defined types, raw
51
+ * native name for built-ins). `formatTypeExpected` is the unqualified
52
+ * `format_type` form used in the postcheck. `rawTargetTypeForLabel` is the
53
+ * string appearing in the human-readable label (typically `toType` when
54
+ * explicit, else the column's native type).
55
+ */
56
+ declare function alterColumnType(schemaName: string, tableName: string, columnName: string, options: {
57
+ readonly qualifiedTargetType: string;
58
+ readonly formatTypeExpected: string;
59
+ readonly rawTargetTypeForLabel: string;
60
+ readonly using?: string;
61
+ }): Op;
62
+ declare function setNotNull(schemaName: string, tableName: string, columnName: string): Op;
63
+ declare function dropNotNull(schemaName: string, tableName: string, columnName: string): Op;
64
+ /**
65
+ * `defaultSql` is the full `DEFAULT …` clause as produced by
66
+ * `buildColumnDefaultSql` — e.g. `"DEFAULT 42"`,
67
+ * `"DEFAULT (CURRENT_TIMESTAMP)"`, or `"DEFAULT nextval('seq'::regclass)"`.
68
+ *
69
+ * `operationClass` defaults to `'additive'` (setting a default on a column
70
+ * that currently has none). The reconciliation planner passes `'widening'`
71
+ * when the column already has a different default — policy enforcement
72
+ * treats that as a widening change rather than an additive one.
73
+ */
74
+ declare function setDefault(schemaName: string, tableName: string, columnName: string, defaultSql: string, operationClass?: 'additive' | 'widening'): Op;
75
+ declare function dropDefault(schemaName: string, tableName: string, columnName: string): Op;
76
+ //#endregion
77
+ //#region src/core/migrations/operations/constraints.d.ts
78
+ declare function addPrimaryKey(schemaName: string, tableName: string, constraintName: string, columns: readonly string[]): Op;
79
+ declare function addUnique(schemaName: string, tableName: string, constraintName: string, columns: readonly string[]): Op;
80
+ declare function addForeignKey(schemaName: string, tableName: string, fk: ForeignKeySpec): Op;
81
+ /**
82
+ * `kind` feeds the operation's `target.details.objectType`. Descriptor-flow
83
+ * does not carry kind information in its drop-constraint descriptor, so the
84
+ * default is `'unique'`. The reconciliation planner passes the correct kind
85
+ * (`'foreignKey'`, `'primaryKey'`, or `'unique'`) based on the `SchemaIssue`
86
+ * that produced the drop.
87
+ */
88
+ declare function dropConstraint(schemaName: string, tableName: string, constraintName: string, kind?: 'foreignKey' | 'unique' | 'primaryKey'): Op;
89
+ //#endregion
90
+ //#region src/core/migrations/operations/data-transform.d.ts
91
+ interface Buildable<R = unknown> {
92
+ build(): SqlQueryPlan<R>;
93
+ }
94
+ /**
95
+ * A single-closure producer of a SQL query plan. Shared between
96
+ * `check` and each `run` entry.
97
+ */
98
+ type DataTransformClosure = () => SqlQueryPlan | Buildable;
99
+ interface DataTransformOptions {
100
+ /** Optional pre-flight query. `undefined` means "no check". */
101
+ readonly check?: DataTransformClosure;
102
+ /** One or more mutation queries to execute. */
103
+ readonly run: DataTransformClosure | readonly DataTransformClosure[];
104
+ }
105
+ declare function dataTransform<TContract extends Contract<SqlStorage>>(contract: TContract, name: string, options: DataTransformOptions): DataTransformOperation;
106
+ //#endregion
107
+ //#region src/core/migrations/operations/dependencies.d.ts
108
+ declare function createExtension(extensionName: string): Op;
109
+ declare function createSchema(schemaName: string): Op;
110
+ //#endregion
111
+ //#region src/core/migrations/operations/enums.d.ts
112
+ declare function createEnumType(schemaName: string, typeName: string, values: readonly string[]): Op;
113
+ /**
114
+ * `typeName` is the contract-facing type name (used for id/label).
115
+ * `nativeType` is the Postgres type name to mutate (may differ for external types).
116
+ */
117
+ declare function addEnumValues(schemaName: string, typeName: string, nativeType: string, values: readonly string[]): Op;
118
+ declare function dropEnumType(schemaName: string, typeName: string): Op;
119
+ declare function renameType(schemaName: string, fromName: string, toName: string): Op;
120
+ //#endregion
121
+ //#region src/core/migrations/operations/indexes.d.ts
122
+ declare function createIndex(schemaName: string, tableName: string, indexName: string, columns: readonly string[]): Op;
123
+ declare function dropIndex(schemaName: string, tableName: string, indexName: string): Op;
124
+ //#endregion
125
+ //#region src/core/migrations/operations/raw.d.ts
126
+ /**
127
+ * Identity factory for an already-materialized `SqlMigrationPlanOperation`.
128
+ *
129
+ * The planner uses this via `liftOpToCall` to carry ops produced by SQL
130
+ * family methods, codec control hooks, and component database dependencies
131
+ * alongside migration IR without reverse-engineering them. Users writing
132
+ * raw migrations can pass a full op shape directly — typically built by
133
+ * composing SQL family helpers — to author a migration that bypasses the
134
+ * structured call classes.
135
+ */
136
+ declare function rawSql(op: Op): Op;
137
+ //#endregion
138
+ //#region src/core/migrations/operations/tables.d.ts
139
+ declare function createTable(schemaName: string, tableName: string, columns: ReadonlyArray<ColumnSpec>, primaryKey?: {
140
+ readonly columns: readonly string[];
141
+ }): Op;
142
+ declare function dropTable(schemaName: string, tableName: string): Op;
143
+ //#endregion
144
+ //#region src/core/migrations/postgres-migration.d.ts
145
+ /**
146
+ * Target-owned base class for Postgres migrations.
147
+ *
148
+ * Fixes the `SqlMigration` generic to `PostgresPlanTargetDetails` and the
149
+ * abstract `targetId` to the Postgres target-id string literal, so both
150
+ * user-authored migrations and renderer-generated scaffolds (the output of
151
+ * `renderCallsToTypeScript`) can extend `PostgresMigration` directly without
152
+ * redeclaring target-local identity.
153
+ *
154
+ * Mirrors `MongoMigration` in `@prisma-next/family-mongo`: the renderer
155
+ * emits `extends Migration` against a target-specific re-export of this
156
+ * class from `@prisma-next/target-postgres/migration`, keeping the
157
+ * authoring surface target-scoped rather than family-scoped.
158
+ */
159
+ declare abstract class PostgresMigration extends Migration<PostgresPlanTargetDetails> {
160
+ readonly targetId: "postgres";
161
+ }
162
+ //#endregion
163
+ export { type DataTransformClosure, type DataTransformOptions, PostgresMigration as Migration, addColumn, addEnumValues, addForeignKey, addPrimaryKey, addUnique, alterColumnType, createEnumType, createExtension, createIndex, createSchema, createTable, dataTransform, dropColumn, dropConstraint, dropDefault, dropEnumType, dropIndex, dropNotNull, dropTable, placeholder, rawSql, renameType, setDefault, setNotNull };
164
+ //# sourceMappingURL=migration.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration.d.mts","names":[],"sources":["../src/core/migrations/operations/shared.ts","../src/core/migrations/operations/columns.ts","../src/core/migrations/operations/constraints.ts","../src/core/migrations/operations/data-transform.ts","../src/core/migrations/operations/dependencies.ts","../src/core/migrations/operations/enums.ts","../src/core/migrations/operations/indexes.ts","../src/core/migrations/operations/raw.ts","../src/core/migrations/operations/tables.ts","../src/core/migrations/postgres-migration.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;KAMY,EAAA,GAAK,0BAA0B;;;;;;;AAA3C;AAcA;AAWA;;;;ACrBgB,UDUC,UAAA,CCVwD;EAoCzD,SAAA,IAAU,EAAA,MAAA;EAyCV,SAAA,OAAA,EAAe,MAAA;EA+Cf,SAAA,UAAU,EAAA,MAA6D;EAqCvE,SAAA,QAAW,EAAA,OAA6D;AA2CxF;AAuCA;;;;ACvNgB,UFPC,cAAA,CEYd;EAkCa,SAAA,IAAS,EAAA,MAAA;EAuCT,SAAA,OAAa,EAAA,SAAA,MAA4C,EAAA;EAsCzD,SAAA,UAAc,EAAA;;;;EC1HpB,SAAA,QAAS,CAAA,EHMG,iBGLX;EAOC,SAAA,QAAA,CAAA,EHDU,iBGCmB;AAEzC;;;iBFhCgB,SAAA,gDAAyD,aAAa;iBAoCtE,UAAA,6DAAuE;;;;;;;;ADxCvF;AAciB,iBCmED,eAAA,CDnEW,UAAA,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,OAAA,EAAA;EAWV,SAAA,mBAAc,EAOT,MAAA;;;;AC5BtB,CAAA,CAAA,EAuFG,EAvFa;AAoCA,iBAwFA,UAAA,CAxFyE,UAAA,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,CAAA,EAwFF,EAxFE;AAyCzE,iBAoFA,WAAA,CA1Eb,UAAE,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,CAAA,EA0EmF,EA1EnF;AAqCL;AAqCA;AA2CA;AAuCA;;;;ACvNA;AAuCA;AAuCA;AAsCgB,iBD4DA,UAAA,CCvDb,UAAE,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,cAAA,CAAA,EAAA,UAAA,GAAA,UAAA,CAAA,ED6DF,EC7DE;iBD8FW,WAAA,6DAAwE;;;iBCvNxE,aAAA,6FAKb;iBAkCa,SAAA,6FAKb;iBAkCa,aAAA,4CAAyD,iBAAiB;;;;;;;AF9G1F;AAciB,iBEsID,cAAA,CFtIW,UAAA,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,EAAA,cAAA,EAAA,MAAA,EAAA,IAAA,CAAA,EAAA,YAAA,GAAA,QAAA,GAAA,YAAA,CAAA,EE2IxB,EF3IwB;;;UGYjB;WACC,aAAa;ADKxB;AAuCA;AAuCA;AAsCA;;KClHY,oBAAA,SAA6B,eAAe;UAEvC,oBAAA;EAVP;EAQE,SAAA,KAAA,CAAA,EAIO,oBAJsB;EAExB;EAEE,SAAA,GAAA,EAEH,oBAFG,GAAA,SAE6B,oBAF7B,EAAA;;AAE6B,iBAYhC,aAZgC,CAAA,kBAYA,QAZA,CAYS,UAZT,CAAA,CAAA,CAAA,QAAA,EAapC,SAboC,EAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAerC,oBAfqC,CAAA,EAgB7C,sBAhB6C;;;iBC3ChC,eAAA,yBAAwC;iBAiBxC,YAAA,sBAAkC;;;iBCNlC,cAAA,mEAIb;;;;;iBA8Ba,aAAA,uFAKb;iBAsBa,YAAA,wCAAoD;iBAepD,UAAA,wDAAkE;;;iBCtFlE,WAAA,wFAKb;iBA6Ba,SAAA,4DAAqE;;;;;;;;;;;;ANhCrF;AAciB,iBORD,MAAA,CPQW,EAAA,EORA,EPQA,CAAA,EORK,EPQL;;;iBQhBX,WAAA,iDAGL,cAAc;;IAEtB;iBAgCa,SAAA,yCAAkD;;;;;;;;;;;ARnClE;AAcA;AAWA;;;;ACrBgB,uBQOM,iBAAA,SAA0B,SRPwC,CQO3B,yBRP2B,CAAA,CAAA;EAoCxE,SAAA,QAAU,EAAA,UAA+D;AAyCzF"}
@@ -0,0 +1,446 @@
1
+ import { F as escapeLiteral, I as quoteIdentifier, M as codecDefinitions, N as PG_JSONB_CODEC_ID, P as PG_JSON_CODEC_ID, S as setNotNull, _ as alterColumnType, a as dropIndex, b as dropNotNull, c as dropEnumType, d as createSchema, f as addForeignKey, g as addColumn, h as dropConstraint, i as createIndex, l as renameType, m as addUnique, n as createTable, o as addEnumValues, p as addPrimaryKey, r as dropTable, s as createEnumType, t as PostgresMigration, u as createExtension, v as dropColumn, x as setDefault, y as dropDefault } from "./postgres-migration-BsHJHV9O.mjs";
2
+ import { ifDefined } from "@prisma-next/utils/defined";
3
+ import { LiteralExpr, createCodecRegistry } from "@prisma-next/sql-relational-core/ast";
4
+ import { errorDataTransformContractMismatch, placeholder } from "@prisma-next/errors/migration";
5
+ import { lowerSqlPlan } from "@prisma-next/sql-runtime";
6
+
7
+ //#region ../../6-adapters/postgres/dist/adapter-Du9Hr9Rl.mjs
8
+ const VECTOR_CODEC_ID = "pg/vector@1";
9
+ function getCodecParamCast(codecId) {
10
+ if (codecId === VECTOR_CODEC_ID) return "vector";
11
+ if (codecId === PG_JSON_CODEC_ID) return "json";
12
+ if (codecId === PG_JSONB_CODEC_ID) return "jsonb";
13
+ }
14
+ function renderTypedParam(index, codecId) {
15
+ const cast = getCodecParamCast(codecId);
16
+ return cast ? `$${index}::${cast}` : `$${index}`;
17
+ }
18
+ const defaultCapabilities = Object.freeze({
19
+ postgres: {
20
+ orderBy: true,
21
+ limit: true,
22
+ lateral: true,
23
+ jsonAgg: true,
24
+ returning: true
25
+ },
26
+ sql: {
27
+ enums: true,
28
+ returning: true,
29
+ defaultInInsert: true
30
+ }
31
+ });
32
+ const parameterizedCodecs = Object.values(codecDefinitions).map((definition) => definition.codec).filter((codec$1) => codec$1.paramsSchema !== void 0).map((codec$1) => Object.freeze({
33
+ codecId: codec$1.id,
34
+ paramsSchema: codec$1.paramsSchema,
35
+ ...ifDefined("init", codec$1.init)
36
+ }));
37
+ var PostgresAdapterImpl = class {
38
+ familyId = "sql";
39
+ targetId = "postgres";
40
+ profile;
41
+ codecRegistry = (() => {
42
+ const registry = createCodecRegistry();
43
+ for (const definition of Object.values(codecDefinitions)) registry.register(definition.codec);
44
+ return registry;
45
+ })();
46
+ constructor(options) {
47
+ this.profile = Object.freeze({
48
+ id: options?.profileId ?? "postgres/default@1",
49
+ target: "postgres",
50
+ capabilities: defaultCapabilities,
51
+ codecs: () => this.codecRegistry,
52
+ readMarkerStatement: () => ({
53
+ sql: "select core_hash, profile_hash, contract_json, canonical_version, updated_at, app_tag, meta from prisma_contract.marker where id = $1",
54
+ params: [1]
55
+ })
56
+ });
57
+ }
58
+ parameterizedCodecs() {
59
+ return parameterizedCodecs;
60
+ }
61
+ lower(ast, context) {
62
+ const collectedParamRefs = ast.collectParamRefs();
63
+ const paramIndexMap = /* @__PURE__ */ new Map();
64
+ const params = [];
65
+ for (const ref of collectedParamRefs) {
66
+ if (paramIndexMap.has(ref)) continue;
67
+ paramIndexMap.set(ref, params.length + 1);
68
+ params.push(ref.value);
69
+ }
70
+ let sql;
71
+ const node = ast;
72
+ switch (node.kind) {
73
+ case "select":
74
+ sql = renderSelect(node, context.contract, paramIndexMap);
75
+ break;
76
+ case "insert":
77
+ sql = renderInsert(node, context.contract, paramIndexMap);
78
+ break;
79
+ case "update":
80
+ sql = renderUpdate(node, context.contract, paramIndexMap);
81
+ break;
82
+ case "delete":
83
+ sql = renderDelete(node, context.contract, paramIndexMap);
84
+ break;
85
+ default: throw new Error(`Unsupported AST node kind: ${node.kind}`);
86
+ }
87
+ return Object.freeze({
88
+ profileId: this.profile.id,
89
+ body: Object.freeze({
90
+ sql,
91
+ params
92
+ })
93
+ });
94
+ }
95
+ };
96
+ function renderSelect(ast, contract, pim) {
97
+ return [
98
+ `SELECT ${renderDistinctPrefix(ast.distinct, ast.distinctOn, contract, pim)}${renderProjection(ast.projection, contract, pim)}`,
99
+ `FROM ${renderSource(ast.from, contract, pim)}`,
100
+ ast.joins?.length ? ast.joins.map((join) => renderJoin(join, contract, pim)).join(" ") : "",
101
+ ast.where ? `WHERE ${renderWhere(ast.where, contract, pim)}` : "",
102
+ ast.groupBy?.length ? `GROUP BY ${ast.groupBy.map((expr) => renderExpr(expr, contract, pim)).join(", ")}` : "",
103
+ ast.having ? `HAVING ${renderWhere(ast.having, contract, pim)}` : "",
104
+ ast.orderBy?.length ? `ORDER BY ${ast.orderBy.map((order) => {
105
+ return `${renderExpr(order.expr, contract, pim)} ${order.dir.toUpperCase()}`;
106
+ }).join(", ")}` : "",
107
+ typeof ast.limit === "number" ? `LIMIT ${ast.limit}` : "",
108
+ typeof ast.offset === "number" ? `OFFSET ${ast.offset}` : ""
109
+ ].filter((part) => part.length > 0).join(" ").trim();
110
+ }
111
+ function renderProjection(projection, contract, pim) {
112
+ return projection.map((item) => {
113
+ const alias = quoteIdentifier(item.alias);
114
+ if (item.expr.kind === "literal") return `${renderLiteral(item.expr)} AS ${alias}`;
115
+ return `${renderExpr(item.expr, contract, pim)} AS ${alias}`;
116
+ }).join(", ");
117
+ }
118
+ function renderDistinctPrefix(distinct, distinctOn, contract, pim) {
119
+ if (distinctOn && distinctOn.length > 0) return `DISTINCT ON (${distinctOn.map((expr) => renderExpr(expr, contract, pim)).join(", ")}) `;
120
+ if (distinct) return "DISTINCT ";
121
+ return "";
122
+ }
123
+ function renderSource(source, contract, pim) {
124
+ const node = source;
125
+ switch (node.kind) {
126
+ case "table-source": {
127
+ const table = quoteIdentifier(node.name);
128
+ if (!node.alias) return table;
129
+ return `${table} AS ${quoteIdentifier(node.alias)}`;
130
+ }
131
+ case "derived-table-source": return `(${renderSelect(node.query, contract, pim)}) AS ${quoteIdentifier(node.alias)}`;
132
+ default: throw new Error(`Unsupported source node kind: ${node.kind}`);
133
+ }
134
+ }
135
+ function assertScalarSubquery(query) {
136
+ if (query.projection.length !== 1) throw new Error("Subquery expressions must project exactly one column");
137
+ }
138
+ function renderSubqueryExpr(expr, contract, pim) {
139
+ assertScalarSubquery(expr.query);
140
+ return `(${renderSelect(expr.query, contract, pim)})`;
141
+ }
142
+ function renderWhere(expr, contract, pim) {
143
+ return renderExpr(expr, contract, pim);
144
+ }
145
+ function renderNullCheck(expr, contract, pim) {
146
+ const rendered = renderExpr(expr.expr, contract, pim);
147
+ const renderedExpr = expr.expr.kind === "operation" || expr.expr.kind === "subquery" ? `(${rendered})` : rendered;
148
+ return expr.isNull ? `${renderedExpr} IS NULL` : `${renderedExpr} IS NOT NULL`;
149
+ }
150
+ function renderBinary(expr, contract, pim) {
151
+ if (expr.right.kind === "list" && expr.right.values.length === 0) {
152
+ if (expr.op === "in") return "FALSE";
153
+ if (expr.op === "notIn") return "TRUE";
154
+ }
155
+ const leftExpr = expr.left;
156
+ const left = renderExpr(leftExpr, contract, pim);
157
+ const leftRendered = leftExpr.kind === "operation" || leftExpr.kind === "subquery" ? `(${left})` : left;
158
+ const rightNode = expr.right;
159
+ let right;
160
+ switch (rightNode.kind) {
161
+ case "list":
162
+ right = renderListLiteral(rightNode, pim);
163
+ break;
164
+ case "literal":
165
+ right = renderLiteral(rightNode);
166
+ break;
167
+ case "column-ref":
168
+ right = renderColumn(rightNode);
169
+ break;
170
+ case "param-ref":
171
+ right = renderParamRef(rightNode, pim);
172
+ break;
173
+ default:
174
+ right = renderExpr(rightNode, contract, pim);
175
+ break;
176
+ }
177
+ return `${leftRendered} ${{
178
+ eq: "=",
179
+ neq: "!=",
180
+ gt: ">",
181
+ lt: "<",
182
+ gte: ">=",
183
+ lte: "<=",
184
+ like: "LIKE",
185
+ in: "IN",
186
+ notIn: "NOT IN"
187
+ }[expr.op]} ${right}`;
188
+ }
189
+ function renderListLiteral(expr, pim) {
190
+ if (expr.values.length === 0) return "(NULL)";
191
+ return `(${expr.values.map((v) => {
192
+ if (v.kind === "param-ref") return renderParamRef(v, pim);
193
+ if (v.kind === "literal") return renderLiteral(v);
194
+ return renderExpr(v, void 0, pim);
195
+ }).join(", ")})`;
196
+ }
197
+ function renderColumn(ref) {
198
+ if (ref.table === "excluded") return `excluded.${quoteIdentifier(ref.column)}`;
199
+ return `${quoteIdentifier(ref.table)}.${quoteIdentifier(ref.column)}`;
200
+ }
201
+ function renderAggregateExpr(expr, contract, pim) {
202
+ const fn = expr.fn.toUpperCase();
203
+ if (!expr.expr) return `${fn}(*)`;
204
+ return `${fn}(${renderExpr(expr.expr, contract, pim)})`;
205
+ }
206
+ function renderJsonObjectExpr(expr, contract, pim) {
207
+ return `json_build_object(${expr.entries.flatMap((entry) => {
208
+ const key = `'${escapeLiteral(entry.key)}'`;
209
+ if (entry.value.kind === "literal") return [key, renderLiteral(entry.value)];
210
+ return [key, renderExpr(entry.value, contract, pim)];
211
+ }).join(", ")})`;
212
+ }
213
+ function renderOrderByItems(items, contract, pim) {
214
+ return items.map((item) => `${renderExpr(item.expr, contract, pim)} ${item.dir.toUpperCase()}`).join(", ");
215
+ }
216
+ function renderJsonArrayAggExpr(expr, contract, pim) {
217
+ const aggregateOrderBy = expr.orderBy && expr.orderBy.length > 0 ? ` ORDER BY ${renderOrderByItems(expr.orderBy, contract, pim)}` : "";
218
+ const aggregated = `json_agg(${renderExpr(expr.expr, contract, pim)}${aggregateOrderBy})`;
219
+ if (expr.onEmpty === "emptyArray") return `coalesce(${aggregated}, json_build_array())`;
220
+ return aggregated;
221
+ }
222
+ function renderExpr(expr, contract, pim) {
223
+ const node = expr;
224
+ switch (node.kind) {
225
+ case "column-ref": return renderColumn(node);
226
+ case "identifier-ref": return quoteIdentifier(node.name);
227
+ case "operation": return renderOperation(node, contract, pim);
228
+ case "subquery": return renderSubqueryExpr(node, contract, pim);
229
+ case "aggregate": return renderAggregateExpr(node, contract, pim);
230
+ case "json-object": return renderJsonObjectExpr(node, contract, pim);
231
+ case "json-array-agg": return renderJsonArrayAggExpr(node, contract, pim);
232
+ case "binary": return renderBinary(node, contract, pim);
233
+ case "and":
234
+ if (node.exprs.length === 0) return "TRUE";
235
+ return `(${node.exprs.map((part) => renderExpr(part, contract, pim)).join(" AND ")})`;
236
+ case "or":
237
+ if (node.exprs.length === 0) return "FALSE";
238
+ return `(${node.exprs.map((part) => renderExpr(part, contract, pim)).join(" OR ")})`;
239
+ case "exists": return `${node.notExists ? "NOT " : ""}EXISTS (${renderSelect(node.subquery, contract, pim)})`;
240
+ case "null-check": return renderNullCheck(node, contract, pim);
241
+ case "not": return `NOT (${renderExpr(node.expr, contract, pim)})`;
242
+ case "param-ref": return renderParamRef(node, pim);
243
+ case "literal": return renderLiteral(node);
244
+ case "list": return renderListLiteral(node, pim);
245
+ default: throw new Error(`Unsupported expression node kind: ${node.kind}`);
246
+ }
247
+ }
248
+ function renderParamRef(ref, pim) {
249
+ const index = pim?.get(ref);
250
+ if (index === void 0) throw new Error("ParamRef not found in index map");
251
+ return renderTypedParam(index, ref.codecId);
252
+ }
253
+ function renderLiteral(expr) {
254
+ if (typeof expr.value === "string") return `'${escapeLiteral(expr.value)}'`;
255
+ if (typeof expr.value === "number" || typeof expr.value === "boolean") return String(expr.value);
256
+ if (typeof expr.value === "bigint") return String(expr.value);
257
+ if (expr.value === null) return "NULL";
258
+ if (expr.value === void 0) return "NULL";
259
+ if (expr.value instanceof Date) return `'${escapeLiteral(expr.value.toISOString())}'`;
260
+ if (Array.isArray(expr.value)) return `ARRAY[${expr.value.map((v) => renderLiteral(new LiteralExpr(v))).join(", ")}]`;
261
+ const json = JSON.stringify(expr.value);
262
+ if (json === void 0) return "NULL";
263
+ return `'${escapeLiteral(json)}'`;
264
+ }
265
+ function renderOperation(expr, contract, pim) {
266
+ const self = renderExpr(expr.self, contract, pim);
267
+ const args = expr.args.map((arg) => {
268
+ return renderExpr(arg, contract, pim);
269
+ });
270
+ let result = expr.lowering.template;
271
+ result = result.replace(/\{\{self\}\}/g, self);
272
+ for (let i = 0; i < args.length; i++) result = result.replace(new RegExp(`\\{\\{arg${i}\\}\\}`, "g"), args[i] ?? "");
273
+ return result;
274
+ }
275
+ function renderJoin(join, contract, pim) {
276
+ return `${join.joinType.toUpperCase()} JOIN ${join.lateral ? "LATERAL " : ""}${renderSource(join.source, contract, pim)} ON ${renderJoinOn(join.on, contract, pim)}`;
277
+ }
278
+ function renderJoinOn(on, contract, pim) {
279
+ if (on.kind === "eq-col-join-on") return `${renderColumn(on.left)} = ${renderColumn(on.right)}`;
280
+ return renderWhere(on, contract, pim);
281
+ }
282
+ function getInsertColumnOrder(rows, contract, tableName) {
283
+ const orderedColumns = [];
284
+ const seenColumns = /* @__PURE__ */ new Set();
285
+ for (const row of rows) for (const column of Object.keys(row)) {
286
+ if (seenColumns.has(column)) continue;
287
+ seenColumns.add(column);
288
+ orderedColumns.push(column);
289
+ }
290
+ if (orderedColumns.length > 0) return orderedColumns;
291
+ return Object.keys(contract.storage.tables[tableName]?.columns ?? {});
292
+ }
293
+ function renderInsertValue(value, pim) {
294
+ if (!value || value.kind === "default-value") return "DEFAULT";
295
+ switch (value.kind) {
296
+ case "param-ref": return renderParamRef(value, pim);
297
+ case "column-ref": return renderColumn(value);
298
+ default: throw new Error(`Unsupported value node in INSERT: ${value.kind}`);
299
+ }
300
+ }
301
+ function renderInsert(ast, contract, pim) {
302
+ const table = quoteIdentifier(ast.table.name);
303
+ const rows = ast.rows;
304
+ if (rows.length === 0) throw new Error("INSERT requires at least one row");
305
+ const hasExplicitValues = rows.some((row) => Object.keys(row).length > 0);
306
+ return `${(() => {
307
+ if (!hasExplicitValues) {
308
+ if (rows.length === 1) return `INSERT INTO ${table} DEFAULT VALUES`;
309
+ const defaultColumns = getInsertColumnOrder(rows, contract, ast.table.name);
310
+ if (defaultColumns.length === 0) return `INSERT INTO ${table} VALUES ${rows.map(() => "()").join(", ")}`;
311
+ const quotedColumns = defaultColumns.map((column) => quoteIdentifier(column));
312
+ const defaultRow = `(${defaultColumns.map(() => "DEFAULT").join(", ")})`;
313
+ return `INSERT INTO ${table} (${quotedColumns.join(", ")}) VALUES ${rows.map(() => defaultRow).join(", ")}`;
314
+ }
315
+ const columnOrder = getInsertColumnOrder(rows, contract, ast.table.name);
316
+ const columns = columnOrder.map((column) => quoteIdentifier(column));
317
+ const values = rows.map((row) => {
318
+ return `(${columnOrder.map((column) => renderInsertValue(row[column], pim)).join(", ")})`;
319
+ }).join(", ");
320
+ return `INSERT INTO ${table} (${columns.join(", ")}) VALUES ${values}`;
321
+ })()}${ast.onConflict ? (() => {
322
+ const conflictColumns = ast.onConflict.columns.map((col) => quoteIdentifier(col.column));
323
+ if (conflictColumns.length === 0) throw new Error("INSERT onConflict requires at least one conflict column");
324
+ const action = ast.onConflict.action;
325
+ switch (action.kind) {
326
+ case "do-nothing": return ` ON CONFLICT (${conflictColumns.join(", ")}) DO NOTHING`;
327
+ case "do-update-set": {
328
+ const updates = Object.entries(action.set).map(([colName, value]) => {
329
+ const target = quoteIdentifier(colName);
330
+ if (value.kind === "param-ref") return `${target} = ${renderParamRef(value, pim)}`;
331
+ return `${target} = ${renderColumn(value)}`;
332
+ });
333
+ return ` ON CONFLICT (${conflictColumns.join(", ")}) DO UPDATE SET ${updates.join(", ")}`;
334
+ }
335
+ default: throw new Error(`Unsupported onConflict action: ${action.kind}`);
336
+ }
337
+ })() : ""}${ast.returning?.length ? ` RETURNING ${ast.returning.map((col) => `${quoteIdentifier(col.table)}.${quoteIdentifier(col.column)}`).join(", ")}` : ""}`;
338
+ }
339
+ function renderUpdate(ast, contract, pim) {
340
+ const table = quoteIdentifier(ast.table.name);
341
+ const setClauses = Object.entries(ast.set).map(([col, val]) => {
342
+ const column = quoteIdentifier(col);
343
+ let value;
344
+ switch (val.kind) {
345
+ case "param-ref":
346
+ value = renderParamRef(val, pim);
347
+ break;
348
+ case "column-ref":
349
+ value = renderColumn(val);
350
+ break;
351
+ default: throw new Error(`Unsupported value node in UPDATE: ${val.kind}`);
352
+ }
353
+ return `${column} = ${value}`;
354
+ });
355
+ const whereClause = ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : "";
356
+ const returningClause = ast.returning?.length ? ` RETURNING ${ast.returning.map((col) => `${quoteIdentifier(col.table)}.${quoteIdentifier(col.column)}`).join(", ")}` : "";
357
+ return `UPDATE ${table} SET ${setClauses.join(", ")}${whereClause}${returningClause}`;
358
+ }
359
+ function renderDelete(ast, contract, pim) {
360
+ return `DELETE FROM ${quoteIdentifier(ast.table.name)}${ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : ""}${ast.returning?.length ? ` RETURNING ${ast.returning.map((col) => `${quoteIdentifier(col.table)}.${quoteIdentifier(col.column)}`).join(", ")}` : ""}`;
361
+ }
362
+ function createPostgresAdapter(options) {
363
+ return Object.freeze(new PostgresAdapterImpl(options));
364
+ }
365
+
366
+ //#endregion
367
+ //#region src/core/migrations/operations/data-transform.ts
368
+ /**
369
+ * User-facing `dataTransform` factory for the Postgres migration authoring
370
+ * surface. Invoked directly inside a `migration.ts` file:
371
+ *
372
+ * ```ts
373
+ * import endContract from './end-contract.json' with { type: 'json' };
374
+ * import { dataTransform } from '@prisma-next/target-postgres/migration';
375
+ *
376
+ * dataTransform(endContract, 'backfill emails', {
377
+ * check: () => db.users.count().where(({ email }) => email.isNull()),
378
+ * run: () => db.users.update({ email: '' }).where(({ email }) => email.isNull()),
379
+ * });
380
+ * ```
381
+ *
382
+ * The factory accepts lazy closures (`() => SqlQueryPlan | Buildable`),
383
+ * invokes each one, asserts that its `meta.storageHash` matches the
384
+ * `contract` it was handed (→ `PN-MIG-2005` on mismatch), and lowers the
385
+ * plan via the Postgres adapter to a serialized `{sql, params}` payload
386
+ * for `ops.json`.
387
+ */
388
+ /** Single shared adapter for apply/CLI; sufficient for single-threaded migration execution. */
389
+ let adapterSingleton = null;
390
+ function getAdapter() {
391
+ if (adapterSingleton === null) adapterSingleton = createPostgresAdapter();
392
+ return adapterSingleton;
393
+ }
394
+ function dataTransform(contract, name, options) {
395
+ const adapter = getAdapter();
396
+ const runClosures = Array.isArray(options.run) ? options.run : [options.run];
397
+ return {
398
+ id: `data_migration.${name}`,
399
+ label: `Data transform: ${name}`,
400
+ operationClass: "data",
401
+ name,
402
+ source: "migration.ts",
403
+ check: options.check ? invokeAndLower(options.check, contract, adapter, name) : null,
404
+ run: runClosures.map((closure) => invokeAndLower(closure, contract, adapter, name))
405
+ };
406
+ }
407
+ function invokeAndLower(closure, contract, adapter, name) {
408
+ const result = closure();
409
+ const plan = isBuildable(result) ? result.build() : result;
410
+ assertContractMatches(plan, contract, name);
411
+ const lowered = lowerSqlPlan(adapter, contract, plan);
412
+ return {
413
+ sql: lowered.sql,
414
+ params: lowered.params
415
+ };
416
+ }
417
+ function isBuildable(value) {
418
+ return typeof value === "object" && value !== null && "build" in value && typeof value.build === "function";
419
+ }
420
+ function assertContractMatches(plan, contract, name) {
421
+ if (plan.meta.storageHash !== contract.storage.storageHash) throw errorDataTransformContractMismatch({
422
+ dataTransformName: name,
423
+ expected: contract.storage.storageHash,
424
+ actual: plan.meta.storageHash
425
+ });
426
+ }
427
+
428
+ //#endregion
429
+ //#region src/core/migrations/operations/raw.ts
430
+ /**
431
+ * Identity factory for an already-materialized `SqlMigrationPlanOperation`.
432
+ *
433
+ * The planner uses this via `liftOpToCall` to carry ops produced by SQL
434
+ * family methods, codec control hooks, and component database dependencies
435
+ * alongside migration IR without reverse-engineering them. Users writing
436
+ * raw migrations can pass a full op shape directly — typically built by
437
+ * composing SQL family helpers — to author a migration that bypasses the
438
+ * structured call classes.
439
+ */
440
+ function rawSql(op) {
441
+ return op;
442
+ }
443
+
444
+ //#endregion
445
+ export { PostgresMigration as Migration, addColumn, addEnumValues, addForeignKey, addPrimaryKey, addUnique, alterColumnType, createEnumType, createExtension, createIndex, createSchema, createTable, dataTransform, dropColumn, dropConstraint, dropDefault, dropEnumType, dropIndex, dropNotNull, dropTable, placeholder, rawSql, renameType, setDefault, setNotNull };
446
+ //# sourceMappingURL=migration.mjs.map