@prisma-next/target-mongo 0.4.0-dev.8 → 0.4.0-dev.9

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,5 +1,6 @@
1
1
  import { a as DropCollectionCall, c as OpFactoryCallVisitor, i as CreateIndexCall, l as schemaCollectionToCreateCollectionOptions, n as CollModMeta, o as DropIndexCall, r as CreateCollectionCall, s as OpFactoryCall, t as CollModCall, u as schemaIndexToCreateIndexOptions } from "./op-factory-call-CfPGebEH.mjs";
2
2
  import { MongoSchemaIR } from "@prisma-next/mongo-schema-ir";
3
+ import { MongoQueryPlan } from "@prisma-next/mongo-query-ast/execution";
3
4
  import { AnyMongoMigrationOperation, MongoAndExpr, MongoDdlCommandVisitor, MongoExistsExpr, MongoExprFilter, MongoFieldFilter, MongoFilterExpr, MongoFilterVisitor, MongoInspectionCommandVisitor, MongoMigrationPlanOperation, MongoNotExpr, MongoOrExpr } from "@prisma-next/mongo-query-ast/control";
4
5
  import { Migration, MigrationMeta } from "@prisma-next/migration-tools/migration";
5
6
  import { MongoContract } from "@prisma-next/mongo-contract";
@@ -7,6 +8,7 @@ import { MigrationOperationPolicy, MigrationPlan, MigrationPlanOperation, Migrat
7
8
  import { ContractMarkerRecord } from "@prisma-next/contract/types";
8
9
  import { Db } from "mongodb";
9
10
  import { TargetBoundComponentDescriptor } from "@prisma-next/framework-components/components";
11
+ import { MongoAdapter, MongoDriver } from "@prisma-next/mongo-lowering";
10
12
 
11
13
  //#region src/core/contract-to-schema.d.ts
12
14
  declare function contractToMongoSchemaIR(contract: MongoContract | null): MongoSchemaIR;
@@ -43,9 +45,9 @@ declare function writeLedgerEntry(db: Db, entry: {
43
45
  }): Promise<void>;
44
46
  //#endregion
45
47
  //#region src/core/mongo-ops-serializer.d.ts
46
- declare function deserializeMongoOp(json: unknown): MongoMigrationPlanOperation;
47
- declare function deserializeMongoOps(json: readonly unknown[]): MongoMigrationPlanOperation[];
48
- declare function serializeMongoOps(ops: readonly MongoMigrationPlanOperation[]): string;
48
+ declare function deserializeMongoOp(json: unknown): AnyMongoMigrationOperation;
49
+ declare function deserializeMongoOps(json: readonly unknown[]): AnyMongoMigrationOperation[];
50
+ declare function serializeMongoOps(ops: readonly AnyMongoMigrationOperation[]): string;
49
51
  //#endregion
50
52
  //#region src/core/mongo-planner.d.ts
51
53
  type PlanCallsResult = {
@@ -102,6 +104,8 @@ interface MarkerOperations {
102
104
  interface MongoRunnerDependencies {
103
105
  readonly commandExecutor: MongoDdlCommandVisitor<Promise<void>>;
104
106
  readonly inspectionExecutor: MongoInspectionCommandVisitor<Promise<Record<string, unknown>[]>>;
107
+ readonly adapter: MongoAdapter;
108
+ readonly driver: MongoDriver;
105
109
  readonly markerOps: MarkerOperations;
106
110
  }
107
111
  declare class MongoMigrationRunner {
@@ -118,6 +122,8 @@ declare class MongoMigrationRunner {
118
122
  readonly executionChecks?: MigrationRunnerExecutionChecks;
119
123
  readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'mongo', 'mongo'>>;
120
124
  }): Promise<MigrationRunnerResult>;
125
+ private executeDataTransform;
126
+ private evaluateDataTransformChecks;
121
127
  private evaluateChecks;
122
128
  private allChecksSatisfied;
123
129
  private enforcePolicyCompatibility;
@@ -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;;;;iBCjDQ,UAAA,KAAe,KAAK,QAAQ;iBAgB5B,UAAA,KAChB;;;IAEH;iBAcmB,YAAA,KAChB;;;IAGH;AHhBa,iBGiCM,gBAAA,CHjCiB,EAAW,EGkC5C,EHlC4C,EAAA,KAAA,EAAA;;;;AC6ClD,CAAA,CAAA,EETG,OFSa,CAAA,IAAA,CAAA;;;iBGiKA,kBAAA,iBAAmC;iBAYnC,mBAAA,4BAA+C;iBAI/C,iBAAA,eAAgC;;;KC9KpC,eAAA;;kBACoC;;;sBACI;;cAEvC,qBAAA,YAAiC;ELpD9B,SAAA,CAAA,OAAA,EAAA;;;qBKwDK;IJXL,SAAA,mBAAqB,EIYH,aJZyB,CIYX,8BJZiC,CAAA,OAAA,EAAA,OAAA,CAAA,CAAA;MIa3E;;;IH5DO,SAAA,MAAgB,EAAA,OAAA;IAGV,SAAA,MAAA,EG6KE,wBH7KF;IAAsB,SAAA,QAAA,EAAA,MAAA;IAK3B,SAAA,mBAAA,EG0KoB,aH1KpB,CG0KkC,8BH1KlC,CAAA,OAAA,EAAA,OAAA,CAAA,CAAA;EAKF,CAAA,CAAA,EGsKN,sBHtKM;EAID;;;;;;;;;ACpCX;EAAqC,cAAA,CAAA,OAAA,EE6NX,wBF7NW,CAAA,EE6NgB,iCF7NhB;;;;UGXpB,gBAAA;gBACD,QAAQ;;;;MAIlB;;IN2BU,SAAA,WAAA,EAAuB,MAAA;;MMvBlC;;ILoEW,SAAA,MAAA,EAAA,MAAqB;;;MK/D/B;AJgBN;AAGmB,UIhBF,uBAAA,CJgBE;EAAsB,SAAA,eAAA,EIfb,sBJea,CIfU,OJeV,CAAA,IAAA,CAAA,CAAA;EAK3B,SAAA,kBAAA,EInBiB,6BJmBjB,CInB+C,OJmB/C,CInBuD,MJmBvD,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,CAAA,CAAA;EAKF,SAAA,SAAA,EIvBU,gBJuBV;;AAQA,cIhBC,oBAAA,CJgBD;EAIG,iBAAA,IAAA;EAKD,WAAA,CAAA,IAAA,EIxBuB,uBJwBvB;EA9B0B,OAAA,CAAA,OAAA,EAAA;IAAkB,SAAA,IAAA,EISvC,aJTuC;;qBIWrC;;MH9BC,gBAAU,EAAA,EAAA,EGgCJ,sBHhCI,CAAA,EAAA,IAAA;MAAK,mBAAA,EAAA,EAAA,EGiCN,sBHjCM,CAAA,EAAA,IAAA;IAAa,CAAA;IAAR,SAAA,eAAA,CAAA,EGmCX,8BHnCW;IAAO,SAAA,mBAAA,EGoCf,aHpCe,CGoCD,8BHpCC,CAAA,OAAA,EAAA,OAAA,CAAA,CAAA;EAgB3B,CAAA,CAAA,EGqBhB,OHrBgB,CGqBR,qBHlBX,CAAA;EAcmB,QAAA,cAAY;EAqBZ,QAAA,kBAAgB;;;;;;;;;;;;;AHjCtC;;;;AC6CA;;;;AC/CA;AAGmB,cK7BN,6BAAA,SACH,SL4BS,CK5BC,0BL4BD,CAAA,YK3BN,iCL2BM,CAAA;EAAsB,iBAAA,KAAA;EAK3B,iBAAA,IAAA;EAKF,SAAA,QAAA,EAAA,OAAA;EAID,WAAA,CAAA,KAAA,EAAA,SKpC0B,aLoC1B,EAAA,EAAA,IAAA,EKnCgB,aLmChB;EAIC,IAAA,UAAA,CAAA,CAAA,EAAA,SKlC0B,0BLkC1B,EAAA;EAIG,QAAA,CAAA,CAAA,EKlCQ,aLkCR;EAKD,gBAAA,CAAA,CAAA,EAAA,MAAA;;;;iBM5CE,SAAA,QAAiB,cAAc,iBAAiB;;;UCzB/C,mBAAA;;;;;;;;;;ATyCjB;;;;AC6CA;iBQtEgB,uBAAA,QACP,cAAc,sBACf"}
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;;;;iBCjDQ,UAAA,KAAe,KAAK,QAAQ;iBAgB5B,UAAA,KAChB;;;IAEH;iBAcmB,YAAA,KAChB;;;IAGH;iBAiBmB,gBAAA,KAChB;;EHlCU,SAAA,IAAA,EAAA,MAAA;;IGoCb;;;iBC8ea,kBAAA,iBAAmC;iBAOnC,mBAAA,4BAA+C;iBAI/C,iBAAA,eAAgC;;;KC7epC,eAAA;;kBACoC;;;sBACI;;cAEvC,qBAAA,YAAiC;;;ILpD9B,SAAA,MAAA,EAAA,OAAuB;qBKwDlB;kCACa,cAAc;MAC1C;EJbU,IAAA,CAAA,OAAA,EAAA;;;qBIiIK;IHhLR,SAAA,QAAgB,EAAA,MAAA;IAGV,SAAA,mBAAA,EG+Ke,aH/Kf,CG+K6B,8BH/K7B,CAAA,OAAA,EAAA,OAAA,CAAA,CAAA;EAAsB,CAAA,CAAA,EGgLnC,sBHhLmC;EAK3B;;;;;;;;;;0BGkMY,2BAA2B;AF7NrD;;;UGMiB,gBAAA;gBACD,QAAQ;;;;MAIlB;;;INUU,SAAA,WAAA,EAAuB,MAAA;MMNlC;;;ILmDW,SAAA,IAAA,EAAA,MAAqB;;MK9C/B;;AJDO,UIII,uBAAA,CJJY;EAGV,SAAA,eAAA,EIES,sBJFT,CIEgC,OJFhC,CAAA,IAAA,CAAA,CAAA;EAAsB,SAAA,kBAAA,EIGV,6BJHU,CIGoB,OJHpB,CIG4B,MJH5B,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,CAAA,CAAA;EAK3B,SAAA,OAAA,EIDM,YJCN;EAKF,SAAA,MAAA,EILO,WJKP;EAID,SAAA,SAAA,EIRW,gBJQX;;AAQI,cIDF,oBAAA,CJCE;EAKD,iBAAA,IAAA;EA9B0B,WAAA,CAAA,IAAA,EIyBH,uBJzBG;EAAkB,OAAA,CAAA,OAAA,EAAA;mBI4BvC;;qBAEE;IHjDC,SAAU,SAAA,CAAA,EAAA;MAAK,gBAAA,EAAA,EAAA,EGmDT,sBHnDS,CAAA,EAAA,IAAA;MAAa,mBAAA,EAAA,EAAA,EGoDnB,sBHpDmB,CAAA,EAAA,IAAA;IAAR,CAAA;IAAO,SAAA,eAAA,CAAA,EGsDlB,8BHtDkB;IAgB3B,SAAU,mBAG7B,EGoC+B,aHpCxB,CGoCsC,8BHpCtC,CAAA,OAAA,EAAA,OAAA,CAAA,CAAA;EAcY,CAAA,CAAA,EGuBhB,OHvBgB,CGuBR,qBHnBX,CAAA;EAiBmB,QAAA,oBAAgB;;;;ECiftB,QAAA,0BAAmC;EAOnC,QAAA,yBAAmB;AAInC;;;;;;;;;;;;AJ7hBA;;;;AC6CA;;;cMzEa,6BAAA,SACH,UAAU,uCACP;ELwBA,iBAAA,KAAgB;EAGV,iBAAA,IAAA;EAAsB,SAAA,QAAA,EAAA,OAAA;EAK3B,WAAA,CAAA,KAAA,EAAA,SK3BuB,aL2BvB,EAAA,EAAA,IAAA,EK1Ba,aL0Bb;EAKF,IAAA,UAAA,CAAA,CAAA,EAAA,SK1B0B,0BL0B1B,EAAA;EAID,QAAA,CAAA,CAAA,EK1BY,aL0BZ;EAIC,gBAAA,CAAA,CAAA,EAAA,MAAA;;;;iBMnCI,SAAA,QAAiB,cAAc,iBAAiB;;;UCzB/C,mBAAA;;;;;;;;;;;;ATyCjB;;;iBSzBgB,uBAAA,QACP,cAAc,sBACf"}
package/dist/control.mjs CHANGED
@@ -1,11 +1,12 @@
1
- import { a as dropIndex, i as dropCollection, n as createCollection, r as createIndex, t as collMod } from "./migration-factories-Brzz-QGG.mjs";
1
+ import { a as dropCollection, n as createCollection, o as dropIndex, r as createIndex, t as collMod } from "./migration-factories-gwi81C8u.mjs";
2
2
  import { MongoSchemaCollection, MongoSchemaCollectionOptions, MongoSchemaIR, MongoSchemaIndex, MongoSchemaValidator, canonicalize, deepEqual } from "@prisma-next/mongo-schema-ir";
3
- import { RawAggregateCommand, RawFindOneAndUpdateCommand, RawInsertOneCommand } from "@prisma-next/mongo-query-ast/execution";
3
+ 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";
4
4
  import { CollModCommand, CreateCollectionCommand, CreateIndexCommand, DropCollectionCommand, DropIndexCommand, ListCollectionsCommand, ListIndexesCommand, MongoAndExpr, MongoExistsExpr, MongoFieldFilter, MongoNotExpr, MongoOrExpr } from "@prisma-next/mongo-query-ast/control";
5
+ import { ifDefined } from "@prisma-next/utils/defined";
5
6
  import { type } from "arktype";
6
7
  import { Migration } from "@prisma-next/migration-tools/migration";
7
- import { ifDefined } from "@prisma-next/utils/defined";
8
8
  import { detectScaffoldRuntime, shebangLineFor } from "@prisma-next/migration-tools/migration-ts";
9
+ import { errorRunnerFailed } from "@prisma-next/errors/execution";
9
10
  import { notOk, ok } from "@prisma-next/utils/result";
10
11
 
11
12
  //#region src/core/contract-to-schema.ts
@@ -295,6 +296,76 @@ const ExistsFilterJson = type({
295
296
  field: "string",
296
297
  exists: "boolean"
297
298
  });
299
+ const RawInsertOneJson = type({
300
+ kind: "\"rawInsertOne\"",
301
+ collection: "string",
302
+ document: "Record<string, unknown>"
303
+ });
304
+ const RawInsertManyJson = type({
305
+ kind: "\"rawInsertMany\"",
306
+ collection: "string",
307
+ documents: "Record<string, unknown>[]"
308
+ });
309
+ const RawUpdateOneJson = type({
310
+ kind: "\"rawUpdateOne\"",
311
+ collection: "string",
312
+ filter: "Record<string, unknown>",
313
+ update: "Record<string, unknown> | Record<string, unknown>[]"
314
+ });
315
+ const RawUpdateManyJson = type({
316
+ kind: "\"rawUpdateMany\"",
317
+ collection: "string",
318
+ filter: "Record<string, unknown>",
319
+ update: "Record<string, unknown> | Record<string, unknown>[]"
320
+ });
321
+ const RawDeleteOneJson = type({
322
+ kind: "\"rawDeleteOne\"",
323
+ collection: "string",
324
+ filter: "Record<string, unknown>"
325
+ });
326
+ const RawDeleteManyJson = type({
327
+ kind: "\"rawDeleteMany\"",
328
+ collection: "string",
329
+ filter: "Record<string, unknown>"
330
+ });
331
+ const RawAggregateJson = type({
332
+ kind: "\"rawAggregate\"",
333
+ collection: "string",
334
+ pipeline: "Record<string, unknown>[]"
335
+ });
336
+ const RawFindOneAndUpdateJson = type({
337
+ kind: "\"rawFindOneAndUpdate\"",
338
+ collection: "string",
339
+ filter: "Record<string, unknown>",
340
+ update: "Record<string, unknown> | Record<string, unknown>[]",
341
+ upsert: "boolean"
342
+ });
343
+ const RawFindOneAndDeleteJson = type({
344
+ kind: "\"rawFindOneAndDelete\"",
345
+ collection: "string",
346
+ filter: "Record<string, unknown>"
347
+ });
348
+ const TypedAggregateJson = type({
349
+ kind: "\"aggregate\"",
350
+ collection: "string",
351
+ pipeline: "Record<string, unknown>[]"
352
+ });
353
+ const QueryPlanJson = type({
354
+ collection: "string",
355
+ command: "Record<string, unknown>",
356
+ meta: type({
357
+ target: "string",
358
+ storageHash: "string",
359
+ lane: "string",
360
+ paramDescriptors: "unknown[]",
361
+ "targetFamily?": "string",
362
+ "profileHash?": "string",
363
+ "annotations?": "Record<string, unknown>",
364
+ "refs?": "Record<string, unknown>",
365
+ "projection?": "Record<string, string> | string[]",
366
+ "projectionTypes?": "Record<string, string>"
367
+ })
368
+ });
298
369
  const CheckJson = type({
299
370
  description: "string",
300
371
  source: "Record<string, unknown>",
@@ -305,7 +376,7 @@ const StepJson = type({
305
376
  description: "string",
306
377
  command: "Record<string, unknown>"
307
378
  });
308
- const OperationJson = type({
379
+ const DdlOperationJson = type({
309
380
  id: "string",
310
381
  label: "string",
311
382
  operationClass: "\"additive\" | \"widening\" | \"destructive\"",
@@ -313,6 +384,21 @@ const OperationJson = type({
313
384
  execute: "Record<string, unknown>[]",
314
385
  postcheck: "Record<string, unknown>[]"
315
386
  });
387
+ const DataTransformCheckJson = type({
388
+ description: "string",
389
+ source: "Record<string, unknown>",
390
+ filter: "Record<string, unknown>",
391
+ expect: "\"exists\" | \"notExists\""
392
+ });
393
+ const DataTransformOperationJson = type({
394
+ id: "string",
395
+ label: "string",
396
+ operationClass: "\"data\"",
397
+ name: "string",
398
+ precheck: "Record<string, unknown>[]",
399
+ run: "Record<string, unknown>[]",
400
+ postcheck: "Record<string, unknown>[]"
401
+ });
316
402
  function validate(schema, data, context) {
317
403
  try {
318
404
  return schema.assert(data);
@@ -353,6 +439,108 @@ function deserializeFilterExpr(json) {
353
439
  default: throw new Error(`Unknown filter expression kind: ${kind}`);
354
440
  }
355
441
  }
442
+ function deserializePipelineStage(json) {
443
+ const record = json;
444
+ const kind = record["kind"];
445
+ switch (kind) {
446
+ case "match": return new MongoMatchStage(deserializeFilterExpr(record["filter"]));
447
+ case "limit": return new MongoLimitStage(record["limit"]);
448
+ case "sort": return new MongoSortStage(record["sort"]);
449
+ case "project": return new MongoProjectStage(record["projection"]);
450
+ case "addFields": return new MongoAddFieldsStage(record["fields"]);
451
+ case "lookup": {
452
+ const opts = {
453
+ from: record["from"],
454
+ as: record["as"]
455
+ };
456
+ if (record["localField"] !== void 0) opts.localField = record["localField"];
457
+ if (record["foreignField"] !== void 0) opts.foreignField = record["foreignField"];
458
+ if (record["pipeline"] !== void 0) opts.pipeline = record["pipeline"].map(deserializePipelineStage);
459
+ if (record["let_"] !== void 0) opts.let_ = record["let_"];
460
+ return new MongoLookupStage(opts);
461
+ }
462
+ case "merge": {
463
+ const opts = { into: record["into"] };
464
+ if (record["on"] !== void 0) opts.on = record["on"];
465
+ if (record["whenMatched"] !== void 0) {
466
+ const wm = record["whenMatched"];
467
+ opts.whenMatched = typeof wm === "string" ? wm : wm.map(deserializePipelineStage);
468
+ }
469
+ if (record["whenNotMatched"] !== void 0) opts.whenNotMatched = record["whenNotMatched"];
470
+ return new MongoMergeStage(opts);
471
+ }
472
+ default: throw new Error(`Unknown pipeline stage kind: ${kind}`);
473
+ }
474
+ }
475
+ function deserializeDmlCommand(json) {
476
+ const kind = json["kind"];
477
+ switch (kind) {
478
+ case "rawInsertOne": {
479
+ const data = validate(RawInsertOneJson, json, "rawInsertOne command");
480
+ return new RawInsertOneCommand(data.collection, data.document);
481
+ }
482
+ case "rawInsertMany": {
483
+ const data = validate(RawInsertManyJson, json, "rawInsertMany command");
484
+ return new RawInsertManyCommand(data.collection, data.documents);
485
+ }
486
+ case "rawUpdateOne": {
487
+ const data = validate(RawUpdateOneJson, json, "rawUpdateOne command");
488
+ return new RawUpdateOneCommand(data.collection, data.filter, data.update);
489
+ }
490
+ case "rawUpdateMany": {
491
+ const data = validate(RawUpdateManyJson, json, "rawUpdateMany command");
492
+ return new RawUpdateManyCommand(data.collection, data.filter, data.update);
493
+ }
494
+ case "rawDeleteOne": {
495
+ const data = validate(RawDeleteOneJson, json, "rawDeleteOne command");
496
+ return new RawDeleteOneCommand(data.collection, data.filter);
497
+ }
498
+ case "rawDeleteMany": {
499
+ const data = validate(RawDeleteManyJson, json, "rawDeleteMany command");
500
+ return new RawDeleteManyCommand(data.collection, data.filter);
501
+ }
502
+ case "rawAggregate": {
503
+ const data = validate(RawAggregateJson, json, "rawAggregate command");
504
+ return new RawAggregateCommand(data.collection, data.pipeline);
505
+ }
506
+ case "rawFindOneAndUpdate": {
507
+ const data = validate(RawFindOneAndUpdateJson, json, "rawFindOneAndUpdate command");
508
+ return new RawFindOneAndUpdateCommand(data.collection, data.filter, data.update, data.upsert);
509
+ }
510
+ case "rawFindOneAndDelete": {
511
+ const data = validate(RawFindOneAndDeleteJson, json, "rawFindOneAndDelete command");
512
+ return new RawFindOneAndDeleteCommand(data.collection, data.filter);
513
+ }
514
+ case "aggregate": {
515
+ const data = validate(TypedAggregateJson, json, "aggregate command");
516
+ const pipeline = data.pipeline.map(deserializePipelineStage);
517
+ return new AggregateCommand(data.collection, pipeline);
518
+ }
519
+ default: throw new Error(`Unknown DML command kind: ${kind}`);
520
+ }
521
+ }
522
+ function deserializeMongoQueryPlan(json) {
523
+ const data = validate(QueryPlanJson, json, "Mongo query plan");
524
+ const command = deserializeDmlCommand(data.command);
525
+ const m = data.meta;
526
+ const meta = {
527
+ target: m.target,
528
+ storageHash: m.storageHash,
529
+ lane: m.lane,
530
+ paramDescriptors: m.paramDescriptors,
531
+ ...ifDefined("targetFamily", m.targetFamily),
532
+ ...ifDefined("profileHash", m.profileHash),
533
+ ...ifDefined("annotations", m.annotations),
534
+ ...ifDefined("refs", m.refs),
535
+ ...ifDefined("projection", m.projection),
536
+ ...ifDefined("projectionTypes", m.projectionTypes)
537
+ };
538
+ return {
539
+ collection: data.collection,
540
+ command,
541
+ meta
542
+ };
543
+ }
356
544
  function deserializeDdlCommand(json) {
357
545
  const kind = json["kind"];
358
546
  switch (kind) {
@@ -429,8 +617,11 @@ function deserializeStep(json) {
429
617
  command: deserializeDdlCommand(data.command)
430
618
  };
431
619
  }
432
- function deserializeMongoOp(json) {
433
- const data = validate(OperationJson, json, "migration operation");
620
+ function isDataTransformJson(json) {
621
+ return typeof json === "object" && json !== null && json["operationClass"] === "data";
622
+ }
623
+ function deserializeDdlOp(json) {
624
+ const data = validate(DdlOperationJson, json, "migration operation");
434
625
  return {
435
626
  id: data.id,
436
627
  label: data.label,
@@ -440,6 +631,31 @@ function deserializeMongoOp(json) {
440
631
  postcheck: data.postcheck.map(deserializeCheck)
441
632
  };
442
633
  }
634
+ function deserializeDataTransformCheck(json) {
635
+ const data = validate(DataTransformCheckJson, json, "data transform check");
636
+ return {
637
+ description: data.description,
638
+ source: deserializeMongoQueryPlan(data.source),
639
+ filter: deserializeFilterExpr(data.filter),
640
+ expect: data.expect
641
+ };
642
+ }
643
+ function deserializeDataTransformOp(json) {
644
+ const data = validate(DataTransformOperationJson, json, "data transform operation");
645
+ return {
646
+ id: data.id,
647
+ label: data.label,
648
+ operationClass: "data",
649
+ name: data.name,
650
+ precheck: data.precheck.map(deserializeDataTransformCheck),
651
+ run: data.run.map(deserializeMongoQueryPlan),
652
+ postcheck: data.postcheck.map(deserializeDataTransformCheck)
653
+ };
654
+ }
655
+ function deserializeMongoOp(json) {
656
+ if (isDataTransformJson(json)) return deserializeDataTransformOp(json);
657
+ return deserializeDdlOp(json);
658
+ }
443
659
  function deserializeMongoOps(json) {
444
660
  return json.map(deserializeMongoOp);
445
661
  }
@@ -923,6 +1139,10 @@ function planMutableOptionsDiffCall(collName, origin, dest) {
923
1139
 
924
1140
  //#endregion
925
1141
  //#region src/core/mongo-runner.ts
1142
+ const READ_ONLY_CHECK_COMMAND_KINDS = new Set(["aggregate", "rawAggregate"]);
1143
+ function hasProfileHash(value) {
1144
+ return typeof value === "object" && value !== null && Object.hasOwn(value, "profileHash") && typeof value.profileHash === "string";
1145
+ }
926
1146
  function runnerFailure(code, summary, opts) {
927
1147
  return notOk({
928
1148
  code,
@@ -935,7 +1155,7 @@ var MongoMigrationRunner = class {
935
1155
  this.deps = deps;
936
1156
  }
937
1157
  async execute(options) {
938
- const { commandExecutor, inspectionExecutor, markerOps } = this.deps;
1158
+ const { commandExecutor, inspectionExecutor, adapter, driver, markerOps } = this.deps;
939
1159
  const operations = deserializeMongoOps(options.plan.operations);
940
1160
  const policyCheck = this.enforcePolicyCompatibility(options.policy, operations);
941
1161
  if (policyCheck) return policyCheck;
@@ -951,15 +1171,22 @@ var MongoMigrationRunner = class {
951
1171
  for (const operation of operations) {
952
1172
  options.callbacks?.onOperationStart?.(operation);
953
1173
  try {
1174
+ if (operation.operationClass === "data") {
1175
+ const result = await this.executeDataTransform(operation, adapter, driver, filterEvaluator, runIdempotency, runPrechecks, runPostchecks);
1176
+ if (result.failure) return result.failure;
1177
+ if (result.executed) operationsExecuted += 1;
1178
+ continue;
1179
+ }
1180
+ const ddlOp = operation;
954
1181
  if (runPostchecks && runIdempotency) {
955
- if (await this.allChecksSatisfied(operation.postcheck, inspectionExecutor, filterEvaluator)) continue;
1182
+ if (await this.allChecksSatisfied(ddlOp.postcheck, inspectionExecutor, filterEvaluator)) continue;
956
1183
  }
957
1184
  if (runPrechecks) {
958
- if (!await this.evaluateChecks(operation.precheck, inspectionExecutor, filterEvaluator)) return runnerFailure("PRECHECK_FAILED", `Operation ${operation.id} failed during precheck`, { meta: { operationId: operation.id } });
1185
+ if (!await this.evaluateChecks(ddlOp.precheck, inspectionExecutor, filterEvaluator)) return runnerFailure("PRECHECK_FAILED", `Operation ${operation.id} failed during precheck`, { meta: { operationId: operation.id } });
959
1186
  }
960
- for (const step of operation.execute) await step.command.accept(commandExecutor);
1187
+ for (const step of ddlOp.execute) await step.command.accept(commandExecutor);
961
1188
  if (runPostchecks) {
962
- if (!await this.evaluateChecks(operation.postcheck, inspectionExecutor, filterEvaluator)) return runnerFailure("POSTCHECK_FAILED", `Operation ${operation.id} failed during postcheck`, { meta: { operationId: operation.id } });
1189
+ if (!await this.evaluateChecks(ddlOp.postcheck, inspectionExecutor, filterEvaluator)) return runnerFailure("POSTCHECK_FAILED", `Operation ${operation.id} failed during postcheck`, { meta: { operationId: operation.id } });
963
1190
  }
964
1191
  operationsExecuted += 1;
965
1192
  } finally {
@@ -967,7 +1194,7 @@ var MongoMigrationRunner = class {
967
1194
  }
968
1195
  }
969
1196
  const destination = options.plan.destination;
970
- const profileHash = options.destinationContract.profileHash ?? destination.storageHash;
1197
+ const profileHash = hasProfileHash(options.destinationContract) ? options.destinationContract.profileHash : destination.storageHash;
971
1198
  if (operationsExecuted === 0 && existingMarker?.storageHash === destination.storageHash && existingMarker.profileHash === profileHash) return ok({
972
1199
  operationsPlanned: operations.length,
973
1200
  operationsExecuted
@@ -995,6 +1222,56 @@ var MongoMigrationRunner = class {
995
1222
  operationsExecuted
996
1223
  });
997
1224
  }
1225
+ async executeDataTransform(op, adapter, driver, filterEvaluator, runIdempotency, runPrechecks, runPostchecks) {
1226
+ if (runPostchecks && runIdempotency && op.postcheck.length > 0) {
1227
+ if (await this.evaluateDataTransformChecks(op.postcheck, adapter, driver, filterEvaluator)) return { executed: false };
1228
+ }
1229
+ if (runPrechecks && op.precheck.length > 0) {
1230
+ if (!await this.evaluateDataTransformChecks(op.precheck, adapter, driver, filterEvaluator)) return {
1231
+ executed: false,
1232
+ failure: runnerFailure("PRECHECK_FAILED", `Operation ${op.id} failed during precheck`, { meta: {
1233
+ operationId: op.id,
1234
+ name: op.name
1235
+ } })
1236
+ };
1237
+ }
1238
+ for (const plan of op.run) {
1239
+ const wireCommand = adapter.lower(plan);
1240
+ for await (const _ of driver.execute(wireCommand));
1241
+ }
1242
+ if (runPostchecks && op.postcheck.length > 0) {
1243
+ if (!await this.evaluateDataTransformChecks(op.postcheck, adapter, driver, filterEvaluator)) return {
1244
+ executed: false,
1245
+ failure: runnerFailure("POSTCHECK_FAILED", `Operation ${op.id} failed during postcheck`, { meta: {
1246
+ operationId: op.id,
1247
+ name: op.name
1248
+ } })
1249
+ };
1250
+ }
1251
+ return { executed: true };
1252
+ }
1253
+ async evaluateDataTransformChecks(checks, adapter, driver, filterEvaluator) {
1254
+ for (const check of checks) {
1255
+ const commandKind = check.source.command.kind;
1256
+ if (!READ_ONLY_CHECK_COMMAND_KINDS.has(commandKind)) throw errorRunnerFailed(`Data-transform check rejected: command kind "${commandKind}" is not read-only`, {
1257
+ why: "Data-transform checks must use aggregate or rawAggregate commands so the pre/postcheck path cannot mutate the database.",
1258
+ fix: "Author the check.source as an aggregate pipeline (or rawAggregate) rather than a DML write command.",
1259
+ meta: {
1260
+ checkDescription: check.description,
1261
+ commandKind,
1262
+ collection: check.source.collection
1263
+ }
1264
+ });
1265
+ const wireCommand = adapter.lower(check.source);
1266
+ let matchFound = false;
1267
+ for await (const row of driver.execute(wireCommand)) if (filterEvaluator.evaluate(check.filter, row)) {
1268
+ matchFound = true;
1269
+ break;
1270
+ }
1271
+ if (!(check.expect === "exists" ? matchFound : !matchFound)) return false;
1272
+ }
1273
+ return true;
1274
+ }
998
1275
  async evaluateChecks(checks, inspectionExecutor, filterEvaluator) {
999
1276
  for (const check of checks) {
1000
1277
  const matchFound = (await check.source.accept(inspectionExecutor)).some((doc) => filterEvaluator.evaluate(check.filter, doc));