@prisma-next/target-mongo 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/control.d.mts +24 -7
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +98 -72
- package/dist/control.mjs.map +1 -1
- package/dist/descriptor-meta-D9_5quQi.mjs +14 -0
- package/dist/descriptor-meta-D9_5quQi.mjs.map +1 -0
- package/dist/{migration-factories-Dbk5afMU.mjs → migration-factories-CoNYWrd1.mjs} +3 -1
- package/dist/migration-factories-CoNYWrd1.mjs.map +1 -0
- package/dist/migration.d.mts +7 -1
- package/dist/migration.d.mts.map +1 -1
- package/dist/migration.mjs +1 -1
- package/dist/{op-factory-call-CVgzmLJh.d.mts → op-factory-call--nK5dk8n.d.mts} +1 -1
- package/dist/{op-factory-call-CVgzmLJh.d.mts.map → op-factory-call--nK5dk8n.d.mts.map} +1 -1
- package/dist/pack.mjs +1 -11
- package/dist/pack.mjs.map +1 -1
- package/dist/runtime.d.mts +20 -0
- package/dist/runtime.d.mts.map +1 -0
- package/dist/runtime.mjs +28 -0
- package/dist/runtime.mjs.map +1 -0
- package/dist/schema-verify.mjs +1 -1
- package/dist/{verify-mongo-schema-P0TRBJNs.mjs → verify-mongo-schema-Daa7BMJY.mjs} +1 -1
- package/dist/{verify-mongo-schema-P0TRBJNs.mjs.map → verify-mongo-schema-Daa7BMJY.mjs.map} +1 -1
- package/package.json +16 -14
- package/src/core/marker-ledger.ts +90 -20
- package/src/core/migration-factories.ts +8 -0
- package/src/core/mongo-ops-serializer.ts +0 -8
- package/src/core/mongo-planner.ts +8 -2
- package/src/core/mongo-runner.ts +80 -57
- package/src/core/planner-produced-migration.ts +0 -1
- package/src/core/render-typescript.ts +3 -7
- package/src/exports/runtime.ts +38 -0
- package/dist/migration-factories-Dbk5afMU.mjs.map +0 -1
package/dist/control.d.mts
CHANGED
|
@@ -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
|
|
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--nK5dk8n.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
|
-
|
|
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
|
|
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
|
package/dist/control.d.mts.map
CHANGED
|
@@ -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":";;;;;;;;;;;;;iBAoDgB,uBAAA,WAAkC,uBAAuB;;;iBC6CzD,qBAAA,sBAA2C;;;cC/C9C,eAAA,YAA2B;;mBAGrB,sBAAsB;cAK3B;YAKF;WAID;YAIC;eAIG;cAKD;;;;
|
|
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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"}
|
package/dist/control.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { n as contractToMongoSchemaIR, t as verifyMongoSchema } from "./verify-mongo-schema-
|
|
2
|
-
import { a as dropCollection, n as createCollection, o as dropIndex, r as createIndex, t as collMod } from "./migration-factories-
|
|
1
|
+
import { n as contractToMongoSchemaIR, t as verifyMongoSchema } from "./verify-mongo-schema-Daa7BMJY.mjs";
|
|
2
|
+
import { a as dropCollection, n as createCollection, o as dropIndex, r as createIndex, t as collMod } from "./migration-factories-CoNYWrd1.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";
|
|
@@ -138,6 +138,31 @@ var FilterEvaluator = class {
|
|
|
138
138
|
//#region src/core/marker-ledger.ts
|
|
139
139
|
const COLLECTION = "_prisma_migrations";
|
|
140
140
|
const MARKER_ID = "marker";
|
|
141
|
+
const MongoMarkerDocSchema = type({
|
|
142
|
+
storageHash: "string",
|
|
143
|
+
profileHash: "string",
|
|
144
|
+
"contractJson?": "unknown | null",
|
|
145
|
+
"canonicalVersion?": "number | null",
|
|
146
|
+
"updatedAt?": "Date",
|
|
147
|
+
"appTag?": "string | null",
|
|
148
|
+
"meta?": type({ "[string]": "unknown" }).or("null"),
|
|
149
|
+
"invariants?": type("string").array(),
|
|
150
|
+
"+": "delete"
|
|
151
|
+
});
|
|
152
|
+
function parseMongoMarkerDoc(doc) {
|
|
153
|
+
const result = MongoMarkerDocSchema(doc);
|
|
154
|
+
if (result instanceof type.errors) throw new Error(`Invalid marker doc on ${COLLECTION}: ${result.summary}`);
|
|
155
|
+
return {
|
|
156
|
+
storageHash: result.storageHash,
|
|
157
|
+
profileHash: result.profileHash,
|
|
158
|
+
contractJson: result.contractJson ?? null,
|
|
159
|
+
canonicalVersion: result.canonicalVersion ?? null,
|
|
160
|
+
updatedAt: result.updatedAt ?? /* @__PURE__ */ new Date(),
|
|
161
|
+
appTag: result.appTag ?? null,
|
|
162
|
+
meta: result.meta ?? {},
|
|
163
|
+
invariants: result.invariants ?? []
|
|
164
|
+
};
|
|
165
|
+
}
|
|
141
166
|
async function executeAggregate(db, cmd) {
|
|
142
167
|
return db.collection(cmd.collection).aggregate(cmd.pipeline).toArray();
|
|
143
168
|
}
|
|
@@ -150,15 +175,7 @@ async function executeFindOneAndUpdate(db, cmd) {
|
|
|
150
175
|
async function readMarker(db) {
|
|
151
176
|
const doc = (await executeAggregate(db, new RawAggregateCommand(COLLECTION, [{ $match: { _id: MARKER_ID } }, { $limit: 1 }])))[0];
|
|
152
177
|
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
|
-
};
|
|
178
|
+
return parseMongoMarkerDoc(doc);
|
|
162
179
|
}
|
|
163
180
|
async function initMarker(db, destination) {
|
|
164
181
|
await executeInsertOne(db, new RawInsertOneCommand(COLLECTION, {
|
|
@@ -169,18 +186,36 @@ async function initMarker(db, destination) {
|
|
|
169
186
|
canonicalVersion: null,
|
|
170
187
|
updatedAt: /* @__PURE__ */ new Date(),
|
|
171
188
|
appTag: null,
|
|
172
|
-
meta: {}
|
|
189
|
+
meta: {},
|
|
190
|
+
invariants: destination.invariants ?? []
|
|
173
191
|
}));
|
|
174
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Updates the marker doc atomically (CAS on `expectedFrom`).
|
|
195
|
+
*
|
|
196
|
+
* `destination.invariants`:
|
|
197
|
+
* - `undefined` → existing field left untouched.
|
|
198
|
+
* - explicit value → merged into the existing field server-side via an
|
|
199
|
+
* aggregation pipeline (`$setUnion + $sortArray`), atomic at the
|
|
200
|
+
* document level. `[]` is a no-op merge.
|
|
201
|
+
*/
|
|
175
202
|
async function updateMarker(db, expectedFrom, destination) {
|
|
176
|
-
|
|
177
|
-
_id: MARKER_ID,
|
|
178
|
-
storageHash: expectedFrom
|
|
179
|
-
}, { $set: {
|
|
203
|
+
const setBase = {
|
|
180
204
|
storageHash: destination.storageHash,
|
|
181
205
|
profileHash: destination.profileHash,
|
|
182
206
|
updatedAt: /* @__PURE__ */ new Date()
|
|
183
|
-
}
|
|
207
|
+
};
|
|
208
|
+
const update = destination.invariants === void 0 ? { $set: setBase } : [{ $set: {
|
|
209
|
+
...setBase,
|
|
210
|
+
invariants: { $sortArray: {
|
|
211
|
+
input: { $setUnion: [{ $ifNull: ["$invariants", []] }, destination.invariants] },
|
|
212
|
+
sortBy: 1
|
|
213
|
+
} }
|
|
214
|
+
} }];
|
|
215
|
+
return await executeFindOneAndUpdate(db, new RawFindOneAndUpdateCommand(COLLECTION, {
|
|
216
|
+
_id: MARKER_ID,
|
|
217
|
+
storageHash: expectedFrom
|
|
218
|
+
}, update, false)) !== null;
|
|
184
219
|
}
|
|
185
220
|
async function writeLedgerEntry(db, entry) {
|
|
186
221
|
await executeInsertOne(db, new RawInsertOneCommand(COLLECTION, {
|
|
@@ -320,13 +355,9 @@ const QueryPlanJson = type({
|
|
|
320
355
|
target: "string",
|
|
321
356
|
storageHash: "string",
|
|
322
357
|
lane: "string",
|
|
323
|
-
paramDescriptors: "unknown[]",
|
|
324
358
|
"targetFamily?": "string",
|
|
325
359
|
"profileHash?": "string",
|
|
326
|
-
"annotations?": "Record<string, unknown>"
|
|
327
|
-
"refs?": "Record<string, unknown>",
|
|
328
|
-
"projection?": "Record<string, string> | string[]",
|
|
329
|
-
"projectionTypes?": "Record<string, string>"
|
|
360
|
+
"annotations?": "Record<string, unknown>"
|
|
330
361
|
})
|
|
331
362
|
});
|
|
332
363
|
const CheckJson = type({
|
|
@@ -490,13 +521,9 @@ function deserializeMongoQueryPlan(json) {
|
|
|
490
521
|
target: m.target,
|
|
491
522
|
storageHash: m.storageHash,
|
|
492
523
|
lane: m.lane,
|
|
493
|
-
paramDescriptors: m.paramDescriptors,
|
|
494
524
|
...ifDefined("targetFamily", m.targetFamily),
|
|
495
525
|
...ifDefined("profileHash", m.profileHash),
|
|
496
|
-
...ifDefined("annotations", m.annotations)
|
|
497
|
-
...ifDefined("refs", m.refs),
|
|
498
|
-
...ifDefined("projection", m.projection),
|
|
499
|
-
...ifDefined("projectionTypes", m.projectionTypes)
|
|
526
|
+
...ifDefined("annotations", m.annotations)
|
|
500
527
|
};
|
|
501
528
|
return {
|
|
502
529
|
collection: data.collection,
|
|
@@ -818,8 +845,8 @@ const BASE_IMPORTS = [{
|
|
|
818
845
|
* `Migration` (i.e. `MongoMigration`) from `@prisma-next/family-mongo`, and
|
|
819
846
|
* implements the abstract `operations` and `describe` members. `meta` is
|
|
820
847
|
* always rendered — `describe()` is part of the `Migration` contract, so
|
|
821
|
-
* even an empty stub must satisfy it; callers pass
|
|
822
|
-
* migration-new scaffold.
|
|
848
|
+
* even an empty stub must satisfy it; callers pass `from: null` for a
|
|
849
|
+
* baseline `migration-new` scaffold (and a real `to` hash either way).
|
|
823
850
|
*
|
|
824
851
|
* The walk is polymorphic: each call node contributes its own
|
|
825
852
|
* `renderTypeScript()` expression and declares its own
|
|
@@ -861,7 +888,6 @@ function buildDescribeMethod(meta) {
|
|
|
861
888
|
lines.push(" return {");
|
|
862
889
|
lines.push(` from: ${JSON.stringify(meta.from)},`);
|
|
863
890
|
lines.push(` to: ${JSON.stringify(meta.to)},`);
|
|
864
|
-
if (meta.kind) lines.push(` kind: ${JSON.stringify(meta.kind)},`);
|
|
865
891
|
if (meta.labels && meta.labels.length > 0) lines.push(` labels: ${jsonToTsSource(meta.labels)},`);
|
|
866
892
|
lines.push(" };");
|
|
867
893
|
lines.push(" }");
|
|
@@ -908,7 +934,6 @@ var PlannerProducedMongoMigration = class extends Migration {
|
|
|
908
934
|
return renderCallsToTypeScript(this.calls, {
|
|
909
935
|
from: this.meta.from,
|
|
910
936
|
to: this.meta.to,
|
|
911
|
-
...ifDefined("kind", this.meta.kind),
|
|
912
937
|
...ifDefined("labels", this.meta.labels)
|
|
913
938
|
});
|
|
914
939
|
}
|
|
@@ -1030,7 +1055,7 @@ var MongoMigrationPlanner = class {
|
|
|
1030
1055
|
return {
|
|
1031
1056
|
kind: "success",
|
|
1032
1057
|
plan: new PlannerProducedMongoMigration(result.calls, {
|
|
1033
|
-
from: options.
|
|
1058
|
+
from: options.fromContract?.storage.storageHash ?? null,
|
|
1034
1059
|
to: contract.storage.storageHash
|
|
1035
1060
|
})
|
|
1036
1061
|
};
|
|
@@ -1142,40 +1167,44 @@ var MongoMigrationRunner = class {
|
|
|
1142
1167
|
}
|
|
1143
1168
|
const destination = options.plan.destination;
|
|
1144
1169
|
const profileHash = options.destinationContract.profileHash ?? destination.storageHash;
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
if (
|
|
1170
|
+
const incomingInvariants = options.plan.providedInvariants ?? [];
|
|
1171
|
+
const existingInvariantSet = new Set(existingMarker?.invariants ?? []);
|
|
1172
|
+
const incomingIsSubsetOfExisting = incomingInvariants.every((id) => existingInvariantSet.has(id));
|
|
1173
|
+
const markerAlreadyAtDestination = existingMarker !== null && existingMarker.storageHash === destination.storageHash && existingMarker.profileHash === profileHash;
|
|
1174
|
+
if (!(operationsExecuted === 0 && markerAlreadyAtDestination && incomingIsSubsetOfExisting)) {
|
|
1175
|
+
const liveSchema = await this.deps.introspectSchema();
|
|
1176
|
+
const verifyResult = verifyMongoSchema({
|
|
1177
|
+
contract: options.destinationContract,
|
|
1178
|
+
schema: liveSchema,
|
|
1179
|
+
strict: options.strictVerification ?? true,
|
|
1180
|
+
frameworkComponents: options.frameworkComponents,
|
|
1181
|
+
...options.context ? { context: options.context } : {}
|
|
1182
|
+
});
|
|
1183
|
+
if (!verifyResult.ok) return runnerFailure("SCHEMA_VERIFY_FAILED", verifyResult.summary, {
|
|
1184
|
+
why: "The resulting database schema does not satisfy the destination contract.",
|
|
1185
|
+
meta: { issues: verifyResult.schema.issues }
|
|
1186
|
+
});
|
|
1187
|
+
if (existingMarker) {
|
|
1188
|
+
if (!await markerOps.updateMarker(existingMarker.storageHash, {
|
|
1189
|
+
storageHash: destination.storageHash,
|
|
1190
|
+
profileHash,
|
|
1191
|
+
invariants: incomingInvariants
|
|
1192
|
+
})) return runnerFailure("MARKER_CAS_FAILURE", "Marker was modified by another process during migration execution.", { meta: {
|
|
1193
|
+
expectedStorageHash: existingMarker.storageHash,
|
|
1194
|
+
destinationStorageHash: destination.storageHash
|
|
1195
|
+
} });
|
|
1196
|
+
} else await markerOps.initMarker({
|
|
1163
1197
|
storageHash: destination.storageHash,
|
|
1164
|
-
profileHash
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
await markerOps.writeLedgerEntry({
|
|
1175
|
-
edgeId: `${originHash}->${destination.storageHash}`,
|
|
1176
|
-
from: originHash,
|
|
1177
|
-
to: destination.storageHash
|
|
1178
|
-
});
|
|
1198
|
+
profileHash,
|
|
1199
|
+
invariants: incomingInvariants
|
|
1200
|
+
});
|
|
1201
|
+
const originHash = existingMarker?.storageHash ?? "";
|
|
1202
|
+
await markerOps.writeLedgerEntry({
|
|
1203
|
+
edgeId: `${originHash}->${destination.storageHash}`,
|
|
1204
|
+
from: originHash,
|
|
1205
|
+
to: destination.storageHash
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
1179
1208
|
return ok({
|
|
1180
1209
|
operationsPlanned: operations.length,
|
|
1181
1210
|
operationsExecuted
|
|
@@ -1195,7 +1224,7 @@ var MongoMigrationRunner = class {
|
|
|
1195
1224
|
};
|
|
1196
1225
|
}
|
|
1197
1226
|
for (const plan of op.run) {
|
|
1198
|
-
const wireCommand = adapter.lower(plan);
|
|
1227
|
+
const wireCommand = await adapter.lower(plan, {});
|
|
1199
1228
|
for await (const _ of driver.execute(wireCommand));
|
|
1200
1229
|
}
|
|
1201
1230
|
if (runPostchecks && op.postcheck.length > 0) {
|
|
@@ -1221,7 +1250,7 @@ var MongoMigrationRunner = class {
|
|
|
1221
1250
|
collection: check.source.collection
|
|
1222
1251
|
}
|
|
1223
1252
|
});
|
|
1224
|
-
const wireCommand = adapter.lower(check.source);
|
|
1253
|
+
const wireCommand = await adapter.lower(check.source, {});
|
|
1225
1254
|
let matchFound = false;
|
|
1226
1255
|
for await (const row of driver.execute(wireCommand)) if (filterEvaluator.evaluate(check.filter, row)) {
|
|
1227
1256
|
matchFound = true;
|
|
@@ -1254,10 +1283,7 @@ var MongoMigrationRunner = class {
|
|
|
1254
1283
|
}
|
|
1255
1284
|
ensureMarkerCompatibility(marker, plan) {
|
|
1256
1285
|
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
|
-
}
|
|
1286
|
+
if (!origin) return;
|
|
1261
1287
|
if (!marker) return runnerFailure("MARKER_ORIGIN_MISMATCH", `Missing contract marker: expected origin storage hash ${origin.storageHash}.`, { meta: { expectedOriginStorageHash: origin.storageHash } });
|
|
1262
1288
|
if (marker.storageHash !== origin.storageHash) return runnerFailure("MARKER_ORIGIN_MISMATCH", `Existing contract marker (${marker.storageHash}) does not match plan origin (${origin.storageHash}).`, { meta: {
|
|
1263
1289
|
markerStorageHash: marker.storageHash,
|