@prisma/orm-family-sql 8.0.0-rc.16-dev.6 → 8.0.0-rc.16-dev.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
1
  import { u as namingOf } from "./naming-DkG_OegU-DpENNdZX.mjs";
2
2
  import { t as sqlContractCanonicalizationHooks } from "./canonicalization-hooks-dmXkOR4a.mjs";
3
3
  import { a as renderSqlTypeName, l as sqlDataTypeOfCodec, t as dataTypeParams, u as unquotedSqlBaseName } from "./data-type-CAPmGXg9.mjs";
4
- import { c as StorageTable, n as ForeignKey } from "./storage-table-CyL4CNMi-ByGZXmzd.mjs";
4
+ import { c as StorageTable } from "./storage-table-CyL4CNMi-ByGZXmzd.mjs";
5
5
  import { a as sqlExpressionAuthoringEntry, o as sqlExpressionDataType, t as SQL_EXPRESSION_DATA_TYPE_ID } from "./sql-expression-D7GsLgDM.mjs";
6
- import { c as isMaterializedSqlNamespace, o as SqlStorage, u as isStorageTypeInstance } from "./types-DDHgx581.mjs";
6
+ import { u as isStorageTypeInstance } from "./types-DDHgx581.mjs";
7
7
  import { m as valueObjectStorageTypeMissingMessage } from "./validators-Xx-TKcx3.mjs";
8
8
  import { c as SqlSchemaIR, n as RelationalSchemaNodeKind, u as SqlTableIR } from "./types-Cz_bcUWN-CC3lFQOi.mjs";
9
9
  import { a as describeUnsupportedSqlAttribute, b as sqlAttributeSpecs } from "./psl-field-resolution-DUCrDnuq-DSxPrd-4.mjs";
@@ -21,8 +21,8 @@ import { assembleDataTypes, canonicalFormOf } from "@prisma/orm-framework/compon
21
21
  import { blindCast } from "@prisma/orm-framework/utils/casts";
22
22
  import { ifDefined } from "@prisma/orm-framework/utils/defined";
23
23
  import { InternalError } from "@prisma/orm-framework/utils/internal-error";
24
- import { effectiveControlPolicy } from "@prisma/orm-framework/contract/types";
25
- import { APP_SPACE_ID, SchemaTreeNode, VERIFY_CODE_HASH_MISMATCH, VERIFY_CODE_MARKER_MISSING, VERIFY_CODE_TARGET_MISMATCH, assembleAuthoringContributions, extractCodecLookup, issueOutcome, sameMarkerHashes } from "@prisma/orm-framework/components/control";
24
+ import { asNamespaceId, effectiveControlPolicy } from "@prisma/orm-framework/contract/types";
25
+ import { APP_SPACE_ID, SchemaTreeNode, VERIFY_CODE_HASH_MISMATCH, VERIFY_CODE_MARKER_MISSING, VERIFY_CODE_TARGET_MISMATCH, assembleAuthoringContributions, describeMigrationStatement, extractCodecLookup, issueOutcome, modelDisplayName, sameMarkerHashes } from "@prisma/orm-framework/components/control";
26
26
  import { notOk, ok } from "@prisma/orm-framework/utils/result";
27
27
  import { assertDescriptorSelfConsistency } from "@prisma/orm-toolchain/migration-tools/spaces";
28
28
  //#region ../../../2-sql/9-family/dist/control.mjs
@@ -76,6 +76,38 @@ function assertContractMatchesStack(contract, stack) {
76
76
  const problems = [...dataTypeProblems(contract.storage, stack.codecLookup), ...valueObjectProblems(contract, stack.authoringContributions)];
77
77
  if (problems.length > 0) throw new ContractValidationError(problems.join("; "), "storage");
78
78
  }
79
+ function isStorageDetails(details) {
80
+ if (typeof details !== "object" || details === null) return false;
81
+ const [objectType, name, schema, table] = [
82
+ "objectType",
83
+ "name",
84
+ "schema",
85
+ "table"
86
+ ].map((key) => Reflect.get(details, key));
87
+ return typeof objectType === "string" && typeof name === "string" && (schema === void 0 || typeof schema === "string") && (table === void 0 || typeof table === "string");
88
+ }
89
+ function storageDetailsOf(operation) {
90
+ const target = Reflect.get(operation, "target");
91
+ if (typeof target !== "object" || target === null) return void 0;
92
+ const details = Reflect.get(target, "details");
93
+ return isStorageDetails(details) ? details : void 0;
94
+ }
95
+ /**
96
+ * The name the database knows an operation's object by, read from the operation's target
97
+ * details: `schema.table.column` for a column, `schema.name` for anything else, without the
98
+ * schema in the unbound namespace. An operation without details is named by its id.
99
+ */
100
+ function storageNameOfOperation(operation) {
101
+ const details = storageDetailsOf(operation);
102
+ if (details === void 0) return operation.id;
103
+ const schema = details.schema === void 0 || details.schema === UNBOUND_NAMESPACE_ID ? [] : [details.schema];
104
+ const table = details.objectType === "column" && details.table !== void 0 ? [details.table] : [];
105
+ return [
106
+ ...schema,
107
+ ...table,
108
+ details.name
109
+ ].join(".");
110
+ }
79
111
  function isDdlStatement(sqlStatement) {
80
112
  const trimmed = sqlStatement.trim().toLowerCase();
81
113
  return trimmed.startsWith("create ") || trimmed.startsWith("alter ") || trimmed.startsWith("drop ");
@@ -535,6 +567,9 @@ function createSqlFamilyInstance(stack) {
535
567
  toOperationPreview(operations) {
536
568
  return sqlOperationsToPreview(operations);
537
569
  },
570
+ storageNameOf(operation) {
571
+ return storageNameOfOperation(operation);
572
+ },
538
573
  toSchemaView(schema) {
539
574
  const root = blindCast(schema);
540
575
  const namespaceEntries = root.namespaces !== void 0 ? Object.entries(root.namespaces).map(([namespaceKey, namespace]) => [namespaceKey, namespace.tables]) : [[void 0, root.tables ?? {}]];
@@ -652,118 +687,6 @@ var SqlFamilyDescriptor = class {
652
687
  return createSqlFamilyInstance(stack);
653
688
  }
654
689
  };
655
- const TABLE_RENAME_UNMATCHED_CODE = "MIGRATION.TABLE_RENAME_UNMATCHED";
656
- function tableLabel(namespaceId, tableName) {
657
- return namespaceId === void 0 || namespaceId === UNBOUND_NAMESPACE_ID ? tableName : `${namespaceId}.${tableName}`;
658
- }
659
- function namespacesDeclaring(contract, tableName) {
660
- return Object.values(contract.storage.namespaces).filter((namespace) => Object.hasOwn(namespace.entries.table ?? {}, tableName)).map((namespace) => namespace.id);
661
- }
662
- function declares(contract, namespaceId, tableName) {
663
- return Object.hasOwn(contract.storage.namespaces[namespaceId]?.entries.table ?? {}, tableName);
664
- }
665
- function unmatched(rename, reason) {
666
- return sqlFamilyError(TABLE_RENAME_UNMATCHED_CODE, `renameTable "${tableLabel(rename.namespaceId, rename.from)}" to "${rename.to}" does not match the migration's contracts: ${reason}.`, {
667
- why: "renameTable must name a table of the migration's start contract and a new name that the end contract has and the start contract does not. Make the rename its own schema change, so the migration's start contract is the schema before the rename and its end contract the schema after it, and check the spelling and the namespace.",
668
- meta: {
669
- from: rename.from,
670
- to: rename.to
671
- }
672
- });
673
- }
674
- function resolveTableRename(rename, startContract, endContract) {
675
- const namespaceIds = rename.namespaceId === void 0 ? namespacesDeclaring(startContract, rename.from) : declares(startContract, rename.namespaceId, rename.from) ? [rename.namespaceId] : [];
676
- const [namespaceId, ...others] = namespaceIds;
677
- if (namespaceId === void 0) return notOk(unmatched(rename, `table "${tableLabel(rename.namespaceId, rename.from)}" does not exist in the start contract`));
678
- if (others.length > 0) return notOk(unmatched(rename, `table "${rename.from}" is declared in more than one namespace (${namespaceIds.join(", ")}); name its namespace`));
679
- if (declares(startContract, namespaceId, rename.to)) return notOk(unmatched(rename, `table "${tableLabel(namespaceId, rename.to)}" already exists in the start contract`));
680
- if (!declares(endContract, namespaceId, rename.to)) return notOk(unmatched(rename, `table "${tableLabel(namespaceId, rename.to)}" does not exist in the end contract`));
681
- return ok({
682
- namespaceId,
683
- from: rename.from,
684
- to: rename.to
685
- });
686
- }
687
- function renamedReference(reference, rename) {
688
- if (!(reference.spaceId === void 0) || reference.namespaceId !== rename.namespaceId || reference.tableName !== rename.from) return reference;
689
- return {
690
- ...reference,
691
- tableName: rename.to
692
- };
693
- }
694
- function renameForeignKeys(table, rename) {
695
- if (!table.foreignKeys.some((fk) => renamedReference(fk.source, rename) !== fk.source || renamedReference(fk.target, rename) !== fk.target)) return table;
696
- return new StorageTable({
697
- ...table,
698
- foreignKeys: table.foreignKeys.map((fk) => new ForeignKey({
699
- ...fk,
700
- source: renamedReference(fk.source, rename),
701
- target: renamedReference(fk.target, rename)
702
- }))
703
- });
704
- }
705
- /**
706
- * The same namespace instance with only `entries` replaced: every own
707
- * property, including the non-enumerable `kind`, is carried over onto the
708
- * same prototype, so the target's namespace class (its `qualifyTable`,
709
- * `ddlSchemaName`, entity getters) keeps working on the copy. This is the
710
- * one place a frozen contract node is rebuilt without its constructor: the
711
- * constructors re-hydrate `entries` from raw input, which the already
712
- * hydrated entities here do not need.
713
- */
714
- function withEntries(namespace, entries) {
715
- const copy = Object.create(Object.getPrototypeOf(namespace), {
716
- ...Object.getOwnPropertyDescriptors(namespace),
717
- entries: {
718
- value: Object.freeze(entries),
719
- enumerable: true,
720
- writable: false,
721
- configurable: false
722
- }
723
- });
724
- return Object.freeze(copy);
725
- }
726
- function renameTableInNamespace(namespace, rename, renameTableReferences) {
727
- const ownsTable = rename.namespaceId === namespace.id;
728
- const tables = Object.entries(namespace.entries.table ?? {}).map(([name, table]) => [ownsTable && name === rename.from ? rename.to : name, renameForeignKeys(table, rename)]);
729
- if (tables.every(([name, table]) => namespace.entries.table?.[name] === table)) return namespace;
730
- if (!isMaterializedSqlNamespace(namespace)) throw new InternalError(`applyTableRename: namespace "${namespace.id}" is not a materialized SQL namespace`);
731
- const renamedTables = {
732
- ...namespace.entries,
733
- table: Object.fromEntries(tables)
734
- };
735
- return withEntries(namespace, renameTableReferences === void 0 || !ownsTable ? renamedTables : renameTableReferences(renamedTables, rename));
736
- }
737
- function renameTableInContract(contract, rename, renameTableReferences) {
738
- const namespaces = Object.fromEntries(Object.entries(contract.storage.namespaces).map(([id, namespace]) => [id, renameTableInNamespace(namespace, rename, renameTableReferences)]));
739
- const materialized = {};
740
- for (const [id, namespace] of Object.entries(namespaces)) {
741
- if (!isMaterializedSqlNamespace(namespace)) throw new InternalError(`applyTableRename: namespace "${id}" is not a materialized SQL namespace`);
742
- materialized[id] = namespace;
743
- }
744
- return {
745
- ...contract,
746
- storage: new SqlStorage({
747
- storageHash: contract.storage.storageHash,
748
- ...contract.storage.types === void 0 ? {} : { types: contract.storage.types },
749
- namespaces: materialized
750
- })
751
- };
752
- }
753
- /**
754
- * Resolves the table a migration renames against its start and end contracts and returns the start contract with that table under its new name, so a diff against the end contract sees the table under one name. The table must exist in the start contract (in exactly one namespace when the namespace is not given), and the new name must exist in the end contract and not in the start contract; otherwise the rename is refused with `MIGRATION.TABLE_RENAME_UNMATCHED`.
755
- *
756
- * Foreign keys that name the renamed table on either side are retargeted. Index, unique, check and primary-key names are carried unchanged. Target entity kinds that name the table are renamed by the target's `renameTableReferences`.
757
- */
758
- function applyTableRename(input) {
759
- if (input.startContract === null) return notOk(unmatched(input.rename, "the migration has no start contract"));
760
- const resolved = resolveTableRename(input.rename, input.startContract, input.endContract);
761
- if (!resolved.ok) return resolved;
762
- return ok({
763
- contract: renameTableInContract(input.startContract, resolved.value, input.renameTableReferences),
764
- rename: resolved.value
765
- });
766
- }
767
690
  function convertColumn(name, column, storageTypes, types, renderDefault, resolveDefault) {
768
691
  const resolved = resolveColumnTypeMetadata(column, storageTypes);
769
692
  const dataType = sqlDataTypeOfCodec(resolved.codecId, types);
@@ -1205,8 +1128,15 @@ function subjectKey(subject) {
1205
1128
  return `${subject.namespaceId}\u0000${subject.entityKind ?? ""}\u0000${subject.entityName ?? ""}\u0000${subject.rlsPolicy ?? ""}`;
1206
1129
  }
1207
1130
  function planFieldEventOperations(options) {
1131
+ return planFieldEventCalls(options).map(({ call }) => call);
1132
+ }
1133
+ /** The calls the codec hooks return, each with the field event's column. */
1134
+ function planFieldEventCalls(options) {
1208
1135
  const priorContract = options.priorContract;
1209
1136
  const newContract = options.newContract;
1137
+ const renamedTo = new Map(options.tableRenames.map((rename) => [renameKey(rename.namespaceId, rename.from), rename.to]));
1138
+ const newNameOf = (namespaceId, tableName) => renamedTo.get(renameKey(namespaceId, tableName));
1139
+ const columnRenamedTo = new Map(options.columnRenames.map((rename) => [renameKey(rename.namespaceId, rename.table, rename.from), rename.to]));
1210
1140
  const added = [];
1211
1141
  const dropped = [];
1212
1142
  const altered = [];
@@ -1214,7 +1144,7 @@ function planFieldEventOperations(options) {
1214
1144
  for (const namespaceId of namespaceIds) {
1215
1145
  const priorNs = priorContract?.storage.namespaces[namespaceId];
1216
1146
  const newNs = newContract.storage.namespaces[namespaceId];
1217
- const priorTables = priorNs?.entries.table;
1147
+ const priorTables = underNewNames(priorNs?.entries.table, (tableName) => newNameOf(namespaceId, tableName));
1218
1148
  const newTables = newNs?.entries.table;
1219
1149
  const tableNames = unionSorted(priorTables ? Object.keys(priorTables) : [], newTables ? Object.keys(newTables) : []);
1220
1150
  for (const tableName of tableNames) {
@@ -1222,9 +1152,10 @@ function planFieldEventOperations(options) {
1222
1152
  const newTableRaw = newTables?.[tableName];
1223
1153
  const priorTable = StorageTable.is(priorTableRaw) ? priorTableRaw : void 0;
1224
1154
  const newTable = StorageTable.is(newTableRaw) ? newTableRaw : void 0;
1225
- const fieldNames = unionSorted(priorTable ? Object.keys(priorTable.columns) : [], newTable ? Object.keys(newTable.columns) : []);
1155
+ const priorColumns = underNewNames(priorTable?.columns, (columnName) => columnRenamedTo.get(renameKey(namespaceId, tableName, columnName)));
1156
+ const fieldNames = unionSorted(priorColumns ? Object.keys(priorColumns) : [], newTable ? Object.keys(newTable.columns) : []);
1226
1157
  for (const fieldName of fieldNames) {
1227
- const priorField = priorTable?.columns[fieldName];
1158
+ const priorField = priorColumns?.[fieldName];
1228
1159
  const newField = newTable?.columns[fieldName];
1229
1160
  const entry = {
1230
1161
  namespaceId,
@@ -1249,6 +1180,13 @@ function planFieldEventOperations(options) {
1249
1180
  appendCalls("altered", altered, options.codecHooks, calls, (e) => e.newField?.codecId);
1250
1181
  return calls;
1251
1182
  }
1183
+ function renameKey(...parts) {
1184
+ return JSON.stringify(parts);
1185
+ }
1186
+ function underNewNames(tables, newNameOf) {
1187
+ if (tables === void 0) return void 0;
1188
+ return Object.fromEntries(Object.entries(tables).map(([tableName, table]) => [newNameOf(tableName) ?? tableName, table]));
1189
+ }
1252
1190
  function appendCalls(event, entries, codecHooks, calls, pickCodecId) {
1253
1191
  for (const entry of entries) {
1254
1192
  const codecId = pickCodecId(entry);
@@ -1257,7 +1195,12 @@ function appendCalls(event, entries, codecHooks, calls, pickCodecId) {
1257
1195
  if (!hook?.onFieldEvent) continue;
1258
1196
  const ctx = buildContext(event, entry);
1259
1197
  const emitted = hook.onFieldEvent(event, ctx);
1260
- for (const call of emitted) calls.push(call);
1198
+ for (const call of emitted) calls.push({
1199
+ call,
1200
+ namespaceId: entry.namespaceId,
1201
+ tableName: entry.tableName,
1202
+ columnName: entry.fieldName
1203
+ });
1261
1204
  }
1262
1205
  }
1263
1206
  /**
@@ -1326,6 +1269,560 @@ function unionSorted(a, b) {
1326
1269
  for (const name of b) set.add(name);
1327
1270
  return [...set].sort((x, y) => x < y ? -1 : x > y ? 1 : 0);
1328
1271
  }
1272
+ const COLUMN_RENAME_UNMATCHED_CODE = "MIGRATION.COLUMN_RENAME_UNMATCHED";
1273
+ function tableLabel$1(namespaceId, table) {
1274
+ return namespaceId === void 0 || namespaceId === UNBOUND_NAMESPACE_ID ? table : `${namespaceId}.${table}`;
1275
+ }
1276
+ function columnLabel(namespaceId, table, column) {
1277
+ return `"${tableLabel$1(namespaceId, table)}"."${column}"`;
1278
+ }
1279
+ function declaresColumn(contract, namespaceId, table, column) {
1280
+ const columns = contract.storage.namespaces[namespaceId]?.entries.table?.[table]?.columns;
1281
+ return columns !== void 0 && Object.hasOwn(columns, column);
1282
+ }
1283
+ /**
1284
+ * Refuses a `renameColumn` call that does not match the migration's contracts, with
1285
+ * `MIGRATION.COLUMN_RENAME_UNMATCHED`.
1286
+ */
1287
+ function unmatchedColumnRename(rename, reason) {
1288
+ return sqlFamilyError(COLUMN_RENAME_UNMATCHED_CODE, `renameColumn ${columnLabel(rename.namespaceId, rename.table, rename.from)} to "${rename.to}" does not match the migration's contracts: ${reason}.`, {
1289
+ why: "renameColumn must name a table and a column as the migration's earlier rename operations leave them, and a new column name that the end contract has on that table and that the table does not have yet. Order the rename calls in the sequence the renames happen, and check the names of the table, the column and the namespace.",
1290
+ meta: {
1291
+ table: rename.table,
1292
+ from: rename.from,
1293
+ to: rename.to
1294
+ }
1295
+ });
1296
+ }
1297
+ /**
1298
+ * Checks a column rename: the table must exist in `previous` (in exactly one namespace when the
1299
+ * namespace is not given) with the old column and without the new one, and the end contract must
1300
+ * have the new column on that table.
1301
+ */
1302
+ function checkColumnRename(previous, endContract, rename) {
1303
+ const namespaceIds = rename.namespaceId === void 0 ? previous.namespacesWithTable(rename.table) : previous.hasTable(rename.namespaceId, rename.table) ? [rename.namespaceId] : [];
1304
+ const [namespaceId, ...others] = namespaceIds;
1305
+ if (namespaceId === void 0) return notOk({ kind: "tableMissing" });
1306
+ if (others.length > 0) return notOk({
1307
+ kind: "tableInManyNamespaces",
1308
+ namespaceIds
1309
+ });
1310
+ if (!previous.hasColumn(namespaceId, rename.table, rename.from)) return notOk({
1311
+ kind: "columnMissing",
1312
+ namespaceId
1313
+ });
1314
+ const [taken] = previous.columnsNamed(namespaceId, rename.table, rename.to).filter((column) => column !== rename.from);
1315
+ if (taken !== void 0) return notOk({
1316
+ kind: "nameTaken",
1317
+ namespaceId,
1318
+ taken
1319
+ });
1320
+ if (!declaresColumn(endContract, namespaceId, rename.table, rename.to)) return notOk({
1321
+ kind: "notInEndContract",
1322
+ namespaceId
1323
+ });
1324
+ return ok({
1325
+ namespaceId,
1326
+ table: rename.table,
1327
+ from: rename.from,
1328
+ to: rename.to
1329
+ });
1330
+ }
1331
+ /** The reason `MIGRATION.COLUMN_RENAME_UNMATCHED` gives for a mismatch. */
1332
+ function columnRenameMismatchReason(rename, mismatch) {
1333
+ switch (mismatch.kind) {
1334
+ case "tableMissing": return `table "${tableLabel$1(rename.namespaceId, rename.table)}" does not exist at this point of the migration`;
1335
+ case "tableInManyNamespaces": return `table "${rename.table}" is declared in more than one namespace (${mismatch.namespaceIds.join(", ")}); name its namespace`;
1336
+ case "columnMissing": return `column ${columnLabel(mismatch.namespaceId, rename.table, rename.from)} does not exist at this point of the migration`;
1337
+ case "nameTaken": return `column ${columnLabel(mismatch.namespaceId, rename.table, rename.to)} already exists at this point of the migration${mismatch.taken === rename.to ? "" : ` as "${mismatch.taken}"`}`;
1338
+ case "notInEndContract": return `column ${columnLabel(mismatch.namespaceId, rename.table, rename.to)} does not exist in the end contract`;
1339
+ }
1340
+ }
1341
+ /**
1342
+ * Resolves a column a migration renames with {@link checkColumnRename}, refusing a mismatch with
1343
+ * `MIGRATION.COLUMN_RENAME_UNMATCHED`.
1344
+ */
1345
+ function resolveColumnRenameAgainst(previous, endContract, rename) {
1346
+ const checked = checkColumnRename(previous, endContract, rename);
1347
+ if (!checked.ok) return notOk(unmatchedColumnRename(rename, columnRenameMismatchReason(rename, checked.failure)));
1348
+ return ok(checked.value);
1349
+ }
1350
+ const TABLE_RENAME_UNMATCHED_CODE = "MIGRATION.TABLE_RENAME_UNMATCHED";
1351
+ function tableLabel(namespaceId, tableName) {
1352
+ return namespaceId === void 0 || namespaceId === UNBOUND_NAMESPACE_ID ? tableName : `${namespaceId}.${tableName}`;
1353
+ }
1354
+ function declares(contract, namespaceId, tableName) {
1355
+ return Object.hasOwn(contract.storage.namespaces[namespaceId]?.entries.table ?? {}, tableName);
1356
+ }
1357
+ /**
1358
+ * Refuses a `renameTable` call that does not match the migration's contracts, with
1359
+ * `MIGRATION.TABLE_RENAME_UNMATCHED`.
1360
+ */
1361
+ function unmatchedTableRename(rename, reason) {
1362
+ return sqlFamilyError(TABLE_RENAME_UNMATCHED_CODE, `renameTable "${tableLabel(rename.namespaceId, rename.from)}" to "${rename.to}" does not match the migration's contracts: ${reason}.`, {
1363
+ why: "renameTable must name a table as the migration's earlier rename operations leave it, and a new name that the end contract has and that no earlier rename operation has already produced. Order the renameTable calls in the sequence the renames happen, make the rename its own schema change, and check the spelling, the table and the namespace.",
1364
+ meta: {
1365
+ from: rename.from,
1366
+ to: rename.to
1367
+ }
1368
+ });
1369
+ }
1370
+ /**
1371
+ * Checks a table rename: the table must exist in `previous` (in exactly one namespace when the
1372
+ * namespace is not given), and the new name must exist in the end contract and not in `previous`.
1373
+ */
1374
+ function checkTableRename(previous, endContract, rename) {
1375
+ const namespaceIds = rename.namespaceId === void 0 ? previous.namespacesWithTable(rename.from) : previous.hasTable(rename.namespaceId, rename.from) ? [rename.namespaceId] : [];
1376
+ const [namespaceId, ...others] = namespaceIds;
1377
+ if (namespaceId === void 0) return notOk({ kind: "tableMissing" });
1378
+ if (others.length > 0) return notOk({
1379
+ kind: "tableInManyNamespaces",
1380
+ namespaceIds
1381
+ });
1382
+ const [taken] = previous.tablesNamed(namespaceId, rename.to).filter((table) => table !== rename.from);
1383
+ if (taken !== void 0) return notOk({
1384
+ kind: "nameTaken",
1385
+ namespaceId,
1386
+ taken
1387
+ });
1388
+ if (!declares(endContract, namespaceId, rename.to)) return notOk({
1389
+ kind: "notInEndContract",
1390
+ namespaceId
1391
+ });
1392
+ return ok({
1393
+ namespaceId,
1394
+ from: rename.from,
1395
+ to: rename.to
1396
+ });
1397
+ }
1398
+ /** The reason `MIGRATION.TABLE_RENAME_UNMATCHED` gives for a mismatch. */
1399
+ function tableRenameMismatchReason(rename, mismatch) {
1400
+ switch (mismatch.kind) {
1401
+ case "tableMissing": return `table "${tableLabel(rename.namespaceId, rename.from)}" does not exist at this point of the migration`;
1402
+ case "tableInManyNamespaces": return `table "${rename.from}" is declared in more than one namespace (${mismatch.namespaceIds.join(", ")}); name its namespace`;
1403
+ case "nameTaken": return `table "${tableLabel(mismatch.namespaceId, rename.to)}" already exists at this point of the migration${mismatch.taken === rename.to ? "" : ` as "${mismatch.taken}"`}`;
1404
+ case "notInEndContract": return `table "${tableLabel(mismatch.namespaceId, rename.to)}" does not exist in the end contract`;
1405
+ }
1406
+ }
1407
+ /**
1408
+ * Resolves a table a migration renames with {@link checkTableRename}, refusing a mismatch with
1409
+ * `MIGRATION.TABLE_RENAME_UNMATCHED`.
1410
+ */
1411
+ function resolveTableRenameAgainst(previous, endContract, rename) {
1412
+ const checked = checkTableRename(previous, endContract, rename);
1413
+ if (!checked.ok) return notOk(unmatchedTableRename(rename, tableRenameMismatchReason(rename, checked.failure)));
1414
+ return ok(checked.value);
1415
+ }
1416
+ /** Whether a model's storage names a table, as a model a SQL contract stores in a table does. */
1417
+ function isSqlModelStorage(storage) {
1418
+ return typeof storage["table"] === "string" && typeof storage["namespaceId"] === "string" && typeof storage["fields"] === "object" && storage["fields"] !== null;
1419
+ }
1420
+ /** The storage of a model the contract stores in a table, or `undefined` for any other model. */
1421
+ function sqlModelStorage(contract, coordinate) {
1422
+ const storage = contract.domain.namespaces[coordinate.namespaceId]?.models[coordinate.model]?.storage;
1423
+ return storage !== void 0 && isSqlModelStorage(storage) ? storage : void 0;
1424
+ }
1425
+ function modelTable(contract, coordinate) {
1426
+ const storage = sqlModelStorage(contract, coordinate);
1427
+ return storage === void 0 ? void 0 : {
1428
+ namespaceId: storage.namespaceId,
1429
+ table: storage.table
1430
+ };
1431
+ }
1432
+ /**
1433
+ * The storage effect of a model rename: the origin model's table compared with the destination
1434
+ * model's. Equal tables mean the rename needs no storage change.
1435
+ */
1436
+ function modelRenameStorageEffect(statement, fromContract, contract) {
1437
+ const from = modelTable(fromContract, statement.from);
1438
+ if (from === void 0) return notOk({
1439
+ kind: "noTable",
1440
+ model: statement.from
1441
+ });
1442
+ const to = modelTable(contract, statement.to);
1443
+ if (to === void 0) return notOk({
1444
+ kind: "noTable",
1445
+ model: statement.to
1446
+ });
1447
+ if (from.namespaceId !== to.namespaceId) return ok({
1448
+ kind: "moveNamespace",
1449
+ from,
1450
+ to
1451
+ });
1452
+ if (from.table === to.table) return ok({ kind: "unchanged" });
1453
+ return ok({
1454
+ kind: "renameTable",
1455
+ rename: {
1456
+ namespaceId: from.namespaceId,
1457
+ from: from.table,
1458
+ to: to.table
1459
+ }
1460
+ });
1461
+ }
1462
+ function fieldColumn(contract, coordinate) {
1463
+ const fields = sqlModelStorage(contract, coordinate)?.fields;
1464
+ return fields !== void 0 && Object.hasOwn(fields, coordinate.field) ? fields[coordinate.field]?.column : void 0;
1465
+ }
1466
+ /**
1467
+ * The storage effect of a field rename: the origin field's column compared with the destination
1468
+ * field's. A relation field has no column on either side, and equal columns need no change.
1469
+ */
1470
+ function fieldRenameStorageEffect(statement, fromContract, contract) {
1471
+ const table = modelTable(fromContract, statement.from);
1472
+ if (table === void 0) return notOk({
1473
+ kind: "noTable",
1474
+ model: statement.from
1475
+ });
1476
+ const from = fieldColumn(fromContract, statement.from);
1477
+ const to = fieldColumn(contract, statement.to);
1478
+ if (from === void 0 && to === void 0) return ok({ kind: "unchanged" });
1479
+ if (from === void 0 || to === void 0) return notOk({ kind: "columnOnOneSide" });
1480
+ if (from === to) return ok({ kind: "unchanged" });
1481
+ return ok({
1482
+ kind: "renameColumn",
1483
+ table,
1484
+ from,
1485
+ to
1486
+ });
1487
+ }
1488
+ function operationsOf(call) {
1489
+ return [call, ...call.companions];
1490
+ }
1491
+ const DRIFTED = "so the database has drifted from that contract. Inspect it with prisma db schema, or leave out this statement.";
1492
+ const UNMATCHED = "A statement plans the rename a hand-written rename call makes, and that call does not match the contracts. Leave out this statement.";
1493
+ function statementRefused(statement, summary, why, location, refusedOperationClass) {
1494
+ return {
1495
+ kind: "statementRefused",
1496
+ summary,
1497
+ why,
1498
+ refusedStatement: statement,
1499
+ ...refusedOperationClass === void 0 ? {} : { refusedOperationClass },
1500
+ ...location === void 0 ? {} : { location: {
1501
+ namespaceId: location.namespaceId,
1502
+ entityKind: "table",
1503
+ entityName: location.table,
1504
+ ...location.column === void 0 ? {} : { column: location.column }
1505
+ } }
1506
+ };
1507
+ }
1508
+ function tableControlPolicy(contract, table) {
1509
+ const node = contract.storage.namespaces[table.namespaceId]?.entries.table?.[table.table];
1510
+ return controlPolicyForCall({
1511
+ namespaceId: table.namespaceId,
1512
+ entityKind: "table",
1513
+ entityName: table.table,
1514
+ ...StorageTable.is(node) && node.control !== void 0 ? { explicitNodeControlPolicy: node.control } : {},
1515
+ createsNewObject: false
1516
+ }, contract.defaultControlPolicy);
1517
+ }
1518
+ function tableKey(table) {
1519
+ return JSON.stringify([table.namespaceId, table.table]);
1520
+ }
1521
+ function tableRenameRefused(statement, label, rename, mismatch) {
1522
+ switch (mismatch.kind) {
1523
+ case "tableMissing": return statementRefused(statement, `${label}: the schema being planned from has no table "${rename.from}"`, `The database has no table "${rename.from}", although the contract it was last updated to names it, ${DRIFTED}`, {
1524
+ namespaceId: rename.namespaceId,
1525
+ table: rename.from
1526
+ });
1527
+ case "nameTaken": return statementRefused(statement, `${label}: the schema being planned from already has a table "${rename.to}"${mismatch.taken === rename.to ? "" : `, as "${mismatch.taken}"`}`, `A rename cannot replace a table that already exists. Rename or drop table "${mismatch.taken}" first, or leave out this statement.`, {
1528
+ namespaceId: rename.namespaceId,
1529
+ table: rename.to
1530
+ });
1531
+ case "tableInManyNamespaces":
1532
+ case "notInEndContract": return statementRefused(statement, `${label}: ${tableRenameMismatchReason(rename, mismatch)}`, UNMATCHED, {
1533
+ namespaceId: rename.namespaceId,
1534
+ table: rename.from
1535
+ });
1536
+ }
1537
+ }
1538
+ function columnRenameRefused(statement, label, rename, mismatch) {
1539
+ const table = {
1540
+ namespaceId: rename.namespaceId,
1541
+ table: rename.table
1542
+ };
1543
+ switch (mismatch.kind) {
1544
+ case "tableMissing": return statementRefused(statement, `${label}: the schema being planned from has no table "${rename.table}"`, `The database has no table "${rename.table}", although the contract it was last updated to names it, ${DRIFTED}`, table);
1545
+ case "columnMissing": return statementRefused(statement, `${label}: the schema being planned from has no column "${rename.from}" on table "${rename.table}"`, `The database has no column "${rename.from}" on table "${rename.table}", although the contract it was last updated to names it, ${DRIFTED}`, {
1546
+ ...table,
1547
+ column: rename.from
1548
+ });
1549
+ case "nameTaken": return statementRefused(statement, `${label}: the schema being planned from already has a column "${mismatch.taken}" on table "${rename.table}"`, `A rename cannot replace a column that already exists. Rename or drop column "${mismatch.taken}" of table "${rename.table}" first, or leave out this statement.`, {
1550
+ ...table,
1551
+ column: rename.to
1552
+ });
1553
+ case "tableInManyNamespaces":
1554
+ case "notInEndContract": return statementRefused(statement, `${label}: ${columnRenameMismatchReason(rename, mismatch)}`, UNMATCHED, {
1555
+ ...table,
1556
+ column: rename.from
1557
+ });
1558
+ }
1559
+ }
1560
+ var StatementPlanner = class {
1561
+ #fromContract;
1562
+ #contract;
1563
+ #policy;
1564
+ #target;
1565
+ /** The name each table renamed so far has in the working schema, keyed by its origin name. */
1566
+ #renamedTables = /* @__PURE__ */ new Map();
1567
+ calls = [];
1568
+ /** How many operations the calls planned so far lower to. */
1569
+ #operationCount = 0;
1570
+ tableRenames = [];
1571
+ columnRenames = [];
1572
+ constructor(input) {
1573
+ this.#fromContract = input.fromContract;
1574
+ this.#contract = input.contract;
1575
+ this.#policy = input.policy;
1576
+ this.#target = input.target;
1577
+ }
1578
+ /** Plans one statement; the result is the positions of the operations it accounts for. */
1579
+ plan(statement) {
1580
+ return statement.entity === "model" ? this.#planModel(statement) : this.#planField(statement);
1581
+ }
1582
+ #controlPolicyRefusal(statement, label, destinationTable) {
1583
+ const controlPolicy = tableControlPolicy(this.#contract, destinationTable);
1584
+ if (controlPolicy === "managed") return void 0;
1585
+ return statementRefused(statement, `${label}: the table's control policy is "${controlPolicy}"`, `Statements rename only tables, and columns of tables, whose control policy is "managed"; table "${destinationTable.table}" is "${controlPolicy}". Make the change in the database yourself and leave out this statement.`, destinationTable);
1586
+ }
1587
+ #emit(statement, label, location, call) {
1588
+ const refused = operationsOf(call).map((operation) => operation.operationClass).find((operationClass) => !this.#policy.allowedOperationClasses.includes(operationClass));
1589
+ if (refused !== void 0) return notOk(statementRefused(statement, `${label}: the plan does not allow "${refused}" operations`, `The rename produces a "${refused}" operation, and this command plans only ${this.#policy.allowedOperationClasses.map((c) => `"${c}"`).join(", ")} operations. Leave out this statement, or make the change with a command that allows "${refused}" operations, such as migration plan.`, location, refused));
1590
+ this.#target.apply(call);
1591
+ this.calls.push(call);
1592
+ const first = this.#operationCount;
1593
+ this.#operationCount += operationsOf(call).length;
1594
+ return ok(operationsOf(call).map((_, offset) => first + offset));
1595
+ }
1596
+ #planModel(statement) {
1597
+ const worked = modelRenameStorageEffect(statement, this.#fromContract, this.#contract);
1598
+ if (!worked.ok) return notOk(statementRefused(statement, `Model "${modelDisplayName(worked.failure.model)}" has no table in its contract`, `A model rename renames the model's table, and model "${modelDisplayName(worked.failure.model)}" has none in its contract. Leave out this statement.`, void 0));
1599
+ const effect = worked.value;
1600
+ if (effect.kind === "unchanged") return ok([]);
1601
+ if (effect.kind === "moveNamespace") return notOk(statementRefused(statement, `Moving a model to another namespace is not supported in this release: "${modelDisplayName(statement.from)}" to "${modelDisplayName(statement.to)}"`, `The model's table would move from namespace "${effect.from.namespaceId}" to namespace "${effect.to.namespaceId}". Leave out this statement and move the table yourself in a hand-written migration, or keep the model in namespace "${effect.from.namespaceId}".`, effect.from));
1602
+ const { rename } = effect;
1603
+ const destinationTable = {
1604
+ namespaceId: rename.namespaceId,
1605
+ table: rename.to
1606
+ };
1607
+ const label = `Cannot rename table "${rename.from}" to "${rename.to}"`;
1608
+ const policyRefusal = this.#controlPolicyRefusal(statement, label, destinationTable);
1609
+ if (policyRefusal !== void 0) return notOk(policyRefusal);
1610
+ const checked = checkTableRename(this.#target.tables(), this.#contract, rename);
1611
+ if (!checked.ok) return notOk(tableRenameRefused(statement, label, rename, checked.failure));
1612
+ const planned = this.#emit(statement, label, destinationTable, this.#target.renameTableCall(rename));
1613
+ if (planned.ok) {
1614
+ this.tableRenames.push(rename);
1615
+ this.#renamedTables.set(tableKey({
1616
+ namespaceId: rename.namespaceId,
1617
+ table: rename.from
1618
+ }), rename.to);
1619
+ }
1620
+ return planned;
1621
+ }
1622
+ #planField(statement) {
1623
+ const worked = fieldRenameStorageEffect(statement, this.#fromContract, this.#contract);
1624
+ if (!worked.ok && worked.failure.kind === "noTable") return notOk(statementRefused(statement, `Model "${modelDisplayName(worked.failure.model)}" has no table in its contract`, `A field rename renames the field's column, and model "${modelDisplayName(worked.failure.model)}" has no table in its contract. Leave out this statement.`, void 0));
1625
+ if (!worked.ok) return notOk(statementRefused(statement, `Field "${modelDisplayName(statement.from)}.${statement.from.field}" has a column on one side only of ${describeMigrationStatement(statement, this.#fromContract, this.#contract)}`, "A field rename renames a column or changes nothing in storage, and this field gains or loses its column. Leave out this statement and plan the change without it.", void 0));
1626
+ const effect = worked.value;
1627
+ if (effect.kind === "unchanged") return ok([]);
1628
+ const table = this.#renamedTables.get(tableKey(effect.table)) ?? effect.table.table;
1629
+ const destinationTable = modelTable(this.#contract, statement.to);
1630
+ if (destinationTable !== void 0 && (destinationTable.namespaceId !== effect.table.namespaceId || destinationTable.table !== table)) {
1631
+ const tableRename = {
1632
+ namespaceId: effect.table.namespaceId,
1633
+ from: table,
1634
+ to: destinationTable.table
1635
+ };
1636
+ const model = modelDisplayName(statement.to);
1637
+ const fieldText = `${model}.${statement.from.field}:${model}.${statement.to.field}`;
1638
+ return notOk(statementRefused(statement, `Cannot rename column "${table}"."${effect.from}": the model's table changes from "${table}" to "${destinationTable.table}", and no statement renames the table`, `The column would be renamed on a table the plan then drops and creates under the new name, and a migration that only changes the table name is planned the same way. With migration plan, rename the table by hand in its own migration first. Change the contract so that only the table name changes, and run prisma contract emit. Run prisma migration new --name <name> --from <hash of the migration the database is at>, add ${this.#target.renderTableRename(tableRename)} to the operations of its migration.ts, and run node on that migration.ts to write its ops.json. Then change the contract to its final form, emit it, and plan the field rename with --from that migration. With db update, change the contract so that only the table name changes, and run prisma contract emit. Rename the table in the database yourself with ${this.#target.tableRenameByHand(tableRename).join("; ")}, check that prisma db update --dry-run plans no drop of a table or column, and run prisma db update to store that contract. Then emit the final contract and run prisma db update --rename ${fieldText}.`, {
1639
+ namespaceId: effect.table.namespaceId,
1640
+ table,
1641
+ column: effect.from
1642
+ }));
1643
+ }
1644
+ const rename = {
1645
+ namespaceId: effect.table.namespaceId,
1646
+ table,
1647
+ from: effect.from,
1648
+ to: effect.to
1649
+ };
1650
+ const tableLocation = {
1651
+ namespaceId: rename.namespaceId,
1652
+ table
1653
+ };
1654
+ const label = `Cannot rename column "${table}"."${rename.from}" to "${rename.to}"`;
1655
+ const policyRefusal = this.#controlPolicyRefusal(statement, label, tableLocation);
1656
+ if (policyRefusal !== void 0) return notOk(policyRefusal);
1657
+ const checked = checkColumnRename(this.#target.tables(), this.#contract, rename);
1658
+ if (!checked.ok) return notOk(columnRenameRefused(statement, label, rename, checked.failure));
1659
+ const planned = this.#emit(statement, label, {
1660
+ ...tableLocation,
1661
+ column: rename.from
1662
+ }, this.#target.renameColumnCall(rename));
1663
+ if (planned.ok) this.columnRenames.push(rename);
1664
+ return planned;
1665
+ }
1666
+ };
1667
+ /**
1668
+ * Plans the statements in order against a target's working schema: each model rename becomes a
1669
+ * table rename and each field rename a column rename, computed against the schema earlier
1670
+ * statements left, then applied to it. The first statement that cannot be planned fails the whole
1671
+ * plan with a `statementRefused` conflict that carries the statement.
1672
+ */
1673
+ function planStatements(input) {
1674
+ const { fromContract } = input;
1675
+ const [first] = input.statements;
1676
+ if (first === void 0) return ok({
1677
+ calls: [],
1678
+ tableRenames: [],
1679
+ columnRenames: [],
1680
+ appliedStatements: []
1681
+ });
1682
+ if (fromContract === null) return notOk(statementRefused(first, "Statements need an origin contract, and this plan has none", "A statement names models and fields of the origin contract, and this plan has none. Plan from a contract that has the old names, or leave out the statement.", void 0));
1683
+ const planner = new StatementPlanner({
1684
+ ...input,
1685
+ fromContract
1686
+ });
1687
+ const appliedStatements = [];
1688
+ for (const statement of input.statements) {
1689
+ const operationIndexes = planner.plan(statement);
1690
+ if (!operationIndexes.ok) return operationIndexes;
1691
+ appliedStatements.push({
1692
+ statement,
1693
+ operationIndexes: operationIndexes.value
1694
+ });
1695
+ }
1696
+ return ok({
1697
+ calls: planner.calls,
1698
+ tableRenames: planner.tableRenames,
1699
+ columnRenames: planner.columnRenames,
1700
+ appliedStatements
1701
+ });
1702
+ }
1703
+ /** What a codec hook's call is about: the column of the field event it was returned for. */
1704
+ function fieldEventStorage(field) {
1705
+ return {
1706
+ storageName: [
1707
+ ...field.namespaceId === UNBOUND_NAMESPACE_ID ? [] : [field.namespaceId],
1708
+ field.tableName,
1709
+ field.columnName
1710
+ ].join("."),
1711
+ table: {
1712
+ namespaceId: field.namespaceId,
1713
+ table: field.tableName,
1714
+ column: field.columnName
1715
+ }
1716
+ };
1717
+ }
1718
+ /**
1719
+ * Names for destructive calls a target cannot map to storage: each call's factory name, with a
1720
+ * `#n` ordinal when several calls of the plan share it, so each name picks out one call.
1721
+ */
1722
+ function unknownCallNames(calls) {
1723
+ const counts = /* @__PURE__ */ new Map();
1724
+ for (const call of calls) counts.set(call.factoryName, (counts.get(call.factoryName) ?? 0) + 1);
1725
+ const seen = /* @__PURE__ */ new Map();
1726
+ return new Map(calls.map((call) => {
1727
+ const ordinal = (seen.get(call.factoryName) ?? 0) + 1;
1728
+ seen.set(call.factoryName, ordinal);
1729
+ return [call, (counts.get(call.factoryName) ?? 0) > 1 ? `${call.factoryName}#${ordinal}` : call.factoryName];
1730
+ }));
1731
+ }
1732
+ function originTable(context, namespaceId, table) {
1733
+ for (const statement of context.statements) {
1734
+ if (statement.entity !== "model") continue;
1735
+ const effect = modelRenameStorageEffect(statement, context.fromContract, context.contract);
1736
+ if (!effect.ok || effect.value.kind !== "renameTable") continue;
1737
+ const { rename } = effect.value;
1738
+ if (rename.namespaceId === namespaceId && rename.to === table) return rename.from;
1739
+ }
1740
+ return table;
1741
+ }
1742
+ function originColumn(context, namespaceId, table, column) {
1743
+ for (const statement of context.statements) {
1744
+ if (statement.entity !== "field") continue;
1745
+ const effect = fieldRenameStorageEffect(statement, context.fromContract, context.contract);
1746
+ if (!effect.ok || effect.value.kind !== "renameColumn") continue;
1747
+ const rename = effect.value;
1748
+ if (rename.table.namespaceId === namespaceId && rename.table.table === table && rename.to === column) return rename.from;
1749
+ }
1750
+ return column;
1751
+ }
1752
+ /** The models of `contract` that store `table`: a model and its variants share one. */
1753
+ function modelsStoring(contract, namespaceId, table) {
1754
+ return Object.entries(contract.domain.namespaces).flatMap(([modelNamespace, namespace]) => Object.entries(namespace.models).flatMap(([model, definition]) => {
1755
+ const { storage } = definition;
1756
+ if (!isSqlModelStorage(storage)) return [];
1757
+ if (storage.namespaceId !== namespaceId || storage.table !== table) return [];
1758
+ return [{
1759
+ coordinate: {
1760
+ namespaceId: asNamespaceId(modelNamespace),
1761
+ model
1762
+ },
1763
+ isRoot: definition.base === void 0,
1764
+ fields: storage.fields
1765
+ }];
1766
+ }));
1767
+ }
1768
+ function subjectOf(target, context) {
1769
+ const storage = {
1770
+ kind: "storage",
1771
+ name: target.storageName
1772
+ };
1773
+ const { fromContract } = context;
1774
+ if (target.table === void 0 || fromContract === null) return storage;
1775
+ const withOrigin = {
1776
+ ...context,
1777
+ fromContract
1778
+ };
1779
+ const { namespaceId } = target.table;
1780
+ const table = originTable(withOrigin, namespaceId, target.table.table);
1781
+ const models = modelsStoring(fromContract, namespaceId, table);
1782
+ if (target.table.column === void 0) {
1783
+ const model = models.find(({ isRoot }) => isRoot) ?? models[0];
1784
+ return model === void 0 ? storage : {
1785
+ kind: "model",
1786
+ ...model.coordinate
1787
+ };
1788
+ }
1789
+ const column = originColumn(withOrigin, namespaceId, table, target.table.column);
1790
+ for (const model of [...models].sort((a, b) => Number(b.isRoot) - Number(a.isRoot))) {
1791
+ const field = Object.entries(model.fields).find(([, stored]) => stored.column === column)?.[0];
1792
+ if (field !== void 0) return {
1793
+ kind: "field",
1794
+ ...model.coordinate,
1795
+ field
1796
+ };
1797
+ }
1798
+ return storage;
1799
+ }
1800
+ /**
1801
+ * The subject of each operation that loses data and each that widens access, at its position in
1802
+ * the plan. A subject is a model or a field of the origin contract when one stores it, found under
1803
+ * its origin name when a rename statement renamed its table or column earlier in the plan.
1804
+ */
1805
+ function subjectsOfCalls(calls, context) {
1806
+ const dataLoss = [];
1807
+ const accessWidening = [];
1808
+ let operationIndex = 0;
1809
+ for (const call of calls) {
1810
+ for (const target of call.dataLoss) dataLoss.push({
1811
+ operationIndex,
1812
+ subject: subjectOf(target, context)
1813
+ });
1814
+ for (const target of call.accessWidening) accessWidening.push({
1815
+ operationIndex,
1816
+ subject: subjectOf(target, context),
1817
+ widens: target.widens
1818
+ });
1819
+ operationIndex += call.operationCount;
1820
+ }
1821
+ return {
1822
+ dataLoss,
1823
+ accessWidening
1824
+ };
1825
+ }
1329
1826
  const readOnlyEmptyObject = Object.freeze({});
1330
1827
  function cloneRecord(value) {
1331
1828
  if (value === readOnlyEmptyObject) return value;
@@ -1381,15 +1878,20 @@ function createMigrationPlan(options) {
1381
1878
  ...options.meta ? { meta: cloneRecord(options.meta) } : {}
1382
1879
  });
1383
1880
  }
1384
- function plannerSuccess(plan, warnings) {
1881
+ function plannerSuccess(plan, appliedStatements, subjects, warnings) {
1385
1882
  return Object.freeze({
1386
1883
  kind: "success",
1387
1884
  plan,
1885
+ appliedStatements: Object.freeze([...appliedStatements]),
1886
+ dataLoss: Object.freeze([...subjects.dataLoss]),
1887
+ accessWidening: Object.freeze([...subjects.accessWidening]),
1388
1888
  ...warnings && warnings.length > 0 ? { warnings: Object.freeze(warnings.map((conflict) => Object.freeze({
1389
1889
  kind: conflict.kind,
1390
1890
  summary: conflict.summary,
1391
1891
  ...conflict.why ? { why: conflict.why } : {},
1392
1892
  ...conflict.location ? { location: Object.freeze({ ...conflict.location }) } : {},
1893
+ ...conflict.refusedStatement ? { refusedStatement: conflict.refusedStatement } : {},
1894
+ ...conflict.refusedOperationClass ? { refusedOperationClass: conflict.refusedOperationClass } : {},
1393
1895
  ...conflict.meta ? { meta: cloneRecord(conflict.meta) } : {}
1394
1896
  }))) } : {}
1395
1897
  });
@@ -1402,6 +1904,8 @@ function plannerFailure(conflicts) {
1402
1904
  summary: conflict.summary,
1403
1905
  ...conflict.why ? { why: conflict.why } : {},
1404
1906
  ...conflict.location ? { location: Object.freeze({ ...conflict.location }) } : {},
1907
+ ...conflict.refusedStatement ? { refusedStatement: conflict.refusedStatement } : {},
1908
+ ...conflict.refusedOperationClass ? { refusedOperationClass: conflict.refusedOperationClass } : {},
1405
1909
  ...conflict.meta ? { meta: cloneRecord(conflict.meta) } : {}
1406
1910
  })))
1407
1911
  });
@@ -1551,6 +2055,6 @@ function temporalCodecPresetWithPrecision(input) {
1551
2055
  }
1552
2056
  var control_default = new SqlFamilyDescriptor();
1553
2057
  //#endregion
1554
- export { runnerFailure as _, contractNamespaceToSchemaIR as a, temporalCodecPresetWithPrecision as b, control_default as c, detectTableNameCaseChanges as d, partitionCallsByControlPolicy as f, plannerSuccess as g, plannerFailure as h, assembleAuthoringContributions as i, createMigrationPlan as l, planFieldEventOperations as m, TABLE_NAME_CASE_CHANGED_CODE as n, contractToSchemaIR as o, partitionIssuesByControlPolicy as p, applyTableRename as r, controlPolicyForCall as s, INIT_ADDITIVE_POLICY as t, detectDestructiveChanges as u, runnerSuccess as v, temporalStringAuthoringPresets as x, sqlTypeLookupsOf as y };
2058
+ export { temporalStringAuthoringPresets as A, resolveTableRenameAgainst as C, storageNameOfOperation as D, sqlTypeLookupsOf as E, unmatchedColumnRename as M, unmatchedTableRename as N, subjectsOfCalls as O, resolveColumnRenameAgainst as S, runnerSuccess as T, planFieldEventCalls as _, contractNamespaceToSchemaIR as a, plannerFailure as b, control_default as c, detectTableNameCaseChanges as d, fieldEventStorage as f, partitionIssuesByControlPolicy as g, partitionCallsByControlPolicy as h, assembleAuthoringContributions as i, unknownCallNames as j, temporalCodecPresetWithPrecision as k, createMigrationPlan as l, modelRenameStorageEffect as m, INIT_ADDITIVE_POLICY as n, contractToSchemaIR as o, fieldRenameStorageEffect as p, TABLE_NAME_CASE_CHANGED_CODE as r, controlPolicyForCall as s, COLUMN_RENAME_UNMATCHED_CODE as t, detectDestructiveChanges as u, planFieldEventOperations as v, runnerFailure as w, plannerSuccess as x, planStatements as y };
1555
2059
 
1556
- //# sourceMappingURL=control-DxvOSmwF.mjs.map
2060
+ //# sourceMappingURL=control-BRbds4vn.mjs.map