@prisma-next/target-mongo 0.5.0-dev.9 → 0.6.0-dev.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 (38) hide show
  1. package/dist/codec-types.d.mts.map +1 -1
  2. package/dist/codec-types.mjs +1 -1
  3. package/dist/control.d.mts +24 -7
  4. package/dist/control.d.mts.map +1 -1
  5. package/dist/control.mjs +102 -83
  6. package/dist/control.mjs.map +1 -1
  7. package/dist/descriptor-meta-DdXFJeK1.mjs +12 -0
  8. package/dist/descriptor-meta-DdXFJeK1.mjs.map +1 -0
  9. package/dist/{migration-factories-Dbk5afMU.mjs → migration-factories-ZBsWqXt-.mjs} +4 -3
  10. package/dist/migration-factories-ZBsWqXt-.mjs.map +1 -0
  11. package/dist/migration.d.mts +7 -1
  12. package/dist/migration.d.mts.map +1 -1
  13. package/dist/migration.mjs +2 -3
  14. package/dist/{op-factory-call-CVgzmLJh.d.mts → op-factory-call-9z5D19cP.d.mts} +1 -2
  15. package/dist/op-factory-call-9z5D19cP.d.mts.map +1 -0
  16. package/dist/pack.d.mts.map +1 -1
  17. package/dist/pack.mjs +3 -15
  18. package/dist/pack.mjs.map +1 -1
  19. package/dist/runtime.d.mts +15 -0
  20. package/dist/runtime.d.mts.map +1 -0
  21. package/dist/runtime.mjs +21 -0
  22. package/dist/runtime.mjs.map +1 -0
  23. package/dist/schema-verify.d.mts.map +1 -1
  24. package/dist/schema-verify.mjs +2 -3
  25. package/dist/{verify-mongo-schema-P0TRBJNs.mjs → verify-mongo-schema-DlPXaotB.mjs} +2 -6
  26. package/dist/verify-mongo-schema-DlPXaotB.mjs.map +1 -0
  27. package/package.json +20 -17
  28. package/src/core/marker-ledger.ts +90 -20
  29. package/src/core/migration-factories.ts +8 -0
  30. package/src/core/mongo-ops-serializer.ts +0 -8
  31. package/src/core/mongo-planner.ts +8 -2
  32. package/src/core/mongo-runner.ts +80 -57
  33. package/src/core/planner-produced-migration.ts +0 -1
  34. package/src/core/render-typescript.ts +3 -7
  35. package/src/exports/runtime.ts +32 -0
  36. package/dist/migration-factories-Dbk5afMU.mjs.map +0 -1
  37. package/dist/op-factory-call-CVgzmLJh.d.mts.map +0 -1
  38. package/dist/verify-mongo-schema-P0TRBJNs.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"codec-types.d.mts","names":[],"sources":["../src/exports/codec-types.ts"],"sourcesContent":[],"mappings":";KAAY,UAAA;EAAA,SAAA,kBAMiC,EAAA;;;;;;;;;;;;;;;;;;;;;oBAAA;qBAAuB"}
1
+ {"version":3,"file":"codec-types.d.mts","names":[],"sources":["../src/exports/codec-types.ts"],"mappings":";KAAY,UAAA;EAAA,SACD,kBAAA;IAAA,SAA+B,KAAA;IAAA,SAAwB,MAAA;EAAA;EAAA,SACvD,gBAAA;IAAA,SAA6B,KAAA;IAAA,SAAwB,MAAA;EAAA;EAAA,SACrD,gBAAA;IAAA,SAA6B,KAAA;IAAA,SAAwB,MAAA;EAAA;EAAA,SACrD,eAAA;IAAA,SAA4B,KAAA;IAAA,SAAwB,MAAA;EAAA;EAAA,SACpD,cAAA;IAAA,SAA2B,KAAA;IAAA,SAAyB,MAAA;EAAA;EAAA,SACpD,cAAA;IAAA,SAA2B,KAAA,EAAO,IAAA;IAAA,SAAe,MAAA,EAAQ,IAAA;EAAA;EAAA,SACzD,gBAAA;IAAA,SACE,KAAA;IAAA,SACA,MAAA;EAAA;AAAA"}
@@ -1 +1 @@
1
- export { };
1
+ export {};
@@ -1,11 +1,11 @@
1
- import { a as DropCollectionCall, c as schemaCollectionToCreateCollectionOptions, i as CreateIndexCall, l as schemaIndexToCreateIndexOptions, n as CollModMeta, o as DropIndexCall, r as CreateCollectionCall, s as OpFactoryCall, t as CollModCall } from "./op-factory-call-CVgzmLJh.mjs";
1
+ import { a as DropCollectionCall, c as schemaCollectionToCreateCollectionOptions, i as CreateIndexCall, l as schemaIndexToCreateIndexOptions, n as CollModMeta, o as DropIndexCall, r as CreateCollectionCall, s as OpFactoryCall, t as CollModCall } from "./op-factory-call-9z5D19cP.mjs";
2
2
  import { MongoSchemaIR } from "@prisma-next/mongo-schema-ir";
3
3
  import { MongoQueryPlan } from "@prisma-next/mongo-query-ast/execution";
4
4
  import { AnyMongoMigrationOperation, MongoAndExpr, MongoDdlCommandVisitor, MongoExistsExpr, MongoExprFilter, MongoFieldFilter, MongoFilterExpr, MongoFilterVisitor, MongoInspectionCommandVisitor, MongoMigrationPlanOperation, MongoNotExpr, MongoOrExpr } from "@prisma-next/mongo-query-ast/control";
5
5
  import { Migration, MigrationMeta } from "@prisma-next/migration-tools/migration";
6
6
  import { MigrationOperationPolicy, MigrationPlan, MigrationPlanOperation, MigrationPlanWithAuthoringSurface, MigrationPlanner, MigrationPlannerConflict, MigrationPlannerResult, MigrationRunnerExecutionChecks, MigrationRunnerResult, MigrationScaffoldContext, OperationContext } from "@prisma-next/framework-components/control";
7
7
  import { MongoContract } from "@prisma-next/mongo-contract";
8
- import { ContractMarkerRecord } from "@prisma-next/contract/types";
8
+ import { Contract, ContractMarkerRecord } from "@prisma-next/contract/types";
9
9
  import { Db } from "mongodb";
10
10
  import { TargetBoundComponentDescriptor } from "@prisma-next/framework-components/components";
11
11
  import { MongoAdapter, MongoDriver } from "@prisma-next/mongo-lowering";
@@ -33,10 +33,21 @@ declare function readMarker(db: Db): Promise<ContractMarkerRecord | null>;
33
33
  declare function initMarker(db: Db, destination: {
34
34
  readonly storageHash: string;
35
35
  readonly profileHash: string;
36
+ readonly invariants?: readonly string[];
36
37
  }): Promise<void>;
38
+ /**
39
+ * Updates the marker doc atomically (CAS on `expectedFrom`).
40
+ *
41
+ * `destination.invariants`:
42
+ * - `undefined` → existing field left untouched.
43
+ * - explicit value → merged into the existing field server-side via an
44
+ * aggregation pipeline (`$setUnion + $sortArray`), atomic at the
45
+ * document level. `[]` is a no-op merge.
46
+ */
37
47
  declare function updateMarker(db: Db, expectedFrom: string, destination: {
38
48
  readonly storageHash: string;
39
49
  readonly profileHash: string;
50
+ readonly invariants?: readonly string[];
40
51
  }): Promise<boolean>;
41
52
  declare function writeLedgerEntry(db: Db, entry: {
42
53
  readonly edgeId: string;
@@ -68,7 +79,12 @@ declare class MongoMigrationPlanner implements MigrationPlanner<'mongo', 'mongo'
68
79
  readonly contract: unknown;
69
80
  readonly schema: unknown;
70
81
  readonly policy: MigrationOperationPolicy;
71
- readonly fromHash: string;
82
+ /**
83
+ * The "from" contract (state the planner assumes the database starts at),
84
+ * or `null` for reconciliation flows. Used to populate `describe().from`
85
+ * on the produced plan as `fromContract?.storage.storageHash ?? null`.
86
+ */
87
+ readonly fromContract: Contract | null;
72
88
  readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'mongo', 'mongo'>>;
73
89
  }): MigrationPlannerResult;
74
90
  /**
@@ -89,10 +105,12 @@ interface MarkerOperations {
89
105
  initMarker(destination: {
90
106
  readonly storageHash: string;
91
107
  readonly profileHash: string;
108
+ readonly invariants?: readonly string[];
92
109
  }): Promise<void>;
93
110
  updateMarker(expectedFrom: string, destination: {
94
111
  readonly storageHash: string;
95
112
  readonly profileHash: string;
113
+ readonly invariants?: readonly string[];
96
114
  }): Promise<boolean>;
97
115
  writeLedgerEntry(entry: {
98
116
  readonly edgeId: string;
@@ -165,9 +183,8 @@ declare function renderOps(calls: ReadonlyArray<OpFactoryCall>): MongoMigrationP
165
183
  //#endregion
166
184
  //#region src/core/render-typescript.d.ts
167
185
  interface RenderMigrationMeta {
168
- readonly from: string;
186
+ readonly from: string | null;
169
187
  readonly to: string;
170
- readonly kind?: string;
171
188
  readonly labels?: readonly string[];
172
189
  }
173
190
  /**
@@ -176,8 +193,8 @@ interface RenderMigrationMeta {
176
193
  * `Migration` (i.e. `MongoMigration`) from `@prisma-next/family-mongo`, and
177
194
  * implements the abstract `operations` and `describe` members. `meta` is
178
195
  * always rendered — `describe()` is part of the `Migration` contract, so
179
- * even an empty stub must satisfy it; callers pass empty strings for a
180
- * migration-new scaffold.
196
+ * even an empty stub must satisfy it; callers pass `from: null` for a
197
+ * baseline `migration-new` scaffold (and a real `to` hash either way).
181
198
  *
182
199
  * The walk is polymorphic: each call node contributes its own
183
200
  * `renderTypeScript()` expression and declares its own
@@ -1 +1 @@
1
- {"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/contract-to-schema.ts","../src/core/ddl-formatter.ts","../src/core/filter-evaluator.ts","../src/core/marker-ledger.ts","../src/core/mongo-ops-serializer.ts","../src/core/mongo-planner.ts","../src/core/mongo-runner.ts","../src/core/planner-produced-migration.ts","../src/core/render-ops.ts","../src/core/render-typescript.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/contract-to-schema.ts","../src/core/ddl-formatter.ts","../src/core/filter-evaluator.ts","../src/core/marker-ledger.ts","../src/core/mongo-ops-serializer.ts","../src/core/mongo-planner.ts","../src/core/mongo-runner.ts","../src/core/planner-produced-migration.ts","../src/core/render-ops.ts","../src/core/render-typescript.ts"],"mappings":"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"}
package/dist/control.mjs CHANGED
@@ -1,16 +1,15 @@
1
- import { n as contractToMongoSchemaIR, t as verifyMongoSchema } from "./verify-mongo-schema-P0TRBJNs.mjs";
2
- import { a as dropCollection, n as createCollection, o as dropIndex, r as createIndex, t as collMod } from "./migration-factories-Dbk5afMU.mjs";
1
+ import { n as contractToMongoSchemaIR, t as verifyMongoSchema } from "./verify-mongo-schema-DlPXaotB.mjs";
2
+ import { a as dropCollection, n as createCollection, o as dropIndex, r as createIndex, t as collMod } from "./migration-factories-ZBsWqXt-.mjs";
3
3
  import { canonicalize, deepEqual } from "@prisma-next/mongo-schema-ir";
4
4
  import { AggregateCommand, MongoAddFieldsStage, MongoLimitStage, MongoLookupStage, MongoMatchStage, MongoMergeStage, MongoProjectStage, MongoSortStage, RawAggregateCommand, RawDeleteManyCommand, RawDeleteOneCommand, RawFindOneAndDeleteCommand, RawFindOneAndUpdateCommand, RawInsertManyCommand, RawInsertOneCommand, RawUpdateManyCommand, RawUpdateOneCommand } from "@prisma-next/mongo-query-ast/execution";
5
+ import { type } from "arktype";
5
6
  import { CollModCommand, CreateCollectionCommand, CreateIndexCommand, DropCollectionCommand, DropIndexCommand, ListCollectionsCommand, ListIndexesCommand, MongoAndExpr, MongoExistsExpr, MongoFieldFilter, MongoNotExpr, MongoOrExpr } from "@prisma-next/mongo-query-ast/control";
6
7
  import { ifDefined } from "@prisma-next/utils/defined";
7
- import { type } from "arktype";
8
8
  import { TsExpression, jsonToTsSource, renderImports } from "@prisma-next/ts-render";
9
9
  import { Migration } from "@prisma-next/migration-tools/migration";
10
10
  import { detectScaffoldRuntime, shebangLineFor } from "@prisma-next/migration-tools/migration-ts";
11
11
  import { errorRunnerFailed } from "@prisma-next/errors/execution";
12
12
  import { notOk, ok } from "@prisma-next/utils/result";
13
-
14
13
  //#region src/core/ddl-formatter.ts
15
14
  function formatKeySpec(keys) {
16
15
  return `{ ${keys.map((k) => `${JSON.stringify(k.field)}: ${JSON.stringify(k.direction)}`).join(", ")} }`;
@@ -80,7 +79,6 @@ function formatMongoOperations(operations) {
80
79
  }
81
80
  return statements;
82
81
  }
83
-
84
82
  //#endregion
85
83
  //#region src/core/filter-evaluator.ts
86
84
  function getNestedField(doc, path) {
@@ -133,11 +131,35 @@ var FilterEvaluator = class {
133
131
  throw new Error("Aggregation expression filters are not supported in migration checks");
134
132
  }
135
133
  };
136
-
137
134
  //#endregion
138
135
  //#region src/core/marker-ledger.ts
139
136
  const COLLECTION = "_prisma_migrations";
140
137
  const MARKER_ID = "marker";
138
+ const MongoMarkerDocSchema = type({
139
+ storageHash: "string",
140
+ profileHash: "string",
141
+ "contractJson?": "unknown | null",
142
+ "canonicalVersion?": "number | null",
143
+ "updatedAt?": "Date",
144
+ "appTag?": "string | null",
145
+ "meta?": type({ "[string]": "unknown" }).or("null"),
146
+ "invariants?": type("string").array(),
147
+ "+": "delete"
148
+ });
149
+ function parseMongoMarkerDoc(doc) {
150
+ const result = MongoMarkerDocSchema(doc);
151
+ if (result instanceof type.errors) throw new Error(`Invalid marker doc on ${COLLECTION}: ${result.summary}`);
152
+ return {
153
+ storageHash: result.storageHash,
154
+ profileHash: result.profileHash,
155
+ contractJson: result.contractJson ?? null,
156
+ canonicalVersion: result.canonicalVersion ?? null,
157
+ updatedAt: result.updatedAt ?? /* @__PURE__ */ new Date(),
158
+ appTag: result.appTag ?? null,
159
+ meta: result.meta ?? {},
160
+ invariants: result.invariants ?? []
161
+ };
162
+ }
141
163
  async function executeAggregate(db, cmd) {
142
164
  return db.collection(cmd.collection).aggregate(cmd.pipeline).toArray();
143
165
  }
@@ -150,15 +172,7 @@ async function executeFindOneAndUpdate(db, cmd) {
150
172
  async function readMarker(db) {
151
173
  const doc = (await executeAggregate(db, new RawAggregateCommand(COLLECTION, [{ $match: { _id: MARKER_ID } }, { $limit: 1 }])))[0];
152
174
  if (!doc) return null;
153
- return {
154
- storageHash: doc["storageHash"],
155
- profileHash: doc["profileHash"],
156
- contractJson: doc["contractJson"] ?? null,
157
- canonicalVersion: doc["canonicalVersion"] ?? null,
158
- updatedAt: doc["updatedAt"],
159
- appTag: doc["appTag"] ?? null,
160
- meta: doc["meta"] ?? {}
161
- };
175
+ return parseMongoMarkerDoc(doc);
162
176
  }
163
177
  async function initMarker(db, destination) {
164
178
  await executeInsertOne(db, new RawInsertOneCommand(COLLECTION, {
@@ -169,18 +183,36 @@ async function initMarker(db, destination) {
169
183
  canonicalVersion: null,
170
184
  updatedAt: /* @__PURE__ */ new Date(),
171
185
  appTag: null,
172
- meta: {}
186
+ meta: {},
187
+ invariants: destination.invariants ?? []
173
188
  }));
174
189
  }
190
+ /**
191
+ * Updates the marker doc atomically (CAS on `expectedFrom`).
192
+ *
193
+ * `destination.invariants`:
194
+ * - `undefined` → existing field left untouched.
195
+ * - explicit value → merged into the existing field server-side via an
196
+ * aggregation pipeline (`$setUnion + $sortArray`), atomic at the
197
+ * document level. `[]` is a no-op merge.
198
+ */
175
199
  async function updateMarker(db, expectedFrom, destination) {
176
- return await executeFindOneAndUpdate(db, new RawFindOneAndUpdateCommand(COLLECTION, {
177
- _id: MARKER_ID,
178
- storageHash: expectedFrom
179
- }, { $set: {
200
+ const setBase = {
180
201
  storageHash: destination.storageHash,
181
202
  profileHash: destination.profileHash,
182
203
  updatedAt: /* @__PURE__ */ new Date()
183
- } }, false)) !== null;
204
+ };
205
+ const update = destination.invariants === void 0 ? { $set: setBase } : [{ $set: {
206
+ ...setBase,
207
+ invariants: { $sortArray: {
208
+ input: { $setUnion: [{ $ifNull: ["$invariants", []] }, destination.invariants] },
209
+ sortBy: 1
210
+ } }
211
+ } }];
212
+ return await executeFindOneAndUpdate(db, new RawFindOneAndUpdateCommand(COLLECTION, {
213
+ _id: MARKER_ID,
214
+ storageHash: expectedFrom
215
+ }, update, false)) !== null;
184
216
  }
185
217
  async function writeLedgerEntry(db, entry) {
186
218
  await executeInsertOne(db, new RawInsertOneCommand(COLLECTION, {
@@ -191,7 +223,6 @@ async function writeLedgerEntry(db, entry) {
191
223
  appliedAt: /* @__PURE__ */ new Date()
192
224
  }));
193
225
  }
194
-
195
226
  //#endregion
196
227
  //#region src/core/mongo-ops-serializer.ts
197
228
  const CreateIndexJson = type({
@@ -320,13 +351,9 @@ const QueryPlanJson = type({
320
351
  target: "string",
321
352
  storageHash: "string",
322
353
  lane: "string",
323
- paramDescriptors: "unknown[]",
324
354
  "targetFamily?": "string",
325
355
  "profileHash?": "string",
326
- "annotations?": "Record<string, unknown>",
327
- "refs?": "Record<string, unknown>",
328
- "projection?": "Record<string, string> | string[]",
329
- "projectionTypes?": "Record<string, string>"
356
+ "annotations?": "Record<string, unknown>"
330
357
  })
331
358
  });
332
359
  const CheckJson = type({
@@ -490,13 +517,9 @@ function deserializeMongoQueryPlan(json) {
490
517
  target: m.target,
491
518
  storageHash: m.storageHash,
492
519
  lane: m.lane,
493
- paramDescriptors: m.paramDescriptors,
494
520
  ...ifDefined("targetFamily", m.targetFamily),
495
521
  ...ifDefined("profileHash", m.profileHash),
496
- ...ifDefined("annotations", m.annotations),
497
- ...ifDefined("refs", m.refs),
498
- ...ifDefined("projection", m.projection),
499
- ...ifDefined("projectionTypes", m.projectionTypes)
522
+ ...ifDefined("annotations", m.annotations)
500
523
  };
501
524
  return {
502
525
  collection: data.collection,
@@ -625,7 +648,6 @@ function deserializeMongoOps(json) {
625
648
  function serializeMongoOps(ops) {
626
649
  return JSON.stringify(ops, null, 2);
627
650
  }
628
-
629
651
  //#endregion
630
652
  //#region src/core/op-factory-call.ts
631
653
  const TARGET_MIGRATION_MODULE = "@prisma-next/target-mongo/migration";
@@ -780,13 +802,11 @@ function schemaCollectionToCreateCollectionOptions(coll) {
780
802
  changeStreamPreAndPostImages: opts?.changeStreamPreAndPostImages
781
803
  };
782
804
  }
783
-
784
805
  //#endregion
785
806
  //#region src/core/render-ops.ts
786
807
  function renderOps(calls) {
787
808
  return calls.map((call) => call.toOp());
788
809
  }
789
-
790
810
  //#endregion
791
811
  //#region src/core/render-typescript.ts
792
812
  /**
@@ -818,8 +838,8 @@ const BASE_IMPORTS = [{
818
838
  * `Migration` (i.e. `MongoMigration`) from `@prisma-next/family-mongo`, and
819
839
  * implements the abstract `operations` and `describe` members. `meta` is
820
840
  * always rendered — `describe()` is part of the `Migration` contract, so
821
- * even an empty stub must satisfy it; callers pass empty strings for a
822
- * migration-new scaffold.
841
+ * even an empty stub must satisfy it; callers pass `from: null` for a
842
+ * baseline `migration-new` scaffold (and a real `to` hash either way).
823
843
  *
824
844
  * The walk is polymorphic: each call node contributes its own
825
845
  * `renderTypeScript()` expression and declares its own
@@ -861,7 +881,6 @@ function buildDescribeMethod(meta) {
861
881
  lines.push(" return {");
862
882
  lines.push(` from: ${JSON.stringify(meta.from)},`);
863
883
  lines.push(` to: ${JSON.stringify(meta.to)},`);
864
- if (meta.kind) lines.push(` kind: ${JSON.stringify(meta.kind)},`);
865
884
  if (meta.labels && meta.labels.length > 0) lines.push(` labels: ${jsonToTsSource(meta.labels)},`);
866
885
  lines.push(" };");
867
886
  lines.push(" }");
@@ -872,7 +891,6 @@ function indent(text, spaces) {
872
891
  const pad = " ".repeat(spaces);
873
892
  return text.split("\n").map((line) => line.trim() ? `${pad}${line}` : line).join("\n");
874
893
  }
875
-
876
894
  //#endregion
877
895
  //#region src/core/planner-produced-migration.ts
878
896
  /**
@@ -892,6 +910,8 @@ function indent(text, spaces) {
892
910
  * cycle.
893
911
  */
894
912
  var PlannerProducedMongoMigration = class extends Migration {
913
+ calls;
914
+ meta;
895
915
  targetId = "mongo";
896
916
  constructor(calls, meta) {
897
917
  super();
@@ -908,12 +928,10 @@ var PlannerProducedMongoMigration = class extends Migration {
908
928
  return renderCallsToTypeScript(this.calls, {
909
929
  from: this.meta.from,
910
930
  to: this.meta.to,
911
- ...ifDefined("kind", this.meta.kind),
912
931
  ...ifDefined("labels", this.meta.labels)
913
932
  });
914
933
  }
915
934
  };
916
-
917
935
  //#endregion
918
936
  //#region src/core/mongo-planner.ts
919
937
  function buildIndexLookupKey(index) {
@@ -1030,7 +1048,7 @@ var MongoMigrationPlanner = class {
1030
1048
  return {
1031
1049
  kind: "success",
1032
1050
  plan: new PlannerProducedMongoMigration(result.calls, {
1033
- from: options.fromHash,
1051
+ from: options.fromContract?.storage.storageHash ?? null,
1034
1052
  to: contract.storage.storageHash
1035
1053
  })
1036
1054
  };
@@ -1086,7 +1104,6 @@ function planMutableOptionsDiffCall(collName, origin, dest) {
1086
1104
  operationClass: desiredCSPPI.enabled ? "widening" : "destructive"
1087
1105
  });
1088
1106
  }
1089
-
1090
1107
  //#endregion
1091
1108
  //#region src/core/mongo-runner.ts
1092
1109
  const READ_ONLY_CHECK_COMMAND_KINDS = new Set(["aggregate", "rawAggregate"]);
@@ -1098,6 +1115,7 @@ function runnerFailure(code, summary, opts) {
1098
1115
  });
1099
1116
  }
1100
1117
  var MongoMigrationRunner = class {
1118
+ deps;
1101
1119
  constructor(deps) {
1102
1120
  this.deps = deps;
1103
1121
  }
@@ -1142,40 +1160,44 @@ var MongoMigrationRunner = class {
1142
1160
  }
1143
1161
  const destination = options.plan.destination;
1144
1162
  const profileHash = options.destinationContract.profileHash ?? destination.storageHash;
1145
- if (operationsExecuted === 0 && existingMarker?.storageHash === destination.storageHash && existingMarker.profileHash === profileHash) return ok({
1146
- operationsPlanned: operations.length,
1147
- operationsExecuted
1148
- });
1149
- const liveSchema = await this.deps.introspectSchema();
1150
- const verifyResult = verifyMongoSchema({
1151
- contract: options.destinationContract,
1152
- schema: liveSchema,
1153
- strict: options.strictVerification ?? true,
1154
- frameworkComponents: options.frameworkComponents,
1155
- ...options.context ? { context: options.context } : {}
1156
- });
1157
- if (!verifyResult.ok) return runnerFailure("SCHEMA_VERIFY_FAILED", verifyResult.summary, {
1158
- why: "The resulting database schema does not satisfy the destination contract.",
1159
- meta: { issues: verifyResult.schema.issues }
1160
- });
1161
- if (existingMarker) {
1162
- if (!await markerOps.updateMarker(existingMarker.storageHash, {
1163
+ const incomingInvariants = options.plan.providedInvariants ?? [];
1164
+ const existingInvariantSet = new Set(existingMarker?.invariants ?? []);
1165
+ const incomingIsSubsetOfExisting = incomingInvariants.every((id) => existingInvariantSet.has(id));
1166
+ const markerAlreadyAtDestination = existingMarker !== null && existingMarker.storageHash === destination.storageHash && existingMarker.profileHash === profileHash;
1167
+ if (!(operationsExecuted === 0 && markerAlreadyAtDestination && incomingIsSubsetOfExisting)) {
1168
+ const liveSchema = await this.deps.introspectSchema();
1169
+ const verifyResult = verifyMongoSchema({
1170
+ contract: options.destinationContract,
1171
+ schema: liveSchema,
1172
+ strict: options.strictVerification ?? true,
1173
+ frameworkComponents: options.frameworkComponents,
1174
+ ...options.context ? { context: options.context } : {}
1175
+ });
1176
+ if (!verifyResult.ok) return runnerFailure("SCHEMA_VERIFY_FAILED", verifyResult.summary, {
1177
+ why: "The resulting database schema does not satisfy the destination contract.",
1178
+ meta: { issues: verifyResult.schema.issues }
1179
+ });
1180
+ if (existingMarker) {
1181
+ if (!await markerOps.updateMarker(existingMarker.storageHash, {
1182
+ storageHash: destination.storageHash,
1183
+ profileHash,
1184
+ invariants: incomingInvariants
1185
+ })) return runnerFailure("MARKER_CAS_FAILURE", "Marker was modified by another process during migration execution.", { meta: {
1186
+ expectedStorageHash: existingMarker.storageHash,
1187
+ destinationStorageHash: destination.storageHash
1188
+ } });
1189
+ } else await markerOps.initMarker({
1163
1190
  storageHash: destination.storageHash,
1164
- profileHash
1165
- })) return runnerFailure("MARKER_CAS_FAILURE", "Marker was modified by another process during migration execution.", { meta: {
1166
- expectedStorageHash: existingMarker.storageHash,
1167
- destinationStorageHash: destination.storageHash
1168
- } });
1169
- } else await markerOps.initMarker({
1170
- storageHash: destination.storageHash,
1171
- profileHash
1172
- });
1173
- const originHash = existingMarker?.storageHash ?? "";
1174
- await markerOps.writeLedgerEntry({
1175
- edgeId: `${originHash}->${destination.storageHash}`,
1176
- from: originHash,
1177
- to: destination.storageHash
1178
- });
1191
+ profileHash,
1192
+ invariants: incomingInvariants
1193
+ });
1194
+ const originHash = existingMarker?.storageHash ?? "";
1195
+ await markerOps.writeLedgerEntry({
1196
+ edgeId: `${originHash}->${destination.storageHash}`,
1197
+ from: originHash,
1198
+ to: destination.storageHash
1199
+ });
1200
+ }
1179
1201
  return ok({
1180
1202
  operationsPlanned: operations.length,
1181
1203
  operationsExecuted
@@ -1195,7 +1217,7 @@ var MongoMigrationRunner = class {
1195
1217
  };
1196
1218
  }
1197
1219
  for (const plan of op.run) {
1198
- const wireCommand = await adapter.lower(plan);
1220
+ const wireCommand = await adapter.lower(plan, {});
1199
1221
  for await (const _ of driver.execute(wireCommand));
1200
1222
  }
1201
1223
  if (runPostchecks && op.postcheck.length > 0) {
@@ -1221,7 +1243,7 @@ var MongoMigrationRunner = class {
1221
1243
  collection: check.source.collection
1222
1244
  }
1223
1245
  });
1224
- const wireCommand = await adapter.lower(check.source);
1246
+ const wireCommand = await adapter.lower(check.source, {});
1225
1247
  let matchFound = false;
1226
1248
  for await (const row of driver.execute(wireCommand)) if (filterEvaluator.evaluate(check.filter, row)) {
1227
1249
  matchFound = true;
@@ -1254,10 +1276,7 @@ var MongoMigrationRunner = class {
1254
1276
  }
1255
1277
  ensureMarkerCompatibility(marker, plan) {
1256
1278
  const origin = plan.origin ?? null;
1257
- if (!origin) {
1258
- if (marker) return runnerFailure("MARKER_ORIGIN_MISMATCH", "Database already has a contract marker but the plan has no origin. This would silently overwrite the existing marker.", { meta: { markerStorageHash: marker.storageHash } });
1259
- return;
1260
- }
1279
+ if (!origin) return;
1261
1280
  if (!marker) return runnerFailure("MARKER_ORIGIN_MISMATCH", `Missing contract marker: expected origin storage hash ${origin.storageHash}.`, { meta: { expectedOriginStorageHash: origin.storageHash } });
1262
1281
  if (marker.storageHash !== origin.storageHash) return runnerFailure("MARKER_ORIGIN_MISMATCH", `Existing contract marker (${marker.storageHash}) does not match plan origin (${origin.storageHash}).`, { meta: {
1263
1282
  markerStorageHash: marker.storageHash,
@@ -1265,7 +1284,7 @@ var MongoMigrationRunner = class {
1265
1284
  } });
1266
1285
  }
1267
1286
  };
1268
-
1269
1287
  //#endregion
1270
1288
  export { CollModCall, CreateCollectionCall, CreateIndexCall, DropCollectionCall, DropIndexCall, FilterEvaluator, MongoMigrationPlanner, MongoMigrationRunner, PlannerProducedMongoMigration, contractToMongoSchemaIR, deserializeMongoOp, deserializeMongoOps, formatMongoOperations, initMarker, readMarker, renderCallsToTypeScript, renderOps, schemaCollectionToCreateCollectionOptions, schemaIndexToCreateIndexOptions, serializeMongoOps, updateMarker, writeLedgerEntry };
1289
+
1271
1290
  //# sourceMappingURL=control.mjs.map