@prisma-next/adapter-mongo 0.12.0-dev.50 → 0.12.0-dev.52

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.
@@ -2,9 +2,9 @@ import { t as createMongoAdapter } from "./mongo-adapter-JuKx_-h9.mjs";
2
2
  import { Db, Document } from "mongodb";
3
3
  import { CollModCommand, CreateCollectionCommand, CreateIndexCommand, DropCollectionCommand, DropIndexCommand, ListCollectionsCommand, ListIndexesCommand, MongoDdlCommandVisitor, MongoInspectionCommandVisitor } from "@prisma-next/mongo-query-ast/control";
4
4
  import { MongoSchemaIR } from "@prisma-next/mongo-schema-ir";
5
- import { ContractMarkerRecord, LedgerEntryRecord } from "@prisma-next/contract/types";
6
5
  import { MongoControlAdapter, MongoControlAdapterDescriptor } from "@prisma-next/family-mongo/control-adapter";
7
6
  import { MongoAdapter, MongoControlDriverInstance, MongoControlDriverInstance as MongoControlDriverInstance$1, MongoDriver } from "@prisma-next/mongo-lowering";
7
+ import { ContractMarkerRecord, LedgerEntryRecord } from "@prisma-next/contract/types";
8
8
  import { ControlDriverInstance, ControlFamilyInstance } from "@prisma-next/framework-components/control";
9
9
 
10
10
  //#region src/core/command-executor.d.ts
@@ -31,10 +31,14 @@ declare function introspectSchema(db: Db): Promise<MongoSchemaIR>;
31
31
  /**
32
32
  * Mongo control adapter for control-plane operations like introspection
33
33
  * and marker-ledger CAS. Implements the family-level `MongoControlAdapter`
34
- * SPI by extracting the underlying `Db` from the framework-shaped driver
35
- * per call.
34
+ * SPI. Every marker/ledger operation builds a canonical command inline via
35
+ * the contract-free fluent builder and dispatches it through the family
36
+ * adapter's lowering path (`createMongoAdapter().lower(plan, {})`) onto the
37
+ * Mongo wire transport (`driver.execute(wireCommand)`) — the same route SQL
38
+ * marker/ledger ops take through `adapter.lower()` → `driver.query()`.
36
39
  */
37
40
  declare class MongoControlAdapterImpl implements MongoControlAdapter<'mongo'> {
41
+ #private;
38
42
  readonly familyId: "mongo";
39
43
  readonly targetId: "mongo";
40
44
  readMarker(driver: ControlDriverInstance<'mongo', 'mongo'>, space: string): Promise<ContractMarkerRecord | null>;
@@ -113,28 +117,7 @@ interface MongoRunnerDependencies {
113
117
  declare function createMongoRunnerDeps(controlDriver: ControlDriverInstance<'mongo', 'mongo'>, driver: MongoDriver, _family: ControlFamilyInstance<'mongo', MongoSchemaIR>, controlAdapter?: MongoControlAdapter<'mongo'>): MongoRunnerDependencies;
114
118
  //#endregion
115
119
  //#region src/exports/control.d.ts
116
- declare function readMarker(db: Db, space: string): Promise<ContractMarkerRecord | null>;
117
- declare function readAllMarkers(db: Db): Promise<ReadonlyMap<string, ContractMarkerRecord>>;
118
- declare function initMarker(db: Db, space: string, destination: {
119
- readonly storageHash: string;
120
- readonly profileHash: string;
121
- readonly invariants?: readonly string[];
122
- }): Promise<void>;
123
- declare function updateMarker(db: Db, space: string, expectedFrom: string, destination: {
124
- readonly storageHash: string;
125
- readonly profileHash: string;
126
- readonly invariants?: readonly string[];
127
- }): Promise<boolean>;
128
- declare function readLedger(db: Db, space?: string): Promise<readonly LedgerEntryRecord[]>;
129
- declare function writeLedgerEntry(db: Db, space: string, entry: {
130
- readonly edgeId: string;
131
- readonly from: string;
132
- readonly to: string;
133
- readonly migrationName: string;
134
- readonly migrationHash: string;
135
- readonly operations: readonly unknown[];
136
- }): Promise<void>;
137
120
  declare const mongoAdapterDescriptor: MongoControlAdapterDescriptor<'mongo'>;
138
121
  //#endregion
139
- export { type MarkerOperations, MongoCommandExecutor, MongoControlAdapterImpl, type MongoControlDriverInstance, MongoInspectionExecutor, type MongoRunnerDependencies, createMongoAdapter, createMongoRunnerDeps, mongoAdapterDescriptor as default, mongoAdapterDescriptor, extractDb, initMarker, introspectSchema, isMongoControlDriver, readAllMarkers, readLedger, readMarker, updateMarker, writeLedgerEntry };
122
+ export { type MarkerOperations, MongoCommandExecutor, MongoControlAdapterImpl, type MongoControlDriverInstance, MongoInspectionExecutor, type MongoRunnerDependencies, createMongoAdapter, createMongoRunnerDeps, mongoAdapterDescriptor as default, mongoAdapterDescriptor, extractDb, introspectSchema, isMongoControlDriver };
140
123
  //# sourceMappingURL=control.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/command-executor.ts","../src/core/introspect-schema.ts","../src/core/mongo-control-adapter.ts","../src/core/mongo-control-driver.ts","../src/core/runner-deps.ts","../src/exports/control.ts"],"mappings":";;;;;;;;;;cAca,oBAAA,YAAgC,sBAAA,CAAuB,OAAA;EAAA,iBACrC,EAAA;cAAA,EAAA,EAAI,EAAA;EAE3B,WAAA,CAAY,GAAA,EAAK,kBAAA,GAAqB,OAAA;EAmBtC,SAAA,CAAU,GAAA,EAAK,gBAAA,GAAmB,OAAA;EAIlC,gBAAA,CAAiB,GAAA,EAAK,uBAAA,GAA0B,OAAA;EAgBhD,cAAA,CAAe,GAAA,EAAK,qBAAA,GAAwB,OAAA;EAI5C,OAAA,CAAQ,GAAA,EAAK,cAAA,GAAiB,OAAA;AAAA;AAAA,cAWzB,uBAAA,YAAmC,6BAAA,CAA8B,OAAA,CAAQ,QAAA;EAAA,iBACvD,EAAA;cAAA,EAAA,EAAI,EAAA;EAE3B,WAAA,CAAY,GAAA,EAAK,kBAAA,GAAqB,OAAA,CAAQ,QAAA;EAW9C,eAAA,CAAgB,IAAA,EAAM,sBAAA,GAAyB,OAAA,CAAQ,QAAA;AAAA;;;iBCMzC,gBAAA,CAAiB,EAAA,EAAI,EAAA,GAAK,OAAA,CAAQ,aAAA;;;;;;;;;cC7D3C,uBAAA,YAAmC,mBAAA;EAAA,SACrC,QAAA;EAAA,SACA,QAAA;EAEH,UAAA,CACJ,MAAA,EAAQ,qBAAA,oBACR,KAAA,WACC,OAAA,CAAQ,oBAAA;EAgBL,cAAA,CACJ,MAAA,EAAQ,qBAAA,qBACP,OAAA,CAAQ,WAAA,SAAoB,oBAAA;EA6BzB,UAAA,CACJ,MAAA,EAAQ,qBAAA,oBACR,KAAA,UACA,WAAA;IAAA,SACW,WAAA;IAAA,SACA,WAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EAiBG,YAAA,CACJ,MAAA,EAAQ,qBAAA,oBACR,KAAA,UACA,YAAA,UACA,WAAA;IAAA,SACW,WAAA;IAAA,SACA,WAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EAmCG,gBAAA,CACJ,MAAA,EAAQ,qBAAA,oBACR,KAAA,UACA,KAAA;IAAA,SACW,MAAA;IAAA,SACA,IAAA;IAAA,SACA,EAAA;IAAA,SACA,aAAA;IAAA,SACA,aAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EAgBG,UAAA,CACJ,MAAA,EAAQ,qBAAA,oBACR,KAAA,YACC,OAAA,UAAiB,iBAAA;EAsDd,gBAAA,CAAiB,MAAA,EAAQ,qBAAA,qBAA0C,OAAA,CAAQ,aAAA;AAAA;;;iBC1OnE,oBAAA,CACd,MAAA,EAAQ,qBAAA,oBACP,MAAA,IAAU,4BAA0B;;;iBCavB,SAAA,CAAU,MAAA,EAAQ,qBAAA,qBAA0C,EAAE;;;AJJ9E;;;;UIoBiB,gBAAA;EACf,UAAA,CAAW,KAAA,WAAgB,OAAA,CAAQ,oBAAA;EACnC,UAAA,CACE,KAAA,UACA,WAAA;IAAA,SACW,WAAA;IAAA,SACA,WAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EACH,YAAA,CACE,KAAA,UACA,YAAA,UACA,WAAA;IAAA,SACW,WAAA;IAAA,SACA,WAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EACH,gBAAA,CACE,KAAA,UACA,KAAA;IAAA,SACW,MAAA;IAAA,SACA,IAAA;IAAA,SACA,EAAA;IAAA,SACA,aAAA;IAAA,SACA,aAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;AAAA;AAAA,UAGY,uBAAA;EAAA,SACN,eAAA,EAAiB,sBAAA,CAAuB,OAAA;EAAA,SACxC,kBAAA,EAAoB,6BAAA,CAA8B,OAAA,CAAQ,MAAA;EAAA,SAC1D,OAAA,EAAS,YAAA;EAAA,SACT,MAAA,EAAQ,WAAA;EAAA,SACR,SAAA,EAAW,gBAAA;EAAA,SACX,gBAAA,QAAwB,OAAA,CAAQ,aAAA;AAAA;;;;;;;;;;iBAY3B,qBAAA,CACd,aAAA,EAAe,qBAAA,oBACf,MAAA,EAAQ,WAAA,EAMR,OAAA,EAAS,qBAAA,UAA+B,aAAA,GACxC,cAAA,GAAgB,mBAAA,YACf,uBAAA;;;iBC9DmB,UAAA,CAAW,EAAA,EAAI,EAAA,EAAI,KAAA,WAAgB,OAAA,CAAQ,oBAAA;AAAA,iBAI3C,cAAA,CAAe,EAAA,EAAI,EAAA,GAAK,OAAA,CAAQ,WAAA,SAAoB,oBAAA;AAAA,iBAIpD,UAAA,CACpB,EAAA,EAAI,EAAA,EACJ,KAAA,UACA,WAAA;EAAA,SACW,WAAA;EAAA,SACA,WAAA;EAAA,SACA,UAAA;AAAA,IAEV,OAAO;AAAA,iBAIY,YAAA,CACpB,EAAA,EAAI,EAAA,EACJ,KAAA,UACA,YAAA,UACA,WAAA;EAAA,SACW,WAAA;EAAA,SACA,WAAA;EAAA,SACA,UAAA;AAAA,IAEV,OAAO;AAAA,iBASY,UAAA,CAAW,EAAA,EAAI,EAAA,EAAI,KAAA,YAAiB,OAAA,UAAiB,iBAAA;AAAA,iBAIrD,gBAAA,CACpB,EAAA,EAAI,EAAA,EACJ,KAAA,UACA,KAAA;EAAA,SACW,MAAA;EAAA,SACA,IAAA;EAAA,SACA,EAAA;EAAA,SACA,aAAA;EAAA,SACA,aAAA;EAAA,SACA,UAAA;AAAA,IAEV,OAAO;AAAA,cAIG,sBAAA,EAAwB,6BAA6B"}
1
+ {"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/command-executor.ts","../src/core/introspect-schema.ts","../src/core/mongo-control-adapter.ts","../src/core/mongo-control-driver.ts","../src/core/runner-deps.ts","../src/exports/control.ts"],"mappings":";;;;;;;;;;cAca,oBAAA,YAAgC,sBAAA,CAAuB,OAAA;EAAA,iBACrC,EAAA;cAAA,EAAA,EAAI,EAAA;EAE3B,WAAA,CAAY,GAAA,EAAK,kBAAA,GAAqB,OAAA;EAmBtC,SAAA,CAAU,GAAA,EAAK,gBAAA,GAAmB,OAAA;EAIlC,gBAAA,CAAiB,GAAA,EAAK,uBAAA,GAA0B,OAAA;EAgBhD,cAAA,CAAe,GAAA,EAAK,qBAAA,GAAwB,OAAA;EAI5C,OAAA,CAAQ,GAAA,EAAK,cAAA,GAAiB,OAAA;AAAA;AAAA,cAWzB,uBAAA,YAAmC,6BAAA,CAA8B,OAAA,CAAQ,QAAA;EAAA,iBACvD,EAAA;cAAA,EAAA,EAAI,EAAA;EAE3B,WAAA,CAAY,GAAA,EAAK,kBAAA,GAAqB,OAAA,CAAQ,QAAA;EAW9C,eAAA,CAAgB,IAAA,EAAM,sBAAA,GAAyB,OAAA,CAAQ,QAAA;AAAA;;;iBCMzC,gBAAA,CAAiB,EAAA,EAAI,EAAA,GAAK,OAAA,CAAQ,aAAA;;;;;;;;;AD7ExD;;;cEyBa,uBAAA,YAAmC,mBAAA;EAAA;WACrC,QAAA;EAAA,SACA,QAAA;EAmDH,UAAA,CACJ,MAAA,EAAQ,qBAAA,oBACR,KAAA,WACC,OAAA,CAAQ,oBAAA;EAoBL,cAAA,CACJ,MAAA,EAAQ,qBAAA,qBACP,OAAA,CAAQ,WAAA,SAAoB,oBAAA;EAyBzB,UAAA,CACJ,MAAA,EAAQ,qBAAA,oBACR,KAAA,UACA,WAAA;IAAA,SACW,WAAA;IAAA,SACA,WAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EAgBG,YAAA,CACJ,MAAA,EAAQ,qBAAA,oBACR,KAAA,UACA,YAAA,UACA,WAAA;IAAA,SACW,WAAA;IAAA,SACA,WAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EA+BG,gBAAA,CACJ,MAAA,EAAQ,qBAAA,oBACR,KAAA,UACA,KAAA;IAAA,SACW,MAAA;IAAA,SACA,IAAA;IAAA,SACA,EAAA;IAAA,SACA,aAAA;IAAA,SACA,aAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EAiBG,UAAA,CACJ,MAAA,EAAQ,qBAAA,oBACR,KAAA,YACC,OAAA,UAAiB,iBAAA;EAqDd,gBAAA,CAAiB,MAAA,EAAQ,qBAAA,qBAA0C,OAAA,CAAQ,aAAA;AAAA;;;iBC/RnE,oBAAA,CACd,MAAA,EAAQ,qBAAA,oBACP,MAAA,IAAU,4BAA0B;;;iBCavB,SAAA,CAAU,MAAA,EAAQ,qBAAA,qBAA0C,EAAE;;;AJJ9E;;;;UIoBiB,gBAAA;EACf,UAAA,CAAW,KAAA,WAAgB,OAAA,CAAQ,oBAAA;EACnC,UAAA,CACE,KAAA,UACA,WAAA;IAAA,SACW,WAAA;IAAA,SACA,WAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EACH,YAAA,CACE,KAAA,UACA,YAAA,UACA,WAAA;IAAA,SACW,WAAA;IAAA,SACA,WAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EACH,gBAAA,CACE,KAAA,UACA,KAAA;IAAA,SACW,MAAA;IAAA,SACA,IAAA;IAAA,SACA,EAAA;IAAA,SACA,aAAA;IAAA,SACA,aAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;AAAA;AAAA,UAGY,uBAAA;EAAA,SACN,eAAA,EAAiB,sBAAA,CAAuB,OAAA;EAAA,SACxC,kBAAA,EAAoB,6BAAA,CAA8B,OAAA,CAAQ,MAAA;EAAA,SAC1D,OAAA,EAAS,YAAA;EAAA,SACT,MAAA,EAAQ,WAAA;EAAA,SACR,SAAA,EAAW,gBAAA;EAAA,SACX,gBAAA,QAAwB,OAAA,CAAQ,aAAA;AAAA;;;;;;;;;;iBAY3B,qBAAA,CACd,aAAA,EAAe,qBAAA,oBACf,MAAA,EAAQ,WAAA,EAMR,OAAA,EAAS,qBAAA,UAA+B,aAAA,GACxC,cAAA,GAAgB,mBAAA,YACf,uBAAA;;;cC3EU,sBAAA,EAAwB,6BAA6B"}
package/dist/control.mjs CHANGED
@@ -1,10 +1,13 @@
1
1
  import { r as mongoCodecDescriptors, t as createMongoAdapter } from "./mongo-adapter-DAC5qq3o.mjs";
2
- import { RawAggregateCommand, RawFindOneAndUpdateCommand, RawInsertOneCommand } from "@prisma-next/mongo-query-ast/execution";
2
+ import { MongoAggFieldRef, MongoAggLiteral, MongoAggOperator } from "@prisma-next/mongo-query-ast/execution";
3
+ import { blindCast } from "@prisma-next/utils/casts";
3
4
  import { MongoServerError } from "mongodb";
4
5
  import { keysToKeySpec } from "@prisma-next/mongo-query-ast/control";
5
6
  import { MongoSchemaCollection, MongoSchemaCollectionOptions, MongoSchemaIR, MongoSchemaIndex, MongoSchemaValidator } from "@prisma-next/mongo-schema-ir";
6
7
  import { parseMarkerRowSafely, withMarkerReadErrorHandling } from "@prisma-next/errors/execution";
7
8
  import { ledgerOriginFromStored } from "@prisma-next/migration-tools/ledger-origin";
9
+ import { expr, fn } from "@prisma-next/mongo-query-builder";
10
+ import { collection } from "@prisma-next/mongo-query-builder/contract-free";
8
11
  import { type } from "arktype";
9
12
  //#region src/core/command-executor.ts
10
13
  var MongoCommandExecutor = class {
@@ -201,19 +204,13 @@ function parseMongoMarkerDocSafely(doc, space) {
201
204
  markerLocation: MONGO_MARKER_COLLECTION
202
205
  });
203
206
  }
204
- async function executeAggregate(db, cmd) {
205
- return db.collection(cmd.collection).aggregate(cmd.pipeline).toArray();
206
- }
207
- async function executeInsertOne(db, cmd) {
208
- await db.collection(cmd.collection).insertOne(cmd.document);
209
- }
210
- async function executeFindOneAndUpdate(db, cmd) {
211
- return db.collection(cmd.collection).findOneAndUpdate(cmd.filter, cmd.update, { upsert: cmd.upsert });
212
- }
207
+ //#endregion
208
+ //#region src/core/marker-ledger-collection.ts
209
+ const MARKER_LEDGER_COLLECTION = "_prisma_migrations";
213
210
  //#endregion
214
211
  //#region src/core/mongo-control-driver.ts
215
212
  function isMongoControlDriver(driver) {
216
- return driver.familyId === "mongo" && driver.targetId === "mongo";
213
+ return driver.familyId === "mongo" && driver.targetId === "mongo" && "execute" in driver && typeof driver.execute === "function";
217
214
  }
218
215
  //#endregion
219
216
  //#region src/core/runner-deps.ts
@@ -250,18 +247,65 @@ function createMongoRunnerDeps(controlDriver, driver, _family, controlAdapter =
250
247
  /**
251
248
  * Mongo control adapter for control-plane operations like introspection
252
249
  * and marker-ledger CAS. Implements the family-level `MongoControlAdapter`
253
- * SPI by extracting the underlying `Db` from the framework-shaped driver
254
- * per call.
250
+ * SPI. Every marker/ledger operation builds a canonical command inline via
251
+ * the contract-free fluent builder and dispatches it through the family
252
+ * adapter's lowering path (`createMongoAdapter().lower(plan, {})`) onto the
253
+ * Mongo wire transport (`driver.execute(wireCommand)`) — the same route SQL
254
+ * marker/ledger ops take through `adapter.lower()` → `driver.query()`.
255
255
  */
256
256
  var MongoControlAdapterImpl = class {
257
257
  familyId = "mongo";
258
258
  targetId = "mongo";
259
+ #adapter = createMongoAdapter();
260
+ #markerLedgerCollection = collection(MARKER_LEDGER_COLLECTION);
261
+ async #execute(driver, command) {
262
+ const plan = {
263
+ collection: MARKER_LEDGER_COLLECTION,
264
+ command,
265
+ meta: {
266
+ target: "mongo",
267
+ targetFamily: "mongo",
268
+ storageHash: "",
269
+ lane: "control"
270
+ }
271
+ };
272
+ const wireCommand = await this.#adapter.lower(plan, {});
273
+ if (!isMongoControlDriver(driver)) throw new Error("Mongo control adapter requires a Mongo control driver with an execute() transport. Provide a MongoControlDriver from `@prisma-next/driver-mongo/control`.");
274
+ const rows = [];
275
+ for await (const row of driver.execute(wireCommand)) rows.push(row);
276
+ return rows;
277
+ }
278
+ /**
279
+ * Server-side invariant-merge aggregation expression:
280
+ * `$sortArray({ input: $setUnion([$ifNull('$invariants', []), incoming]), sortBy: 1 })`.
281
+ *
282
+ * Built through the typed agg-expr layer — `fn.setUnion` plus the generic
283
+ * `MongoAggOperator` for `$ifNull` / `$sortArray` (neither has a named `fn`
284
+ * helper). Returns a `MongoAggOperator` that is passed directly to
285
+ * `f.stage.set({ invariants: ... })` in the update pipeline.
286
+ */
287
+ #invariantMergeExpr(incoming) {
288
+ const existingOrEmpty = MongoAggOperator.of("$ifNull", [MongoAggFieldRef.of("invariants"), MongoAggLiteral.of([])]);
289
+ const merged = fn.setUnion({
290
+ _field: {
291
+ codecId: "mongo/array@1",
292
+ nullable: false
293
+ },
294
+ node: existingOrEmpty
295
+ }, {
296
+ _field: {
297
+ codecId: "mongo/array@1",
298
+ nullable: false
299
+ },
300
+ node: MongoAggLiteral.of([...incoming])
301
+ });
302
+ return MongoAggOperator.of("$sortArray", {
303
+ input: merged.node,
304
+ sortBy: MongoAggLiteral.of(1)
305
+ });
306
+ }
259
307
  async readMarker(driver, space) {
260
- const db = extractDb(driver);
261
- const doc = (await withMarkerReadErrorHandling(() => executeAggregate(db, new RawAggregateCommand(COLLECTION, [{ $match: {
262
- _id: space,
263
- space
264
- } }, { $limit: 1 }])), {
308
+ const doc = (await withMarkerReadErrorHandling(() => this.#execute(driver, this.#markerLedgerCollection.aggregate().match((f) => f._id.eq(space)).match((f) => f.space.eq(space)).limit(1).build()), {
265
309
  space,
266
310
  markerLocation: MONGO_MARKER_COLLECTION
267
311
  }))[0];
@@ -269,12 +313,7 @@ var MongoControlAdapterImpl = class {
269
313
  return parseMongoMarkerDocSafely(doc, space);
270
314
  }
271
315
  async readAllMarkers(driver) {
272
- const db = extractDb(driver);
273
- const docs = await withMarkerReadErrorHandling(() => executeAggregate(db, new RawAggregateCommand(COLLECTION, [{ $match: {
274
- _id: { $type: "string" },
275
- space: { $type: "string" },
276
- $expr: { $eq: ["$_id", "$space"] }
277
- } }])), {
316
+ const docs = await withMarkerReadErrorHandling(() => this.#execute(driver, this.#markerLedgerCollection.aggregate().match((f) => f._id.type("string")).match((f) => f.space.type("string")).match((f) => expr(fn.eq(f._id, f.space))).build()), {
278
317
  space: "app",
279
318
  markerLocation: MONGO_MARKER_COLLECTION
280
319
  });
@@ -288,7 +327,7 @@ var MongoControlAdapterImpl = class {
288
327
  return out;
289
328
  }
290
329
  async initMarker(driver, space, destination) {
291
- await executeInsertOne(extractDb(driver), new RawInsertOneCommand(COLLECTION, {
330
+ const document = {
292
331
  _id: space,
293
332
  space,
294
333
  storageHash: destination.storageHash,
@@ -298,31 +337,25 @@ var MongoControlAdapterImpl = class {
298
337
  updatedAt: /* @__PURE__ */ new Date(),
299
338
  appTag: null,
300
339
  meta: {},
301
- invariants: destination.invariants ?? []
302
- }));
340
+ invariants: [...destination.invariants ?? []]
341
+ };
342
+ await this.#execute(driver, this.#markerLedgerCollection.insertOne(document));
303
343
  }
304
344
  async updateMarker(driver, space, expectedFrom, destination) {
305
- const db = extractDb(driver);
306
- const setBase = {
307
- storageHash: destination.storageHash,
308
- profileHash: destination.profileHash,
309
- updatedAt: /* @__PURE__ */ new Date()
310
- };
311
- const update = destination.invariants === void 0 ? { $set: setBase } : [{ $set: {
312
- ...setBase,
313
- invariants: { $sortArray: {
314
- input: { $setUnion: [{ $ifNull: ["$invariants", []] }, destination.invariants] },
315
- sortBy: 1
316
- } }
317
- } }];
318
- return await executeFindOneAndUpdate(db, new RawFindOneAndUpdateCommand(COLLECTION, {
319
- _id: space,
320
- space,
321
- storageHash: expectedFrom
322
- }, update, false)) !== null;
345
+ const { invariants } = destination;
346
+ return (await this.#execute(driver, this.#markerLedgerCollection.match((f) => f._id.eq(space)).match((f) => f.space.eq(space)).match((f) => f.storageHash.eq(expectedFrom)).findOneAndUpdate((f) => [f.stage.set(invariants === void 0 ? {
347
+ storageHash: MongoAggLiteral.of(destination.storageHash),
348
+ profileHash: MongoAggLiteral.of(destination.profileHash),
349
+ updatedAt: MongoAggLiteral.of(/* @__PURE__ */ new Date())
350
+ } : {
351
+ storageHash: MongoAggLiteral.of(destination.storageHash),
352
+ profileHash: MongoAggLiteral.of(destination.profileHash),
353
+ updatedAt: MongoAggLiteral.of(/* @__PURE__ */ new Date()),
354
+ invariants: this.#invariantMergeExpr(invariants)
355
+ })], { upsert: false }))).length > 0;
323
356
  }
324
357
  async writeLedgerEntry(driver, space, entry) {
325
- await executeInsertOne(extractDb(driver), new RawInsertOneCommand(COLLECTION, {
358
+ const document = {
326
359
  type: "ledger",
327
360
  space,
328
361
  edgeId: entry.edgeId,
@@ -330,19 +363,19 @@ var MongoControlAdapterImpl = class {
330
363
  to: entry.to,
331
364
  migrationName: entry.migrationName,
332
365
  migrationHash: entry.migrationHash,
333
- operations: entry.operations,
366
+ operations: blindCast(entry.operations),
334
367
  appliedAt: /* @__PURE__ */ new Date()
335
- }));
368
+ };
369
+ await this.#execute(driver, this.#markerLedgerCollection.insertOne(document));
336
370
  }
337
371
  async readLedger(driver, space) {
338
- const db = extractDb(driver);
339
372
  const ledgerContext = {
340
373
  space: space ?? "*",
341
374
  markerLocation: MONGO_LEDGER_COLLECTION
342
375
  };
343
- const matchStage = { type: "ledger" };
344
- if (space !== void 0) matchStage["space"] = space;
345
- const docs = await withMarkerReadErrorHandling(() => executeAggregate(db, new RawAggregateCommand(COLLECTION, [{ $match: matchStage }, { $sort: { _id: 1 } }])), ledgerContext);
376
+ const chain = this.#markerLedgerCollection.aggregate().match((f) => f.type.eq("ledger"));
377
+ const command = space === void 0 ? chain.sort({ _id: 1 }).build() : chain.match((f) => f.space.eq(space)).sort({ _id: 1 }).build();
378
+ const docs = await withMarkerReadErrorHandling(() => this.#execute(driver, command), ledgerContext);
346
379
  const entries = [];
347
380
  for (const doc of docs) {
348
381
  const migrationName = doc["migrationName"];
@@ -375,33 +408,6 @@ var MongoControlAdapterImpl = class {
375
408
  };
376
409
  //#endregion
377
410
  //#region src/exports/control.ts
378
- const defaultControlAdapter = new MongoControlAdapterImpl();
379
- function controlDriverFromDb(db) {
380
- return {
381
- familyId: "mongo",
382
- targetId: "mongo",
383
- db,
384
- close: async () => {}
385
- };
386
- }
387
- async function readMarker(db, space) {
388
- return defaultControlAdapter.readMarker(controlDriverFromDb(db), space);
389
- }
390
- async function readAllMarkers(db) {
391
- return defaultControlAdapter.readAllMarkers(controlDriverFromDb(db));
392
- }
393
- async function initMarker(db, space, destination) {
394
- await defaultControlAdapter.initMarker(controlDriverFromDb(db), space, destination);
395
- }
396
- async function updateMarker(db, space, expectedFrom, destination) {
397
- return defaultControlAdapter.updateMarker(controlDriverFromDb(db), space, expectedFrom, destination);
398
- }
399
- async function readLedger(db, space) {
400
- return defaultControlAdapter.readLedger(controlDriverFromDb(db), space);
401
- }
402
- async function writeLedgerEntry(db, space, entry) {
403
- await defaultControlAdapter.writeLedgerEntry(controlDriverFromDb(db), space, entry);
404
- }
405
411
  const mongoAdapterDescriptor = {
406
412
  kind: "adapter",
407
413
  id: "mongo",
@@ -434,6 +440,6 @@ const mongoAdapterDescriptor = {
434
440
  }
435
441
  };
436
442
  //#endregion
437
- export { MongoCommandExecutor, MongoControlAdapterImpl, MongoInspectionExecutor, createMongoAdapter, createMongoRunnerDeps, mongoAdapterDescriptor as default, mongoAdapterDescriptor, extractDb, initMarker, introspectSchema, isMongoControlDriver, readAllMarkers, readLedger, readMarker, updateMarker, writeLedgerEntry };
443
+ export { MongoCommandExecutor, MongoControlAdapterImpl, MongoInspectionExecutor, createMongoAdapter, createMongoRunnerDeps, mongoAdapterDescriptor as default, mongoAdapterDescriptor, extractDb, introspectSchema, isMongoControlDriver };
438
444
 
439
445
  //# sourceMappingURL=control.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"control.mjs","names":[],"sources":["../src/core/command-executor.ts","../src/core/introspect-schema.ts","../src/core/marker-ledger.ts","../src/core/mongo-control-driver.ts","../src/core/runner-deps.ts","../src/core/mongo-control-adapter.ts","../src/exports/control.ts"],"sourcesContent":["import type {\n CollModCommand,\n CreateCollectionCommand,\n CreateIndexCommand,\n DropCollectionCommand,\n DropIndexCommand,\n ListCollectionsCommand,\n ListIndexesCommand,\n MongoDdlCommandVisitor,\n MongoInspectionCommandVisitor,\n} from '@prisma-next/mongo-query-ast/control';\nimport { keysToKeySpec } from '@prisma-next/mongo-query-ast/control';\nimport { type Db, type Document, MongoServerError } from 'mongodb';\n\nexport class MongoCommandExecutor implements MongoDdlCommandVisitor<Promise<void>> {\n constructor(private readonly db: Db) {}\n\n async createIndex(cmd: CreateIndexCommand): Promise<void> {\n const keySpec: Document = keysToKeySpec(cmd.keys);\n const options: Record<string, unknown> = {};\n if (cmd.unique !== undefined) options['unique'] = cmd.unique;\n if (cmd.sparse !== undefined) options['sparse'] = cmd.sparse;\n if (cmd.expireAfterSeconds !== undefined)\n options['expireAfterSeconds'] = cmd.expireAfterSeconds;\n if (cmd.partialFilterExpression !== undefined)\n options['partialFilterExpression'] = cmd.partialFilterExpression;\n if (cmd.name !== undefined) options['name'] = cmd.name;\n if (cmd.wildcardProjection !== undefined)\n options['wildcardProjection'] = cmd.wildcardProjection;\n if (cmd.collation !== undefined) options['collation'] = cmd.collation;\n if (cmd.weights !== undefined) options['weights'] = cmd.weights;\n if (cmd.default_language !== undefined) options['default_language'] = cmd.default_language;\n if (cmd.language_override !== undefined) options['language_override'] = cmd.language_override;\n await this.db.collection(cmd.collection).createIndex(keySpec, options);\n }\n\n async dropIndex(cmd: DropIndexCommand): Promise<void> {\n await this.db.collection(cmd.collection).dropIndex(cmd.name);\n }\n\n async createCollection(cmd: CreateCollectionCommand): Promise<void> {\n const options: Record<string, unknown> = {};\n if (cmd.capped !== undefined) options['capped'] = cmd.capped;\n if (cmd.size !== undefined) options['size'] = cmd.size;\n if (cmd.max !== undefined) options['max'] = cmd.max;\n if (cmd.timeseries !== undefined) options['timeseries'] = cmd.timeseries;\n if (cmd.collation !== undefined) options['collation'] = cmd.collation;\n if (cmd.clusteredIndex !== undefined) options['clusteredIndex'] = cmd.clusteredIndex;\n if (cmd.validator !== undefined) options['validator'] = cmd.validator;\n if (cmd.validationLevel !== undefined) options['validationLevel'] = cmd.validationLevel;\n if (cmd.validationAction !== undefined) options['validationAction'] = cmd.validationAction;\n if (cmd.changeStreamPreAndPostImages !== undefined)\n options['changeStreamPreAndPostImages'] = cmd.changeStreamPreAndPostImages;\n await this.db.createCollection(cmd.collection, options);\n }\n\n async dropCollection(cmd: DropCollectionCommand): Promise<void> {\n await this.db.collection(cmd.collection).drop();\n }\n\n async collMod(cmd: CollModCommand): Promise<void> {\n const command: Record<string, unknown> = { collMod: cmd.collection };\n if (cmd.validator !== undefined) command['validator'] = cmd.validator;\n if (cmd.validationLevel !== undefined) command['validationLevel'] = cmd.validationLevel;\n if (cmd.validationAction !== undefined) command['validationAction'] = cmd.validationAction;\n if (cmd.changeStreamPreAndPostImages !== undefined)\n command['changeStreamPreAndPostImages'] = cmd.changeStreamPreAndPostImages;\n await this.db.command(command);\n }\n}\n\nexport class MongoInspectionExecutor implements MongoInspectionCommandVisitor<Promise<Document[]>> {\n constructor(private readonly db: Db) {}\n\n async listIndexes(cmd: ListIndexesCommand): Promise<Document[]> {\n try {\n return await this.db.collection(cmd.collection).listIndexes().toArray();\n } catch (error: unknown) {\n if (error instanceof MongoServerError && error.code === 26) {\n return [];\n }\n throw error;\n }\n }\n\n async listCollections(_cmd: ListCollectionsCommand): Promise<Document[]> {\n return this.db.listCollections().toArray();\n }\n}\n","import type { MongoIndexKey, MongoIndexKeyDirection } from '@prisma-next/mongo-contract';\nimport {\n MongoSchemaCollection,\n MongoSchemaCollectionOptions,\n MongoSchemaIndex,\n MongoSchemaIR,\n MongoSchemaValidator,\n} from '@prisma-next/mongo-schema-ir';\nimport type { Db, Document } from 'mongodb';\n\nconst PRISMA_MIGRATIONS_COLLECTION = '_prisma_migrations';\n\nfunction parseIndexKeys(keySpec: Record<string, unknown>): MongoIndexKey[] {\n const keys: MongoIndexKey[] = [];\n for (const [field, direction] of Object.entries(keySpec)) {\n keys.push({ field, direction: direction as MongoIndexKeyDirection });\n }\n return keys;\n}\n\n/**\n * Exported for unit tests to exercise the defensive `!key` guard; not part of\n * the public API. Callers in this package use it via the `introspectSchema`\n * pipeline only.\n */\nexport function isDefaultIdIndex(doc: Document): boolean {\n const key = doc['key'] as Record<string, unknown> | undefined;\n if (!key) return false;\n const entries = Object.entries(key);\n return entries.length === 1 && entries[0]?.[0] === '_id' && entries[0]?.[1] === 1;\n}\n\nfunction parseIndex(doc: Document): MongoSchemaIndex {\n const keySpec = doc['key'] as Record<string, unknown>;\n return new MongoSchemaIndex({\n keys: parseIndexKeys(keySpec),\n unique: doc['unique'] as boolean | undefined,\n sparse: doc['sparse'] as boolean | undefined,\n expireAfterSeconds: doc['expireAfterSeconds'] as number | undefined,\n partialFilterExpression: doc['partialFilterExpression'] as Record<string, unknown> | undefined,\n wildcardProjection: doc['wildcardProjection'] as Record<string, 0 | 1> | undefined,\n collation: doc['collation'] as Record<string, unknown> | undefined,\n weights: doc['weights'] as Record<string, number> | undefined,\n default_language: doc['default_language'] as string | undefined,\n language_override: doc['language_override'] as string | undefined,\n });\n}\n\nfunction parseValidator(options: Document): MongoSchemaValidator | undefined {\n const validator = options['validator'] as Record<string, unknown> | undefined;\n if (!validator) return undefined;\n\n const jsonSchema = validator['$jsonSchema'] as Record<string, unknown> | undefined;\n if (!jsonSchema) return undefined;\n\n return new MongoSchemaValidator({\n jsonSchema,\n validationLevel: (options['validationLevel'] as 'strict' | 'moderate') ?? 'strict',\n validationAction: (options['validationAction'] as 'error' | 'warn') ?? 'error',\n });\n}\n\nfunction parseCollectionOptions(info: Document): MongoSchemaCollectionOptions | undefined {\n const options = info['options'] as Record<string, unknown> | undefined;\n if (!options) return undefined;\n\n const capped = options['capped'] as boolean | undefined;\n const size = options['size'] as number | undefined;\n const max = options['max'] as number | undefined;\n const timeseries = options['timeseries'] as\n | { timeField: string; metaField?: string; granularity?: 'seconds' | 'minutes' | 'hours' }\n | undefined;\n const collation = options['collation'] as Record<string, unknown> | undefined;\n const changeStreamPreAndPostImages = options['changeStreamPreAndPostImages'] as\n | { enabled: boolean }\n | undefined;\n const clusteredIndex = options['clusteredIndex'] as { name?: string } | undefined;\n\n const hasMeaningfulOptions =\n capped || timeseries || collation || changeStreamPreAndPostImages || clusteredIndex;\n if (!hasMeaningfulOptions) return undefined;\n\n return new MongoSchemaCollectionOptions({\n ...(capped ? { capped: { size: size ?? 0, ...(max != null ? { max } : {}) } } : {}),\n ...(timeseries ? { timeseries } : {}),\n ...(collation ? { collation } : {}),\n ...(changeStreamPreAndPostImages ? { changeStreamPreAndPostImages } : {}),\n ...(clusteredIndex ? { clusteredIndex } : {}),\n });\n}\n\nexport async function introspectSchema(db: Db): Promise<MongoSchemaIR> {\n const collectionInfos = await db.listCollections().toArray();\n\n const collections: MongoSchemaCollection[] = [];\n\n for (const info of collectionInfos) {\n const name = info['name'] as string;\n const type = info['type'] as string | undefined;\n\n if (name === PRISMA_MIGRATIONS_COLLECTION) continue;\n if (name.startsWith('system.')) continue;\n if (type === 'view') continue;\n\n const indexDocs = await db.collection(name).listIndexes().toArray();\n const indexes = indexDocs.filter((doc) => !isDefaultIdIndex(doc)).map(parseIndex);\n\n const infoOptions = 'options' in info ? (info['options'] as Record<string, unknown>) : {};\n const validator = parseValidator(infoOptions);\n const options = parseCollectionOptions(info);\n\n collections.push(\n new MongoSchemaCollection({\n name,\n indexes,\n ...(validator ? { validator } : {}),\n ...(options ? { options } : {}),\n }),\n );\n }\n\n return new MongoSchemaIR(collections);\n}\n","import type { ContractMarkerRecord } from '@prisma-next/contract/types';\nimport { parseMarkerRowSafely } from '@prisma-next/errors/execution';\nimport type {\n RawAggregateCommand,\n RawFindOneAndUpdateCommand,\n RawInsertOneCommand,\n} from '@prisma-next/mongo-query-ast/execution';\nimport { type } from 'arktype';\nimport type { Db, Document, UpdateFilter } from 'mongodb';\n\nexport const COLLECTION = '_prisma_migrations';\nexport const MONGO_MARKER_COLLECTION = `_prisma_migrations marker documents in ${COLLECTION}`;\nexport const MONGO_LEDGER_COLLECTION = `_prisma_migrations ledger documents in ${COLLECTION}`;\n\nconst MongoMarkerDocSchema = type({\n space: 'string',\n storageHash: 'string',\n profileHash: 'string',\n 'contractJson?': 'unknown | null',\n 'canonicalVersion?': 'number | null',\n 'updatedAt?': 'Date',\n 'appTag?': 'string | null',\n 'meta?': type({ '[string]': 'unknown' }).or('null'),\n 'invariants?': type('string').array(),\n '+': 'delete',\n});\n\nexport function parseMongoMarkerDoc(doc: unknown): ContractMarkerRecord {\n const result = MongoMarkerDocSchema(doc);\n if (result instanceof type.errors) {\n throw new Error(`Invalid marker doc on ${COLLECTION}: ${result.summary}`);\n }\n return {\n storageHash: result.storageHash,\n profileHash: result.profileHash,\n contractJson: result.contractJson ?? null,\n canonicalVersion: result.canonicalVersion ?? null,\n updatedAt: result.updatedAt ?? new Date(),\n appTag: result.appTag ?? null,\n meta: (result.meta as Record<string, unknown> | null) ?? {},\n invariants: result.invariants ?? [],\n };\n}\n\nexport function parseMongoMarkerDocSafely(doc: unknown, space: string): ContractMarkerRecord {\n return parseMarkerRowSafely(doc, parseMongoMarkerDoc, {\n space,\n markerLocation: MONGO_MARKER_COLLECTION,\n });\n}\n\nexport async function executeAggregate(db: Db, cmd: RawAggregateCommand): Promise<Document[]> {\n return db\n .collection(cmd.collection)\n .aggregate(cmd.pipeline as Record<string, unknown>[])\n .toArray();\n}\n\nexport async function executeInsertOne(db: Db, cmd: RawInsertOneCommand): Promise<void> {\n await db.collection(cmd.collection).insertOne(cmd.document);\n}\n\nexport async function executeFindOneAndUpdate(\n db: Db,\n cmd: RawFindOneAndUpdateCommand,\n): Promise<Document | null> {\n return db\n .collection(cmd.collection)\n .findOneAndUpdate(cmd.filter, cmd.update as UpdateFilter<Document> | Document[], {\n upsert: cmd.upsert,\n });\n}\n","import type { ControlDriverInstance } from '@prisma-next/framework-components/control';\nimport type { MongoControlDriverInstance } from '@prisma-next/mongo-lowering';\n\nexport function isMongoControlDriver(\n driver: ControlDriverInstance<'mongo', string>,\n): driver is MongoControlDriverInstance {\n return driver.familyId === 'mongo' && driver.targetId === 'mongo';\n}\n","import type { ContractMarkerRecord } from '@prisma-next/contract/types';\nimport type { MongoControlAdapter } from '@prisma-next/family-mongo/control-adapter';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n} from '@prisma-next/framework-components/control';\nimport type { MongoAdapter, MongoDriver } from '@prisma-next/mongo-lowering';\nimport type {\n MongoDdlCommandVisitor,\n MongoInspectionCommandVisitor,\n} from '@prisma-next/mongo-query-ast/control';\nimport type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport type { Db } from 'mongodb';\nimport { createMongoAdapter } from '../mongo-adapter';\nimport { MongoCommandExecutor, MongoInspectionExecutor } from './command-executor';\nimport { MongoControlAdapterImpl } from './mongo-control-adapter';\nimport { isMongoControlDriver } from './mongo-control-driver';\n\nexport function extractDb(driver: ControlDriverInstance<'mongo', 'mongo'>): Db {\n if (!isMongoControlDriver(driver)) {\n throw new Error(\n 'Expected a Mongo control driver created by ' +\n 'mongoControlDriver.create() from `@prisma-next/driver-mongo/control`.',\n );\n }\n return driver.db;\n}\n\n/**\n * Marker / ledger operations the Mongo runner depends on. Every method\n * takes a `space` parameter so each loaded contract space addresses its\n * own marker row independently — see ADR 212 for the per-space\n * mechanism.\n */\nexport interface MarkerOperations {\n readMarker(space: string): Promise<ContractMarkerRecord | null>;\n initMarker(\n space: string,\n destination: {\n readonly storageHash: string;\n readonly profileHash: string;\n readonly invariants?: readonly string[];\n },\n ): Promise<void>;\n updateMarker(\n space: string,\n expectedFrom: string,\n destination: {\n readonly storageHash: string;\n readonly profileHash: string;\n readonly invariants?: readonly string[];\n },\n ): Promise<boolean>;\n writeLedgerEntry(\n space: string,\n entry: {\n readonly edgeId: string;\n readonly from: string;\n readonly to: string;\n readonly migrationName: string;\n readonly migrationHash: string;\n readonly operations: readonly unknown[];\n },\n ): Promise<void>;\n}\n\nexport interface MongoRunnerDependencies {\n readonly commandExecutor: MongoDdlCommandVisitor<Promise<void>>;\n readonly inspectionExecutor: MongoInspectionCommandVisitor<Promise<Record<string, unknown>[]>>;\n readonly adapter: MongoAdapter;\n readonly driver: MongoDriver;\n readonly markerOps: MarkerOperations;\n readonly introspectSchema: () => Promise<MongoSchemaIR>;\n}\n\n/**\n * Build the runner-dependencies envelope. `controlAdapter` is the\n * dispatch surface for wire-level Mongo CAS operations (marker reads,\n * marker advances, ledger appends, introspection); the envelope's\n * `markerOps` shim simply forwards each call through it. When the\n * caller already has a `MongoControlAdapter` on the control stack it\n * can pass it in; otherwise a default `MongoControlAdapterImpl` is\n * constructed locally.\n */\nexport function createMongoRunnerDeps(\n controlDriver: ControlDriverInstance<'mongo', 'mongo'>,\n driver: MongoDriver,\n // Vestigial after the family→adapter SPI refactor: the runner dependencies\n // now route every wire-level call through `controlAdapter`, so the `family`\n // instance is no longer consulted. Kept on the signature to avoid rippling\n // through ~14 call sites; a follow-up that already touches this factory\n // should drop the parameter outright.\n _family: ControlFamilyInstance<'mongo', MongoSchemaIR>,\n controlAdapter: MongoControlAdapter<'mongo'> = new MongoControlAdapterImpl(),\n): MongoRunnerDependencies {\n return {\n commandExecutor: new MongoCommandExecutor(extractDb(controlDriver)),\n inspectionExecutor: new MongoInspectionExecutor(extractDb(controlDriver)),\n adapter: createMongoAdapter(),\n driver,\n markerOps: {\n readMarker: (space) => controlAdapter.readMarker(controlDriver, space),\n initMarker: (space, dest) => controlAdapter.initMarker(controlDriver, space, dest),\n updateMarker: (space, expectedFrom, dest) =>\n controlAdapter.updateMarker(controlDriver, space, expectedFrom, dest),\n writeLedgerEntry: (space, entry) =>\n controlAdapter.writeLedgerEntry(controlDriver, space, entry),\n },\n introspectSchema: () => controlAdapter.introspectSchema(controlDriver),\n };\n}\n","import type { ContractMarkerRecord, LedgerEntryRecord } from '@prisma-next/contract/types';\nimport { withMarkerReadErrorHandling } from '@prisma-next/errors/execution';\nimport type { MongoControlAdapter } from '@prisma-next/family-mongo/control-adapter';\nimport type { ControlDriverInstance } from '@prisma-next/framework-components/control';\nimport { ledgerOriginFromStored } from '@prisma-next/migration-tools/ledger-origin';\nimport {\n RawAggregateCommand,\n RawFindOneAndUpdateCommand,\n RawInsertOneCommand,\n} from '@prisma-next/mongo-query-ast/execution';\nimport type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport type { Document } from 'mongodb';\nimport { introspectSchema } from './introspect-schema';\nimport {\n COLLECTION,\n executeAggregate,\n executeFindOneAndUpdate,\n executeInsertOne,\n MONGO_LEDGER_COLLECTION,\n MONGO_MARKER_COLLECTION,\n parseMongoMarkerDocSafely,\n} from './marker-ledger';\nimport { extractDb } from './runner-deps';\n\n/**\n * Mongo control adapter for control-plane operations like introspection\n * and marker-ledger CAS. Implements the family-level `MongoControlAdapter`\n * SPI by extracting the underlying `Db` from the framework-shaped driver\n * per call.\n */\nexport class MongoControlAdapterImpl implements MongoControlAdapter<'mongo'> {\n readonly familyId = 'mongo' as const;\n readonly targetId = 'mongo' as const;\n\n async readMarker(\n driver: ControlDriverInstance<'mongo', 'mongo'>,\n space: string,\n ): Promise<ContractMarkerRecord | null> {\n const db = extractDb(driver);\n const markerContext = { space, markerLocation: MONGO_MARKER_COLLECTION };\n const docs = await withMarkerReadErrorHandling(\n () =>\n executeAggregate(\n db,\n new RawAggregateCommand(COLLECTION, [{ $match: { _id: space, space } }, { $limit: 1 }]),\n ),\n markerContext,\n );\n const doc = docs[0];\n if (!doc) return null;\n return parseMongoMarkerDocSafely(doc, space);\n }\n\n async readAllMarkers(\n driver: ControlDriverInstance<'mongo', 'mongo'>,\n ): Promise<ReadonlyMap<string, ContractMarkerRecord>> {\n const db = extractDb(driver);\n const markerContext = { space: 'app', markerLocation: MONGO_MARKER_COLLECTION };\n const docs = await withMarkerReadErrorHandling(\n () =>\n executeAggregate(\n db,\n new RawAggregateCommand(COLLECTION, [\n {\n $match: {\n _id: { $type: 'string' },\n space: { $type: 'string' },\n $expr: { $eq: ['$_id', '$space'] },\n },\n },\n ]),\n ),\n markerContext,\n );\n const out = new Map<string, ContractMarkerRecord>();\n for (const doc of docs) {\n const space = doc['space'];\n /* v8 ignore next -- @preserve type-narrowing guard: the $match stage above filters on `space: { $type: 'string' }`, so this branch is unreachable at runtime. The check exists so the `out.set(space, ...)` call below can accept `string`. */\n if (typeof space !== 'string') continue;\n out.set(space, parseMongoMarkerDocSafely(doc, space));\n }\n return out;\n }\n\n async initMarker(\n driver: ControlDriverInstance<'mongo', 'mongo'>,\n space: string,\n destination: {\n readonly storageHash: string;\n readonly profileHash: string;\n readonly invariants?: readonly string[];\n },\n ): Promise<void> {\n const db = extractDb(driver);\n const cmd = new RawInsertOneCommand(COLLECTION, {\n _id: space,\n space,\n storageHash: destination.storageHash,\n profileHash: destination.profileHash,\n contractJson: null,\n canonicalVersion: null,\n updatedAt: new Date(),\n appTag: null,\n meta: {},\n invariants: destination.invariants ?? [],\n });\n await executeInsertOne(db, cmd);\n }\n\n async updateMarker(\n driver: ControlDriverInstance<'mongo', 'mongo'>,\n space: string,\n expectedFrom: string,\n destination: {\n readonly storageHash: string;\n readonly profileHash: string;\n readonly invariants?: readonly string[];\n },\n ): Promise<boolean> {\n const db = extractDb(driver);\n const setBase: Record<string, unknown> = {\n storageHash: destination.storageHash,\n profileHash: destination.profileHash,\n updatedAt: new Date(),\n };\n const update: Document | Document[] =\n destination.invariants === undefined\n ? { $set: setBase }\n : [\n {\n $set: {\n ...setBase,\n invariants: {\n $sortArray: {\n input: {\n $setUnion: [{ $ifNull: ['$invariants', []] }, destination.invariants],\n },\n sortBy: 1,\n },\n },\n },\n },\n ];\n const cmd = new RawFindOneAndUpdateCommand(\n COLLECTION,\n { _id: space, space, storageHash: expectedFrom },\n update,\n false,\n );\n const result = await executeFindOneAndUpdate(db, cmd);\n return result !== null;\n }\n\n async writeLedgerEntry(\n driver: ControlDriverInstance<'mongo', 'mongo'>,\n space: string,\n entry: {\n readonly edgeId: string;\n readonly from: string;\n readonly to: string;\n readonly migrationName: string;\n readonly migrationHash: string;\n readonly operations: readonly unknown[];\n },\n ): Promise<void> {\n const db = extractDb(driver);\n const cmd = new RawInsertOneCommand(COLLECTION, {\n type: 'ledger',\n space,\n edgeId: entry.edgeId,\n from: entry.from,\n to: entry.to,\n migrationName: entry.migrationName,\n migrationHash: entry.migrationHash,\n operations: entry.operations,\n appliedAt: new Date(),\n });\n await executeInsertOne(db, cmd);\n }\n\n async readLedger(\n driver: ControlDriverInstance<'mongo', 'mongo'>,\n space?: string,\n ): Promise<readonly LedgerEntryRecord[]> {\n const db = extractDb(driver);\n const ledgerContext = { space: space ?? '*', markerLocation: MONGO_LEDGER_COLLECTION };\n const matchStage: Record<string, unknown> = { type: 'ledger' };\n if (space !== undefined) {\n matchStage['space'] = space;\n }\n const docs = await withMarkerReadErrorHandling(\n () =>\n executeAggregate(\n db,\n new RawAggregateCommand(COLLECTION, [{ $match: matchStage }, { $sort: { _id: 1 } }]),\n ),\n ledgerContext,\n );\n\n const entries: LedgerEntryRecord[] = [];\n for (const doc of docs) {\n const migrationName = doc['migrationName'];\n const migrationHash = doc['migrationHash'];\n const from = doc['from'];\n const to = doc['to'];\n const docSpace = doc['space'];\n if (typeof migrationName !== 'string' || typeof migrationHash !== 'string') {\n continue;\n }\n if (typeof from !== 'string' || typeof to !== 'string') {\n continue;\n }\n if (typeof docSpace !== 'string') {\n continue;\n }\n const appliedAt = doc['appliedAt'];\n const appliedAtDate =\n appliedAt instanceof Date\n ? appliedAt\n : appliedAt !== undefined\n ? new Date(String(appliedAt))\n : new Date();\n const operations = doc['operations'];\n const opList = Array.isArray(operations) ? operations : [];\n entries.push({\n space: docSpace,\n migrationName,\n migrationHash,\n from: ledgerOriginFromStored(from),\n to,\n appliedAt: appliedAtDate,\n operationCount: opList.length,\n });\n }\n return entries;\n }\n\n async introspectSchema(driver: ControlDriverInstance<'mongo', 'mongo'>): Promise<MongoSchemaIR> {\n return introspectSchema(extractDb(driver));\n }\n}\n","import type { ContractMarkerRecord, LedgerEntryRecord } from '@prisma-next/contract/types';\nimport type { MongoControlAdapterDescriptor } from '@prisma-next/family-mongo/control-adapter';\nimport type { ControlDriverInstance } from '@prisma-next/framework-components/control';\nimport type { Db } from 'mongodb';\n\nexport type { MongoControlDriverInstance } from '@prisma-next/mongo-lowering';\nexport { MongoCommandExecutor, MongoInspectionExecutor } from '../core/command-executor';\nexport { introspectSchema } from '../core/introspect-schema';\nexport { MongoControlAdapterImpl } from '../core/mongo-control-adapter';\nexport { isMongoControlDriver } from '../core/mongo-control-driver';\nexport {\n createMongoRunnerDeps,\n extractDb,\n type MarkerOperations,\n type MongoRunnerDependencies,\n} from '../core/runner-deps';\nexport { createMongoAdapter } from '../mongo-adapter';\n\nimport { mongoCodecDescriptors } from '../core/codecs';\nimport { MongoControlAdapterImpl } from '../core/mongo-control-adapter';\n\nconst defaultControlAdapter = new MongoControlAdapterImpl();\n\nfunction controlDriverFromDb(db: Db): ControlDriverInstance<'mongo', 'mongo'> & { db: Db } {\n return {\n familyId: 'mongo',\n targetId: 'mongo',\n db,\n close: async () => {},\n };\n}\n\nexport async function readMarker(db: Db, space: string): Promise<ContractMarkerRecord | null> {\n return defaultControlAdapter.readMarker(controlDriverFromDb(db), space);\n}\n\nexport async function readAllMarkers(db: Db): Promise<ReadonlyMap<string, ContractMarkerRecord>> {\n return defaultControlAdapter.readAllMarkers(controlDriverFromDb(db));\n}\n\nexport async function initMarker(\n db: Db,\n space: string,\n destination: {\n readonly storageHash: string;\n readonly profileHash: string;\n readonly invariants?: readonly string[];\n },\n): Promise<void> {\n await defaultControlAdapter.initMarker(controlDriverFromDb(db), space, destination);\n}\n\nexport async function updateMarker(\n db: Db,\n space: string,\n expectedFrom: string,\n destination: {\n readonly storageHash: string;\n readonly profileHash: string;\n readonly invariants?: readonly string[];\n },\n): Promise<boolean> {\n return defaultControlAdapter.updateMarker(\n controlDriverFromDb(db),\n space,\n expectedFrom,\n destination,\n );\n}\n\nexport async function readLedger(db: Db, space?: string): Promise<readonly LedgerEntryRecord[]> {\n return defaultControlAdapter.readLedger(controlDriverFromDb(db), space);\n}\n\nexport async function writeLedgerEntry(\n db: Db,\n space: string,\n entry: {\n readonly edgeId: string;\n readonly from: string;\n readonly to: string;\n readonly migrationName: string;\n readonly migrationHash: string;\n readonly operations: readonly unknown[];\n },\n): Promise<void> {\n await defaultControlAdapter.writeLedgerEntry(controlDriverFromDb(db), space, entry);\n}\n\nexport const mongoAdapterDescriptor: MongoControlAdapterDescriptor<'mongo'> = {\n kind: 'adapter',\n id: 'mongo',\n familyId: 'mongo',\n targetId: 'mongo',\n version: '0.0.1',\n scalarTypeDescriptors: new Map([\n ['String', 'mongo/string@1'],\n ['Int', 'mongo/int32@1'],\n ['Boolean', 'mongo/bool@1'],\n ['DateTime', 'mongo/date@1'],\n ['ObjectId', 'mongo/objectId@1'],\n ['Float', 'mongo/double@1'],\n ]),\n types: {\n codecTypes: {\n codecDescriptors: mongoCodecDescriptors,\n import: {\n package: '@prisma-next/adapter-mongo/codec-types',\n named: 'CodecTypes',\n alias: 'MongoCodecTypes',\n },\n typeImports: [\n {\n package: '@prisma-next/adapter-mongo/codec-types',\n named: 'Vector',\n alias: 'Vector',\n },\n ],\n },\n },\n create(_stack) {\n return new MongoControlAdapterImpl();\n },\n};\n\nexport default mongoAdapterDescriptor;\n"],"mappings":"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"}
1
+ {"version":3,"file":"control.mjs","names":["#adapter","#markerLedgerCollection","#execute","#invariantMergeExpr"],"sources":["../src/core/command-executor.ts","../src/core/introspect-schema.ts","../src/core/marker-ledger.ts","../src/core/marker-ledger-collection.ts","../src/core/mongo-control-driver.ts","../src/core/runner-deps.ts","../src/core/mongo-control-adapter.ts","../src/exports/control.ts"],"sourcesContent":["import type {\n CollModCommand,\n CreateCollectionCommand,\n CreateIndexCommand,\n DropCollectionCommand,\n DropIndexCommand,\n ListCollectionsCommand,\n ListIndexesCommand,\n MongoDdlCommandVisitor,\n MongoInspectionCommandVisitor,\n} from '@prisma-next/mongo-query-ast/control';\nimport { keysToKeySpec } from '@prisma-next/mongo-query-ast/control';\nimport { type Db, type Document, MongoServerError } from 'mongodb';\n\nexport class MongoCommandExecutor implements MongoDdlCommandVisitor<Promise<void>> {\n constructor(private readonly db: Db) {}\n\n async createIndex(cmd: CreateIndexCommand): Promise<void> {\n const keySpec: Document = keysToKeySpec(cmd.keys);\n const options: Record<string, unknown> = {};\n if (cmd.unique !== undefined) options['unique'] = cmd.unique;\n if (cmd.sparse !== undefined) options['sparse'] = cmd.sparse;\n if (cmd.expireAfterSeconds !== undefined)\n options['expireAfterSeconds'] = cmd.expireAfterSeconds;\n if (cmd.partialFilterExpression !== undefined)\n options['partialFilterExpression'] = cmd.partialFilterExpression;\n if (cmd.name !== undefined) options['name'] = cmd.name;\n if (cmd.wildcardProjection !== undefined)\n options['wildcardProjection'] = cmd.wildcardProjection;\n if (cmd.collation !== undefined) options['collation'] = cmd.collation;\n if (cmd.weights !== undefined) options['weights'] = cmd.weights;\n if (cmd.default_language !== undefined) options['default_language'] = cmd.default_language;\n if (cmd.language_override !== undefined) options['language_override'] = cmd.language_override;\n await this.db.collection(cmd.collection).createIndex(keySpec, options);\n }\n\n async dropIndex(cmd: DropIndexCommand): Promise<void> {\n await this.db.collection(cmd.collection).dropIndex(cmd.name);\n }\n\n async createCollection(cmd: CreateCollectionCommand): Promise<void> {\n const options: Record<string, unknown> = {};\n if (cmd.capped !== undefined) options['capped'] = cmd.capped;\n if (cmd.size !== undefined) options['size'] = cmd.size;\n if (cmd.max !== undefined) options['max'] = cmd.max;\n if (cmd.timeseries !== undefined) options['timeseries'] = cmd.timeseries;\n if (cmd.collation !== undefined) options['collation'] = cmd.collation;\n if (cmd.clusteredIndex !== undefined) options['clusteredIndex'] = cmd.clusteredIndex;\n if (cmd.validator !== undefined) options['validator'] = cmd.validator;\n if (cmd.validationLevel !== undefined) options['validationLevel'] = cmd.validationLevel;\n if (cmd.validationAction !== undefined) options['validationAction'] = cmd.validationAction;\n if (cmd.changeStreamPreAndPostImages !== undefined)\n options['changeStreamPreAndPostImages'] = cmd.changeStreamPreAndPostImages;\n await this.db.createCollection(cmd.collection, options);\n }\n\n async dropCollection(cmd: DropCollectionCommand): Promise<void> {\n await this.db.collection(cmd.collection).drop();\n }\n\n async collMod(cmd: CollModCommand): Promise<void> {\n const command: Record<string, unknown> = { collMod: cmd.collection };\n if (cmd.validator !== undefined) command['validator'] = cmd.validator;\n if (cmd.validationLevel !== undefined) command['validationLevel'] = cmd.validationLevel;\n if (cmd.validationAction !== undefined) command['validationAction'] = cmd.validationAction;\n if (cmd.changeStreamPreAndPostImages !== undefined)\n command['changeStreamPreAndPostImages'] = cmd.changeStreamPreAndPostImages;\n await this.db.command(command);\n }\n}\n\nexport class MongoInspectionExecutor implements MongoInspectionCommandVisitor<Promise<Document[]>> {\n constructor(private readonly db: Db) {}\n\n async listIndexes(cmd: ListIndexesCommand): Promise<Document[]> {\n try {\n return await this.db.collection(cmd.collection).listIndexes().toArray();\n } catch (error: unknown) {\n if (error instanceof MongoServerError && error.code === 26) {\n return [];\n }\n throw error;\n }\n }\n\n async listCollections(_cmd: ListCollectionsCommand): Promise<Document[]> {\n return this.db.listCollections().toArray();\n }\n}\n","import type { MongoIndexKey, MongoIndexKeyDirection } from '@prisma-next/mongo-contract';\nimport {\n MongoSchemaCollection,\n MongoSchemaCollectionOptions,\n MongoSchemaIndex,\n MongoSchemaIR,\n MongoSchemaValidator,\n} from '@prisma-next/mongo-schema-ir';\nimport type { Db, Document } from 'mongodb';\n\nconst PRISMA_MIGRATIONS_COLLECTION = '_prisma_migrations';\n\nfunction parseIndexKeys(keySpec: Record<string, unknown>): MongoIndexKey[] {\n const keys: MongoIndexKey[] = [];\n for (const [field, direction] of Object.entries(keySpec)) {\n keys.push({ field, direction: direction as MongoIndexKeyDirection });\n }\n return keys;\n}\n\n/**\n * Exported for unit tests to exercise the defensive `!key` guard; not part of\n * the public API. Callers in this package use it via the `introspectSchema`\n * pipeline only.\n */\nexport function isDefaultIdIndex(doc: Document): boolean {\n const key = doc['key'] as Record<string, unknown> | undefined;\n if (!key) return false;\n const entries = Object.entries(key);\n return entries.length === 1 && entries[0]?.[0] === '_id' && entries[0]?.[1] === 1;\n}\n\nfunction parseIndex(doc: Document): MongoSchemaIndex {\n const keySpec = doc['key'] as Record<string, unknown>;\n return new MongoSchemaIndex({\n keys: parseIndexKeys(keySpec),\n unique: doc['unique'] as boolean | undefined,\n sparse: doc['sparse'] as boolean | undefined,\n expireAfterSeconds: doc['expireAfterSeconds'] as number | undefined,\n partialFilterExpression: doc['partialFilterExpression'] as Record<string, unknown> | undefined,\n wildcardProjection: doc['wildcardProjection'] as Record<string, 0 | 1> | undefined,\n collation: doc['collation'] as Record<string, unknown> | undefined,\n weights: doc['weights'] as Record<string, number> | undefined,\n default_language: doc['default_language'] as string | undefined,\n language_override: doc['language_override'] as string | undefined,\n });\n}\n\nfunction parseValidator(options: Document): MongoSchemaValidator | undefined {\n const validator = options['validator'] as Record<string, unknown> | undefined;\n if (!validator) return undefined;\n\n const jsonSchema = validator['$jsonSchema'] as Record<string, unknown> | undefined;\n if (!jsonSchema) return undefined;\n\n return new MongoSchemaValidator({\n jsonSchema,\n validationLevel: (options['validationLevel'] as 'strict' | 'moderate') ?? 'strict',\n validationAction: (options['validationAction'] as 'error' | 'warn') ?? 'error',\n });\n}\n\nfunction parseCollectionOptions(info: Document): MongoSchemaCollectionOptions | undefined {\n const options = info['options'] as Record<string, unknown> | undefined;\n if (!options) return undefined;\n\n const capped = options['capped'] as boolean | undefined;\n const size = options['size'] as number | undefined;\n const max = options['max'] as number | undefined;\n const timeseries = options['timeseries'] as\n | { timeField: string; metaField?: string; granularity?: 'seconds' | 'minutes' | 'hours' }\n | undefined;\n const collation = options['collation'] as Record<string, unknown> | undefined;\n const changeStreamPreAndPostImages = options['changeStreamPreAndPostImages'] as\n | { enabled: boolean }\n | undefined;\n const clusteredIndex = options['clusteredIndex'] as { name?: string } | undefined;\n\n const hasMeaningfulOptions =\n capped || timeseries || collation || changeStreamPreAndPostImages || clusteredIndex;\n if (!hasMeaningfulOptions) return undefined;\n\n return new MongoSchemaCollectionOptions({\n ...(capped ? { capped: { size: size ?? 0, ...(max != null ? { max } : {}) } } : {}),\n ...(timeseries ? { timeseries } : {}),\n ...(collation ? { collation } : {}),\n ...(changeStreamPreAndPostImages ? { changeStreamPreAndPostImages } : {}),\n ...(clusteredIndex ? { clusteredIndex } : {}),\n });\n}\n\nexport async function introspectSchema(db: Db): Promise<MongoSchemaIR> {\n const collectionInfos = await db.listCollections().toArray();\n\n const collections: MongoSchemaCollection[] = [];\n\n for (const info of collectionInfos) {\n const name = info['name'] as string;\n const type = info['type'] as string | undefined;\n\n if (name === PRISMA_MIGRATIONS_COLLECTION) continue;\n if (name.startsWith('system.')) continue;\n if (type === 'view') continue;\n\n const indexDocs = await db.collection(name).listIndexes().toArray();\n const indexes = indexDocs.filter((doc) => !isDefaultIdIndex(doc)).map(parseIndex);\n\n const infoOptions = 'options' in info ? (info['options'] as Record<string, unknown>) : {};\n const validator = parseValidator(infoOptions);\n const options = parseCollectionOptions(info);\n\n collections.push(\n new MongoSchemaCollection({\n name,\n indexes,\n ...(validator ? { validator } : {}),\n ...(options ? { options } : {}),\n }),\n );\n }\n\n return new MongoSchemaIR(collections);\n}\n","import type { ContractMarkerRecord } from '@prisma-next/contract/types';\nimport { parseMarkerRowSafely } from '@prisma-next/errors/execution';\nimport { type } from 'arktype';\n\nexport const COLLECTION = '_prisma_migrations';\nexport const MONGO_MARKER_COLLECTION = `_prisma_migrations marker documents in ${COLLECTION}`;\nexport const MONGO_LEDGER_COLLECTION = `_prisma_migrations ledger documents in ${COLLECTION}`;\n\nconst MongoMarkerDocSchema = type({\n space: 'string',\n storageHash: 'string',\n profileHash: 'string',\n 'contractJson?': 'unknown | null',\n 'canonicalVersion?': 'number | null',\n 'updatedAt?': 'Date',\n 'appTag?': 'string | null',\n 'meta?': type({ '[string]': 'unknown' }).or('null'),\n 'invariants?': type('string').array(),\n '+': 'delete',\n});\n\nexport function parseMongoMarkerDoc(doc: unknown): ContractMarkerRecord {\n const result = MongoMarkerDocSchema(doc);\n if (result instanceof type.errors) {\n throw new Error(`Invalid marker doc on ${COLLECTION}: ${result.summary}`);\n }\n return {\n storageHash: result.storageHash,\n profileHash: result.profileHash,\n contractJson: result.contractJson ?? null,\n canonicalVersion: result.canonicalVersion ?? null,\n updatedAt: result.updatedAt ?? new Date(),\n appTag: result.appTag ?? null,\n meta: result.meta ?? {},\n invariants: result.invariants ?? [],\n };\n}\n\nexport function parseMongoMarkerDocSafely(doc: unknown, space: string): ContractMarkerRecord {\n return parseMarkerRowSafely(doc, parseMongoMarkerDoc, {\n space,\n markerLocation: MONGO_MARKER_COLLECTION,\n });\n}\n","/**\n * Document shape of the `_prisma_migrations` collection, which stores both the\n * per-space contract **markers** (`space` / `storageHash` / … / `invariants`)\n * and the migration **ledger** entries (`type` / `edgeId` / … / `appliedAt`) —\n * so the shape is their union. Declared once so the contract-free field\n * accessor is typed without threading a contract, codecs, or paths at the call\n * sites.\n */\nexport type MarkerLedgerDocShape = {\n readonly _id: { readonly codecId: 'mongo/string@1'; readonly nullable: false };\n // Marker fields\n readonly space: { readonly codecId: 'mongo/string@1'; readonly nullable: false };\n readonly storageHash: { readonly codecId: 'mongo/string@1'; readonly nullable: false };\n readonly profileHash: { readonly codecId: 'mongo/string@1'; readonly nullable: false };\n readonly contractJson: { readonly codecId: 'mongo/string@1'; readonly nullable: true };\n readonly canonicalVersion: { readonly codecId: 'mongo/double@1'; readonly nullable: true };\n readonly updatedAt: { readonly codecId: 'mongo/date@1'; readonly nullable: false };\n readonly appTag: { readonly codecId: 'mongo/string@1'; readonly nullable: true };\n readonly meta: { readonly codecId: 'mongo/document@1'; readonly nullable: true };\n readonly invariants: { readonly codecId: 'mongo/array@1'; readonly nullable: false };\n // Ledger fields\n readonly type: { readonly codecId: 'mongo/string@1'; readonly nullable: false };\n readonly edgeId: { readonly codecId: 'mongo/string@1'; readonly nullable: false };\n readonly from: { readonly codecId: 'mongo/string@1'; readonly nullable: false };\n readonly to: { readonly codecId: 'mongo/string@1'; readonly nullable: false };\n readonly migrationName: { readonly codecId: 'mongo/string@1'; readonly nullable: false };\n readonly migrationHash: { readonly codecId: 'mongo/string@1'; readonly nullable: false };\n readonly operations: { readonly codecId: 'mongo/array@1'; readonly nullable: false };\n readonly appliedAt: { readonly codecId: 'mongo/date@1'; readonly nullable: false };\n};\n\nexport const MARKER_LEDGER_COLLECTION = '_prisma_migrations';\n","import type { ControlDriverInstance } from '@prisma-next/framework-components/control';\nimport type { MongoControlDriverInstance } from '@prisma-next/mongo-lowering';\n\nexport function isMongoControlDriver(\n driver: ControlDriverInstance<'mongo', string>,\n): driver is MongoControlDriverInstance {\n return (\n driver.familyId === 'mongo' &&\n driver.targetId === 'mongo' &&\n 'execute' in driver &&\n typeof driver.execute === 'function'\n );\n}\n","import type { ContractMarkerRecord } from '@prisma-next/contract/types';\nimport type { MongoControlAdapter } from '@prisma-next/family-mongo/control-adapter';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n} from '@prisma-next/framework-components/control';\nimport type { MongoAdapter, MongoDriver } from '@prisma-next/mongo-lowering';\nimport type {\n MongoDdlCommandVisitor,\n MongoInspectionCommandVisitor,\n} from '@prisma-next/mongo-query-ast/control';\nimport type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport type { Db } from 'mongodb';\nimport { createMongoAdapter } from '../mongo-adapter';\nimport { MongoCommandExecutor, MongoInspectionExecutor } from './command-executor';\nimport { MongoControlAdapterImpl } from './mongo-control-adapter';\nimport { isMongoControlDriver } from './mongo-control-driver';\n\nexport function extractDb(driver: ControlDriverInstance<'mongo', 'mongo'>): Db {\n if (!isMongoControlDriver(driver)) {\n throw new Error(\n 'Expected a Mongo control driver created by ' +\n 'mongoControlDriver.create() from `@prisma-next/driver-mongo/control`.',\n );\n }\n return driver.db;\n}\n\n/**\n * Marker / ledger operations the Mongo runner depends on. Every method\n * takes a `space` parameter so each loaded contract space addresses its\n * own marker row independently — see ADR 212 for the per-space\n * mechanism.\n */\nexport interface MarkerOperations {\n readMarker(space: string): Promise<ContractMarkerRecord | null>;\n initMarker(\n space: string,\n destination: {\n readonly storageHash: string;\n readonly profileHash: string;\n readonly invariants?: readonly string[];\n },\n ): Promise<void>;\n updateMarker(\n space: string,\n expectedFrom: string,\n destination: {\n readonly storageHash: string;\n readonly profileHash: string;\n readonly invariants?: readonly string[];\n },\n ): Promise<boolean>;\n writeLedgerEntry(\n space: string,\n entry: {\n readonly edgeId: string;\n readonly from: string;\n readonly to: string;\n readonly migrationName: string;\n readonly migrationHash: string;\n readonly operations: readonly unknown[];\n },\n ): Promise<void>;\n}\n\nexport interface MongoRunnerDependencies {\n readonly commandExecutor: MongoDdlCommandVisitor<Promise<void>>;\n readonly inspectionExecutor: MongoInspectionCommandVisitor<Promise<Record<string, unknown>[]>>;\n readonly adapter: MongoAdapter;\n readonly driver: MongoDriver;\n readonly markerOps: MarkerOperations;\n readonly introspectSchema: () => Promise<MongoSchemaIR>;\n}\n\n/**\n * Build the runner-dependencies envelope. `controlAdapter` is the\n * dispatch surface for wire-level Mongo CAS operations (marker reads,\n * marker advances, ledger appends, introspection); the envelope's\n * `markerOps` shim simply forwards each call through it. When the\n * caller already has a `MongoControlAdapter` on the control stack it\n * can pass it in; otherwise a default `MongoControlAdapterImpl` is\n * constructed locally.\n */\nexport function createMongoRunnerDeps(\n controlDriver: ControlDriverInstance<'mongo', 'mongo'>,\n driver: MongoDriver,\n // Vestigial after the family→adapter SPI refactor: the runner dependencies\n // now route every wire-level call through `controlAdapter`, so the `family`\n // instance is no longer consulted. Kept on the signature to avoid rippling\n // through ~14 call sites; a follow-up that already touches this factory\n // should drop the parameter outright.\n _family: ControlFamilyInstance<'mongo', MongoSchemaIR>,\n controlAdapter: MongoControlAdapter<'mongo'> = new MongoControlAdapterImpl(),\n): MongoRunnerDependencies {\n return {\n commandExecutor: new MongoCommandExecutor(extractDb(controlDriver)),\n inspectionExecutor: new MongoInspectionExecutor(extractDb(controlDriver)),\n adapter: createMongoAdapter(),\n driver,\n markerOps: {\n readMarker: (space) => controlAdapter.readMarker(controlDriver, space),\n initMarker: (space, dest) => controlAdapter.initMarker(controlDriver, space, dest),\n updateMarker: (space, expectedFrom, dest) =>\n controlAdapter.updateMarker(controlDriver, space, expectedFrom, dest),\n writeLedgerEntry: (space, entry) =>\n controlAdapter.writeLedgerEntry(controlDriver, space, entry),\n },\n introspectSchema: () => controlAdapter.introspectSchema(controlDriver),\n };\n}\n","import type { ContractMarkerRecord, LedgerEntryRecord } from '@prisma-next/contract/types';\nimport { withMarkerReadErrorHandling } from '@prisma-next/errors/execution';\nimport type { MongoControlAdapter } from '@prisma-next/family-mongo/control-adapter';\nimport type { ControlDriverInstance } from '@prisma-next/framework-components/control';\nimport { ledgerOriginFromStored } from '@prisma-next/migration-tools/ledger-origin';\nimport type { MongoAdapter } from '@prisma-next/mongo-lowering';\nimport {\n type AnyMongoCommand,\n MongoAggFieldRef,\n MongoAggLiteral,\n MongoAggOperator,\n type MongoQueryPlan,\n} from '@prisma-next/mongo-query-ast/execution';\nimport { expr, fn } from '@prisma-next/mongo-query-builder';\nimport { collection } from '@prisma-next/mongo-query-builder/contract-free';\nimport type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport type { MongoValue } from '@prisma-next/mongo-value';\nimport { blindCast } from '@prisma-next/utils/casts';\nimport type { Document } from 'mongodb';\nimport { createMongoAdapter } from '../mongo-adapter';\nimport { introspectSchema } from './introspect-schema';\nimport {\n MONGO_LEDGER_COLLECTION,\n MONGO_MARKER_COLLECTION,\n parseMongoMarkerDocSafely,\n} from './marker-ledger';\nimport { MARKER_LEDGER_COLLECTION, type MarkerLedgerDocShape } from './marker-ledger-collection';\nimport { isMongoControlDriver } from './mongo-control-driver';\nimport { extractDb } from './runner-deps';\n\n/**\n * Mongo control adapter for control-plane operations like introspection\n * and marker-ledger CAS. Implements the family-level `MongoControlAdapter`\n * SPI. Every marker/ledger operation builds a canonical command inline via\n * the contract-free fluent builder and dispatches it through the family\n * adapter's lowering path (`createMongoAdapter().lower(plan, {})`) onto the\n * Mongo wire transport (`driver.execute(wireCommand)`) — the same route SQL\n * marker/ledger ops take through `adapter.lower()` → `driver.query()`.\n */\nexport class MongoControlAdapterImpl implements MongoControlAdapter<'mongo'> {\n readonly familyId = 'mongo' as const;\n readonly targetId = 'mongo' as const;\n readonly #adapter: MongoAdapter = createMongoAdapter();\n readonly #markerLedgerCollection = collection<MarkerLedgerDocShape>(MARKER_LEDGER_COLLECTION);\n\n async #execute(\n driver: ControlDriverInstance<'mongo', 'mongo'>,\n command: AnyMongoCommand,\n ): Promise<Document[]> {\n const plan: MongoQueryPlan = {\n collection: MARKER_LEDGER_COLLECTION,\n command,\n meta: { target: 'mongo', targetFamily: 'mongo', storageHash: '', lane: 'control' },\n };\n const wireCommand = await this.#adapter.lower(plan, {});\n if (!isMongoControlDriver(driver)) {\n throw new Error(\n 'Mongo control adapter requires a Mongo control driver with an execute() transport. ' +\n 'Provide a MongoControlDriver from `@prisma-next/driver-mongo/control`.',\n );\n }\n const rows: Document[] = [];\n for await (const row of driver.execute<Document>(wireCommand)) {\n rows.push(row);\n }\n return rows;\n }\n\n /**\n * Server-side invariant-merge aggregation expression:\n * `$sortArray({ input: $setUnion([$ifNull('$invariants', []), incoming]), sortBy: 1 })`.\n *\n * Built through the typed agg-expr layer — `fn.setUnion` plus the generic\n * `MongoAggOperator` for `$ifNull` / `$sortArray` (neither has a named `fn`\n * helper). Returns a `MongoAggOperator` that is passed directly to\n * `f.stage.set({ invariants: ... })` in the update pipeline.\n */\n #invariantMergeExpr(incoming: readonly string[]): MongoAggOperator {\n const existingOrEmpty = MongoAggOperator.of('$ifNull', [\n MongoAggFieldRef.of('invariants'),\n MongoAggLiteral.of([]),\n ]);\n const merged = fn.setUnion(\n { _field: { codecId: 'mongo/array@1', nullable: false }, node: existingOrEmpty },\n {\n _field: { codecId: 'mongo/array@1', nullable: false },\n node: MongoAggLiteral.of([...incoming]),\n },\n );\n return MongoAggOperator.of('$sortArray', { input: merged.node, sortBy: MongoAggLiteral.of(1) });\n }\n\n async readMarker(\n driver: ControlDriverInstance<'mongo', 'mongo'>,\n space: string,\n ): Promise<ContractMarkerRecord | null> {\n const markerContext = { space, markerLocation: MONGO_MARKER_COLLECTION };\n const docs = await withMarkerReadErrorHandling(\n () =>\n this.#execute(\n driver,\n this.#markerLedgerCollection\n .aggregate()\n .match((f) => f._id.eq(space))\n .match((f) => f.space.eq(space))\n .limit(1)\n .build(),\n ),\n markerContext,\n );\n const doc = docs[0];\n if (!doc) return null;\n return parseMongoMarkerDocSafely(doc, space);\n }\n\n async readAllMarkers(\n driver: ControlDriverInstance<'mongo', 'mongo'>,\n ): Promise<ReadonlyMap<string, ContractMarkerRecord>> {\n const markerContext = { space: 'app', markerLocation: MONGO_MARKER_COLLECTION };\n const docs = await withMarkerReadErrorHandling(\n () =>\n this.#execute(\n driver,\n this.#markerLedgerCollection\n .aggregate()\n .match((f) => f._id.type('string'))\n .match((f) => f.space.type('string'))\n .match((f) => expr(fn.eq(f._id, f.space)))\n .build(),\n ),\n markerContext,\n );\n const out = new Map<string, ContractMarkerRecord>();\n for (const doc of docs) {\n const space = doc['space'];\n /* v8 ignore next -- @preserve type-narrowing guard: the $match stage above filters on `space: { $type: 'string' }`, so this branch is unreachable at runtime. The check exists so the `out.set(space, ...)` call below can accept `string`. */\n if (typeof space !== 'string') continue;\n out.set(space, parseMongoMarkerDocSafely(doc, space));\n }\n return out;\n }\n\n async initMarker(\n driver: ControlDriverInstance<'mongo', 'mongo'>,\n space: string,\n destination: {\n readonly storageHash: string;\n readonly profileHash: string;\n readonly invariants?: readonly string[];\n },\n ): Promise<void> {\n const document: Record<string, MongoValue> = {\n _id: space,\n space,\n storageHash: destination.storageHash,\n profileHash: destination.profileHash,\n contractJson: null,\n canonicalVersion: null,\n updatedAt: new Date(),\n appTag: null,\n meta: {},\n invariants: [...(destination.invariants ?? [])],\n };\n await this.#execute(driver, this.#markerLedgerCollection.insertOne(document));\n }\n\n async updateMarker(\n driver: ControlDriverInstance<'mongo', 'mongo'>,\n space: string,\n expectedFrom: string,\n destination: {\n readonly storageHash: string;\n readonly profileHash: string;\n readonly invariants?: readonly string[];\n },\n ): Promise<boolean> {\n const { invariants } = destination;\n const docs = await this.#execute(\n driver,\n this.#markerLedgerCollection\n .match((f) => f._id.eq(space))\n .match((f) => f.space.eq(space))\n .match((f) => f.storageHash.eq(expectedFrom))\n .findOneAndUpdate(\n (f) => [\n f.stage.set(\n invariants === undefined\n ? {\n storageHash: MongoAggLiteral.of(destination.storageHash),\n profileHash: MongoAggLiteral.of(destination.profileHash),\n updatedAt: MongoAggLiteral.of(new Date()),\n }\n : {\n storageHash: MongoAggLiteral.of(destination.storageHash),\n profileHash: MongoAggLiteral.of(destination.profileHash),\n updatedAt: MongoAggLiteral.of(new Date()),\n invariants: this.#invariantMergeExpr(invariants),\n },\n ),\n ],\n { upsert: false },\n ),\n );\n return docs.length > 0;\n }\n\n async writeLedgerEntry(\n driver: ControlDriverInstance<'mongo', 'mongo'>,\n space: string,\n entry: {\n readonly edgeId: string;\n readonly from: string;\n readonly to: string;\n readonly migrationName: string;\n readonly migrationHash: string;\n readonly operations: readonly unknown[];\n },\n ): Promise<void> {\n const document: Record<string, MongoValue> = {\n type: 'ledger',\n space,\n edgeId: entry.edgeId,\n from: entry.from,\n to: entry.to,\n migrationName: entry.migrationName,\n migrationHash: entry.migrationHash,\n operations: blindCast<ReadonlyArray<MongoValue>, 'ledger operation docs are BSON values'>(\n entry.operations,\n ),\n appliedAt: new Date(),\n };\n await this.#execute(driver, this.#markerLedgerCollection.insertOne(document));\n }\n\n async readLedger(\n driver: ControlDriverInstance<'mongo', 'mongo'>,\n space?: string,\n ): Promise<readonly LedgerEntryRecord[]> {\n const ledgerContext = { space: space ?? '*', markerLocation: MONGO_LEDGER_COLLECTION };\n const chain = this.#markerLedgerCollection.aggregate().match((f) => f.type.eq('ledger'));\n const command =\n space === undefined\n ? chain.sort({ _id: 1 }).build()\n : chain\n .match((f) => f.space.eq(space))\n .sort({ _id: 1 })\n .build();\n const docs = await withMarkerReadErrorHandling(\n () => this.#execute(driver, command),\n ledgerContext,\n );\n\n const entries: LedgerEntryRecord[] = [];\n for (const doc of docs) {\n const migrationName = doc['migrationName'];\n const migrationHash = doc['migrationHash'];\n const from = doc['from'];\n const to = doc['to'];\n const docSpace = doc['space'];\n if (typeof migrationName !== 'string' || typeof migrationHash !== 'string') {\n continue;\n }\n if (typeof from !== 'string' || typeof to !== 'string') {\n continue;\n }\n if (typeof docSpace !== 'string') {\n continue;\n }\n const appliedAt = doc['appliedAt'];\n const appliedAtDate =\n appliedAt instanceof Date\n ? appliedAt\n : appliedAt !== undefined\n ? new Date(String(appliedAt))\n : new Date();\n const operations = doc['operations'];\n const opList = Array.isArray(operations) ? operations : [];\n entries.push({\n space: docSpace,\n migrationName,\n migrationHash,\n from: ledgerOriginFromStored(from),\n to,\n appliedAt: appliedAtDate,\n operationCount: opList.length,\n });\n }\n return entries;\n }\n\n async introspectSchema(driver: ControlDriverInstance<'mongo', 'mongo'>): Promise<MongoSchemaIR> {\n return introspectSchema(extractDb(driver));\n }\n}\n","import type { MongoControlAdapterDescriptor } from '@prisma-next/family-mongo/control-adapter';\nimport type { MongoControlDriverInstance } from '@prisma-next/mongo-lowering';\n\nexport { MongoCommandExecutor, MongoInspectionExecutor } from '../core/command-executor';\nexport { introspectSchema } from '../core/introspect-schema';\nexport { MongoControlAdapterImpl } from '../core/mongo-control-adapter';\nexport { isMongoControlDriver } from '../core/mongo-control-driver';\nexport {\n createMongoRunnerDeps,\n extractDb,\n type MarkerOperations,\n type MongoRunnerDependencies,\n} from '../core/runner-deps';\nexport { createMongoAdapter } from '../mongo-adapter';\nexport type { MongoControlDriverInstance };\n\nimport { mongoCodecDescriptors } from '../core/codecs';\nimport { MongoControlAdapterImpl } from '../core/mongo-control-adapter';\n\nexport const mongoAdapterDescriptor: MongoControlAdapterDescriptor<'mongo'> = {\n kind: 'adapter',\n id: 'mongo',\n familyId: 'mongo',\n targetId: 'mongo',\n version: '0.0.1',\n scalarTypeDescriptors: new Map([\n ['String', 'mongo/string@1'],\n ['Int', 'mongo/int32@1'],\n ['Boolean', 'mongo/bool@1'],\n ['DateTime', 'mongo/date@1'],\n ['ObjectId', 'mongo/objectId@1'],\n ['Float', 'mongo/double@1'],\n ]),\n types: {\n codecTypes: {\n codecDescriptors: mongoCodecDescriptors,\n import: {\n package: '@prisma-next/adapter-mongo/codec-types',\n named: 'CodecTypes',\n alias: 'MongoCodecTypes',\n },\n typeImports: [\n {\n package: '@prisma-next/adapter-mongo/codec-types',\n named: 'Vector',\n alias: 'Vector',\n },\n ],\n },\n },\n create(_stack) {\n return new MongoControlAdapterImpl();\n },\n};\n\nexport default mongoAdapterDescriptor;\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,36 +1,38 @@
1
1
  {
2
2
  "name": "@prisma-next/adapter-mongo",
3
- "version": "0.12.0-dev.50",
3
+ "version": "0.12.0-dev.52",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "description": "MongoDB adapter for Prisma Next (lowers commands to wire format)",
8
8
  "dependencies": {
9
- "@prisma-next/config": "0.12.0-dev.50",
10
- "@prisma-next/contract": "0.12.0-dev.50",
11
- "@prisma-next/errors": "0.12.0-dev.50",
12
- "@prisma-next/family-mongo": "0.12.0-dev.50",
13
- "@prisma-next/framework-components": "0.12.0-dev.50",
14
- "@prisma-next/migration-tools": "0.12.0-dev.50",
15
- "@prisma-next/mongo-codec": "0.12.0-dev.50",
16
- "@prisma-next/mongo-contract": "0.12.0-dev.50",
17
- "@prisma-next/mongo-lowering": "0.12.0-dev.50",
18
- "@prisma-next/mongo-query-ast": "0.12.0-dev.50",
19
- "@prisma-next/mongo-schema-ir": "0.12.0-dev.50",
20
- "@prisma-next/mongo-value": "0.12.0-dev.50",
21
- "@prisma-next/mongo-wire": "0.12.0-dev.50",
22
- "@prisma-next/operations": "0.12.0-dev.50",
23
- "@prisma-next/utils": "0.12.0-dev.50",
9
+ "@prisma-next/config": "0.12.0-dev.52",
10
+ "@prisma-next/contract": "0.12.0-dev.52",
11
+ "@prisma-next/errors": "0.12.0-dev.52",
12
+ "@prisma-next/family-mongo": "0.12.0-dev.52",
13
+ "@prisma-next/framework-components": "0.12.0-dev.52",
14
+ "@prisma-next/migration-tools": "0.12.0-dev.52",
15
+ "@prisma-next/mongo-codec": "0.12.0-dev.52",
16
+ "@prisma-next/mongo-contract": "0.12.0-dev.52",
17
+ "@prisma-next/mongo-lowering": "0.12.0-dev.52",
18
+ "@prisma-next/mongo-query-ast": "0.12.0-dev.52",
19
+ "@prisma-next/mongo-query-builder": "0.12.0-dev.52",
20
+ "@prisma-next/mongo-schema-ir": "0.12.0-dev.52",
21
+ "@prisma-next/mongo-value": "0.12.0-dev.52",
22
+ "@prisma-next/mongo-wire": "0.12.0-dev.52",
23
+ "@prisma-next/operations": "0.12.0-dev.52",
24
+ "@prisma-next/utils": "0.12.0-dev.52",
24
25
  "arktype": "^2.2.0"
25
26
  },
26
27
  "devDependencies": {
27
28
  "mongodb": "^7.2.0",
28
- "@prisma-next/errors": "0.12.0-dev.50",
29
- "@prisma-next/mongo-contract-psl": "0.12.0-dev.50",
30
- "@prisma-next/psl-parser": "0.12.0-dev.50",
31
- "@prisma-next/test-utils": "0.12.0-dev.50",
32
- "@prisma-next/tsconfig": "0.12.0-dev.50",
33
- "@prisma-next/tsdown": "0.12.0-dev.50",
29
+ "@prisma-next/driver-mongo": "0.12.0-dev.52",
30
+ "@prisma-next/errors": "0.12.0-dev.52",
31
+ "@prisma-next/mongo-contract-psl": "0.12.0-dev.52",
32
+ "@prisma-next/psl-parser": "0.12.0-dev.52",
33
+ "@prisma-next/test-utils": "0.12.0-dev.52",
34
+ "@prisma-next/tsconfig": "0.12.0-dev.52",
35
+ "@prisma-next/tsdown": "0.12.0-dev.52",
34
36
  "mongodb-memory-server": "11.1.0",
35
37
  "tsdown": "0.22.0",
36
38
  "typescript": "5.9.3",
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Document shape of the `_prisma_migrations` collection, which stores both the
3
+ * per-space contract **markers** (`space` / `storageHash` / … / `invariants`)
4
+ * and the migration **ledger** entries (`type` / `edgeId` / … / `appliedAt`) —
5
+ * so the shape is their union. Declared once so the contract-free field
6
+ * accessor is typed without threading a contract, codecs, or paths at the call
7
+ * sites.
8
+ */
9
+ export type MarkerLedgerDocShape = {
10
+ readonly _id: { readonly codecId: 'mongo/string@1'; readonly nullable: false };
11
+ // Marker fields
12
+ readonly space: { readonly codecId: 'mongo/string@1'; readonly nullable: false };
13
+ readonly storageHash: { readonly codecId: 'mongo/string@1'; readonly nullable: false };
14
+ readonly profileHash: { readonly codecId: 'mongo/string@1'; readonly nullable: false };
15
+ readonly contractJson: { readonly codecId: 'mongo/string@1'; readonly nullable: true };
16
+ readonly canonicalVersion: { readonly codecId: 'mongo/double@1'; readonly nullable: true };
17
+ readonly updatedAt: { readonly codecId: 'mongo/date@1'; readonly nullable: false };
18
+ readonly appTag: { readonly codecId: 'mongo/string@1'; readonly nullable: true };
19
+ readonly meta: { readonly codecId: 'mongo/document@1'; readonly nullable: true };
20
+ readonly invariants: { readonly codecId: 'mongo/array@1'; readonly nullable: false };
21
+ // Ledger fields
22
+ readonly type: { readonly codecId: 'mongo/string@1'; readonly nullable: false };
23
+ readonly edgeId: { readonly codecId: 'mongo/string@1'; readonly nullable: false };
24
+ readonly from: { readonly codecId: 'mongo/string@1'; readonly nullable: false };
25
+ readonly to: { readonly codecId: 'mongo/string@1'; readonly nullable: false };
26
+ readonly migrationName: { readonly codecId: 'mongo/string@1'; readonly nullable: false };
27
+ readonly migrationHash: { readonly codecId: 'mongo/string@1'; readonly nullable: false };
28
+ readonly operations: { readonly codecId: 'mongo/array@1'; readonly nullable: false };
29
+ readonly appliedAt: { readonly codecId: 'mongo/date@1'; readonly nullable: false };
30
+ };
31
+
32
+ export const MARKER_LEDGER_COLLECTION = '_prisma_migrations';
@@ -1,12 +1,6 @@
1
1
  import type { ContractMarkerRecord } from '@prisma-next/contract/types';
2
2
  import { parseMarkerRowSafely } from '@prisma-next/errors/execution';
3
- import type {
4
- RawAggregateCommand,
5
- RawFindOneAndUpdateCommand,
6
- RawInsertOneCommand,
7
- } from '@prisma-next/mongo-query-ast/execution';
8
3
  import { type } from 'arktype';
9
- import type { Db, Document, UpdateFilter } from 'mongodb';
10
4
 
11
5
  export const COLLECTION = '_prisma_migrations';
12
6
  export const MONGO_MARKER_COLLECTION = `_prisma_migrations marker documents in ${COLLECTION}`;
@@ -37,7 +31,7 @@ export function parseMongoMarkerDoc(doc: unknown): ContractMarkerRecord {
37
31
  canonicalVersion: result.canonicalVersion ?? null,
38
32
  updatedAt: result.updatedAt ?? new Date(),
39
33
  appTag: result.appTag ?? null,
40
- meta: (result.meta as Record<string, unknown> | null) ?? {},
34
+ meta: result.meta ?? {},
41
35
  invariants: result.invariants ?? [],
42
36
  };
43
37
  }
@@ -48,25 +42,3 @@ export function parseMongoMarkerDocSafely(doc: unknown, space: string): Contract
48
42
  markerLocation: MONGO_MARKER_COLLECTION,
49
43
  });
50
44
  }
51
-
52
- export async function executeAggregate(db: Db, cmd: RawAggregateCommand): Promise<Document[]> {
53
- return db
54
- .collection(cmd.collection)
55
- .aggregate(cmd.pipeline as Record<string, unknown>[])
56
- .toArray();
57
- }
58
-
59
- export async function executeInsertOne(db: Db, cmd: RawInsertOneCommand): Promise<void> {
60
- await db.collection(cmd.collection).insertOne(cmd.document);
61
- }
62
-
63
- export async function executeFindOneAndUpdate(
64
- db: Db,
65
- cmd: RawFindOneAndUpdateCommand,
66
- ): Promise<Document | null> {
67
- return db
68
- .collection(cmd.collection)
69
- .findOneAndUpdate(cmd.filter, cmd.update as UpdateFilter<Document> | Document[], {
70
- upsert: cmd.upsert,
71
- });
72
- }
@@ -3,46 +3,108 @@ import { withMarkerReadErrorHandling } from '@prisma-next/errors/execution';
3
3
  import type { MongoControlAdapter } from '@prisma-next/family-mongo/control-adapter';
4
4
  import type { ControlDriverInstance } from '@prisma-next/framework-components/control';
5
5
  import { ledgerOriginFromStored } from '@prisma-next/migration-tools/ledger-origin';
6
+ import type { MongoAdapter } from '@prisma-next/mongo-lowering';
6
7
  import {
7
- RawAggregateCommand,
8
- RawFindOneAndUpdateCommand,
9
- RawInsertOneCommand,
8
+ type AnyMongoCommand,
9
+ MongoAggFieldRef,
10
+ MongoAggLiteral,
11
+ MongoAggOperator,
12
+ type MongoQueryPlan,
10
13
  } from '@prisma-next/mongo-query-ast/execution';
14
+ import { expr, fn } from '@prisma-next/mongo-query-builder';
15
+ import { collection } from '@prisma-next/mongo-query-builder/contract-free';
11
16
  import type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';
17
+ import type { MongoValue } from '@prisma-next/mongo-value';
18
+ import { blindCast } from '@prisma-next/utils/casts';
12
19
  import type { Document } from 'mongodb';
20
+ import { createMongoAdapter } from '../mongo-adapter';
13
21
  import { introspectSchema } from './introspect-schema';
14
22
  import {
15
- COLLECTION,
16
- executeAggregate,
17
- executeFindOneAndUpdate,
18
- executeInsertOne,
19
23
  MONGO_LEDGER_COLLECTION,
20
24
  MONGO_MARKER_COLLECTION,
21
25
  parseMongoMarkerDocSafely,
22
26
  } from './marker-ledger';
27
+ import { MARKER_LEDGER_COLLECTION, type MarkerLedgerDocShape } from './marker-ledger-collection';
28
+ import { isMongoControlDriver } from './mongo-control-driver';
23
29
  import { extractDb } from './runner-deps';
24
30
 
25
31
  /**
26
32
  * Mongo control adapter for control-plane operations like introspection
27
33
  * and marker-ledger CAS. Implements the family-level `MongoControlAdapter`
28
- * SPI by extracting the underlying `Db` from the framework-shaped driver
29
- * per call.
34
+ * SPI. Every marker/ledger operation builds a canonical command inline via
35
+ * the contract-free fluent builder and dispatches it through the family
36
+ * adapter's lowering path (`createMongoAdapter().lower(plan, {})`) onto the
37
+ * Mongo wire transport (`driver.execute(wireCommand)`) — the same route SQL
38
+ * marker/ledger ops take through `adapter.lower()` → `driver.query()`.
30
39
  */
31
40
  export class MongoControlAdapterImpl implements MongoControlAdapter<'mongo'> {
32
41
  readonly familyId = 'mongo' as const;
33
42
  readonly targetId = 'mongo' as const;
43
+ readonly #adapter: MongoAdapter = createMongoAdapter();
44
+ readonly #markerLedgerCollection = collection<MarkerLedgerDocShape>(MARKER_LEDGER_COLLECTION);
45
+
46
+ async #execute(
47
+ driver: ControlDriverInstance<'mongo', 'mongo'>,
48
+ command: AnyMongoCommand,
49
+ ): Promise<Document[]> {
50
+ const plan: MongoQueryPlan = {
51
+ collection: MARKER_LEDGER_COLLECTION,
52
+ command,
53
+ meta: { target: 'mongo', targetFamily: 'mongo', storageHash: '', lane: 'control' },
54
+ };
55
+ const wireCommand = await this.#adapter.lower(plan, {});
56
+ if (!isMongoControlDriver(driver)) {
57
+ throw new Error(
58
+ 'Mongo control adapter requires a Mongo control driver with an execute() transport. ' +
59
+ 'Provide a MongoControlDriver from `@prisma-next/driver-mongo/control`.',
60
+ );
61
+ }
62
+ const rows: Document[] = [];
63
+ for await (const row of driver.execute<Document>(wireCommand)) {
64
+ rows.push(row);
65
+ }
66
+ return rows;
67
+ }
68
+
69
+ /**
70
+ * Server-side invariant-merge aggregation expression:
71
+ * `$sortArray({ input: $setUnion([$ifNull('$invariants', []), incoming]), sortBy: 1 })`.
72
+ *
73
+ * Built through the typed agg-expr layer — `fn.setUnion` plus the generic
74
+ * `MongoAggOperator` for `$ifNull` / `$sortArray` (neither has a named `fn`
75
+ * helper). Returns a `MongoAggOperator` that is passed directly to
76
+ * `f.stage.set({ invariants: ... })` in the update pipeline.
77
+ */
78
+ #invariantMergeExpr(incoming: readonly string[]): MongoAggOperator {
79
+ const existingOrEmpty = MongoAggOperator.of('$ifNull', [
80
+ MongoAggFieldRef.of('invariants'),
81
+ MongoAggLiteral.of([]),
82
+ ]);
83
+ const merged = fn.setUnion(
84
+ { _field: { codecId: 'mongo/array@1', nullable: false }, node: existingOrEmpty },
85
+ {
86
+ _field: { codecId: 'mongo/array@1', nullable: false },
87
+ node: MongoAggLiteral.of([...incoming]),
88
+ },
89
+ );
90
+ return MongoAggOperator.of('$sortArray', { input: merged.node, sortBy: MongoAggLiteral.of(1) });
91
+ }
34
92
 
35
93
  async readMarker(
36
94
  driver: ControlDriverInstance<'mongo', 'mongo'>,
37
95
  space: string,
38
96
  ): Promise<ContractMarkerRecord | null> {
39
- const db = extractDb(driver);
40
97
  const markerContext = { space, markerLocation: MONGO_MARKER_COLLECTION };
41
98
  const docs = await withMarkerReadErrorHandling(
42
99
  () =>
43
- executeAggregate(
44
- db,
45
- new RawAggregateCommand(COLLECTION, [{ $match: { _id: space, space } }, { $limit: 1 }]),
100
+ this.#execute(
101
+ driver,
102
+ this.#markerLedgerCollection
103
+ .aggregate()
104
+ .match((f) => f._id.eq(space))
105
+ .match((f) => f.space.eq(space))
106
+ .limit(1)
107
+ .build(),
46
108
  ),
47
109
  markerContext,
48
110
  );
@@ -54,21 +116,17 @@ export class MongoControlAdapterImpl implements MongoControlAdapter<'mongo'> {
54
116
  async readAllMarkers(
55
117
  driver: ControlDriverInstance<'mongo', 'mongo'>,
56
118
  ): Promise<ReadonlyMap<string, ContractMarkerRecord>> {
57
- const db = extractDb(driver);
58
119
  const markerContext = { space: 'app', markerLocation: MONGO_MARKER_COLLECTION };
59
120
  const docs = await withMarkerReadErrorHandling(
60
121
  () =>
61
- executeAggregate(
62
- db,
63
- new RawAggregateCommand(COLLECTION, [
64
- {
65
- $match: {
66
- _id: { $type: 'string' },
67
- space: { $type: 'string' },
68
- $expr: { $eq: ['$_id', '$space'] },
69
- },
70
- },
71
- ]),
122
+ this.#execute(
123
+ driver,
124
+ this.#markerLedgerCollection
125
+ .aggregate()
126
+ .match((f) => f._id.type('string'))
127
+ .match((f) => f.space.type('string'))
128
+ .match((f) => expr(fn.eq(f._id, f.space)))
129
+ .build(),
72
130
  ),
73
131
  markerContext,
74
132
  );
@@ -91,8 +149,7 @@ export class MongoControlAdapterImpl implements MongoControlAdapter<'mongo'> {
91
149
  readonly invariants?: readonly string[];
92
150
  },
93
151
  ): Promise<void> {
94
- const db = extractDb(driver);
95
- const cmd = new RawInsertOneCommand(COLLECTION, {
152
+ const document: Record<string, MongoValue> = {
96
153
  _id: space,
97
154
  space,
98
155
  storageHash: destination.storageHash,
@@ -102,9 +159,9 @@ export class MongoControlAdapterImpl implements MongoControlAdapter<'mongo'> {
102
159
  updatedAt: new Date(),
103
160
  appTag: null,
104
161
  meta: {},
105
- invariants: destination.invariants ?? [],
106
- });
107
- await executeInsertOne(db, cmd);
162
+ invariants: [...(destination.invariants ?? [])],
163
+ };
164
+ await this.#execute(driver, this.#markerLedgerCollection.insertOne(document));
108
165
  }
109
166
 
110
167
  async updateMarker(
@@ -117,38 +174,34 @@ export class MongoControlAdapterImpl implements MongoControlAdapter<'mongo'> {
117
174
  readonly invariants?: readonly string[];
118
175
  },
119
176
  ): Promise<boolean> {
120
- const db = extractDb(driver);
121
- const setBase: Record<string, unknown> = {
122
- storageHash: destination.storageHash,
123
- profileHash: destination.profileHash,
124
- updatedAt: new Date(),
125
- };
126
- const update: Document | Document[] =
127
- destination.invariants === undefined
128
- ? { $set: setBase }
129
- : [
130
- {
131
- $set: {
132
- ...setBase,
133
- invariants: {
134
- $sortArray: {
135
- input: {
136
- $setUnion: [{ $ifNull: ['$invariants', []] }, destination.invariants],
137
- },
138
- sortBy: 1,
177
+ const { invariants } = destination;
178
+ const docs = await this.#execute(
179
+ driver,
180
+ this.#markerLedgerCollection
181
+ .match((f) => f._id.eq(space))
182
+ .match((f) => f.space.eq(space))
183
+ .match((f) => f.storageHash.eq(expectedFrom))
184
+ .findOneAndUpdate(
185
+ (f) => [
186
+ f.stage.set(
187
+ invariants === undefined
188
+ ? {
189
+ storageHash: MongoAggLiteral.of(destination.storageHash),
190
+ profileHash: MongoAggLiteral.of(destination.profileHash),
191
+ updatedAt: MongoAggLiteral.of(new Date()),
192
+ }
193
+ : {
194
+ storageHash: MongoAggLiteral.of(destination.storageHash),
195
+ profileHash: MongoAggLiteral.of(destination.profileHash),
196
+ updatedAt: MongoAggLiteral.of(new Date()),
197
+ invariants: this.#invariantMergeExpr(invariants),
139
198
  },
140
- },
141
- },
142
- },
143
- ];
144
- const cmd = new RawFindOneAndUpdateCommand(
145
- COLLECTION,
146
- { _id: space, space, storageHash: expectedFrom },
147
- update,
148
- false,
199
+ ),
200
+ ],
201
+ { upsert: false },
202
+ ),
149
203
  );
150
- const result = await executeFindOneAndUpdate(db, cmd);
151
- return result !== null;
204
+ return docs.length > 0;
152
205
  }
153
206
 
154
207
  async writeLedgerEntry(
@@ -163,8 +216,7 @@ export class MongoControlAdapterImpl implements MongoControlAdapter<'mongo'> {
163
216
  readonly operations: readonly unknown[];
164
217
  },
165
218
  ): Promise<void> {
166
- const db = extractDb(driver);
167
- const cmd = new RawInsertOneCommand(COLLECTION, {
219
+ const document: Record<string, MongoValue> = {
168
220
  type: 'ledger',
169
221
  space,
170
222
  edgeId: entry.edgeId,
@@ -172,28 +224,29 @@ export class MongoControlAdapterImpl implements MongoControlAdapter<'mongo'> {
172
224
  to: entry.to,
173
225
  migrationName: entry.migrationName,
174
226
  migrationHash: entry.migrationHash,
175
- operations: entry.operations,
227
+ operations: blindCast<ReadonlyArray<MongoValue>, 'ledger operation docs are BSON values'>(
228
+ entry.operations,
229
+ ),
176
230
  appliedAt: new Date(),
177
- });
178
- await executeInsertOne(db, cmd);
231
+ };
232
+ await this.#execute(driver, this.#markerLedgerCollection.insertOne(document));
179
233
  }
180
234
 
181
235
  async readLedger(
182
236
  driver: ControlDriverInstance<'mongo', 'mongo'>,
183
237
  space?: string,
184
238
  ): Promise<readonly LedgerEntryRecord[]> {
185
- const db = extractDb(driver);
186
239
  const ledgerContext = { space: space ?? '*', markerLocation: MONGO_LEDGER_COLLECTION };
187
- const matchStage: Record<string, unknown> = { type: 'ledger' };
188
- if (space !== undefined) {
189
- matchStage['space'] = space;
190
- }
240
+ const chain = this.#markerLedgerCollection.aggregate().match((f) => f.type.eq('ledger'));
241
+ const command =
242
+ space === undefined
243
+ ? chain.sort({ _id: 1 }).build()
244
+ : chain
245
+ .match((f) => f.space.eq(space))
246
+ .sort({ _id: 1 })
247
+ .build();
191
248
  const docs = await withMarkerReadErrorHandling(
192
- () =>
193
- executeAggregate(
194
- db,
195
- new RawAggregateCommand(COLLECTION, [{ $match: matchStage }, { $sort: { _id: 1 } }]),
196
- ),
249
+ () => this.#execute(driver, command),
197
250
  ledgerContext,
198
251
  );
199
252
 
@@ -4,5 +4,10 @@ import type { MongoControlDriverInstance } from '@prisma-next/mongo-lowering';
4
4
  export function isMongoControlDriver(
5
5
  driver: ControlDriverInstance<'mongo', string>,
6
6
  ): driver is MongoControlDriverInstance {
7
- return driver.familyId === 'mongo' && driver.targetId === 'mongo';
7
+ return (
8
+ driver.familyId === 'mongo' &&
9
+ driver.targetId === 'mongo' &&
10
+ 'execute' in driver &&
11
+ typeof driver.execute === 'function'
12
+ );
8
13
  }
@@ -1,9 +1,6 @@
1
- import type { ContractMarkerRecord, LedgerEntryRecord } from '@prisma-next/contract/types';
2
1
  import type { MongoControlAdapterDescriptor } from '@prisma-next/family-mongo/control-adapter';
3
- import type { ControlDriverInstance } from '@prisma-next/framework-components/control';
4
- import type { Db } from 'mongodb';
2
+ import type { MongoControlDriverInstance } from '@prisma-next/mongo-lowering';
5
3
 
6
- export type { MongoControlDriverInstance } from '@prisma-next/mongo-lowering';
7
4
  export { MongoCommandExecutor, MongoInspectionExecutor } from '../core/command-executor';
8
5
  export { introspectSchema } from '../core/introspect-schema';
9
6
  export { MongoControlAdapterImpl } from '../core/mongo-control-adapter';
@@ -15,78 +12,11 @@ export {
15
12
  type MongoRunnerDependencies,
16
13
  } from '../core/runner-deps';
17
14
  export { createMongoAdapter } from '../mongo-adapter';
15
+ export type { MongoControlDriverInstance };
18
16
 
19
17
  import { mongoCodecDescriptors } from '../core/codecs';
20
18
  import { MongoControlAdapterImpl } from '../core/mongo-control-adapter';
21
19
 
22
- const defaultControlAdapter = new MongoControlAdapterImpl();
23
-
24
- function controlDriverFromDb(db: Db): ControlDriverInstance<'mongo', 'mongo'> & { db: Db } {
25
- return {
26
- familyId: 'mongo',
27
- targetId: 'mongo',
28
- db,
29
- close: async () => {},
30
- };
31
- }
32
-
33
- export async function readMarker(db: Db, space: string): Promise<ContractMarkerRecord | null> {
34
- return defaultControlAdapter.readMarker(controlDriverFromDb(db), space);
35
- }
36
-
37
- export async function readAllMarkers(db: Db): Promise<ReadonlyMap<string, ContractMarkerRecord>> {
38
- return defaultControlAdapter.readAllMarkers(controlDriverFromDb(db));
39
- }
40
-
41
- export async function initMarker(
42
- db: Db,
43
- space: string,
44
- destination: {
45
- readonly storageHash: string;
46
- readonly profileHash: string;
47
- readonly invariants?: readonly string[];
48
- },
49
- ): Promise<void> {
50
- await defaultControlAdapter.initMarker(controlDriverFromDb(db), space, destination);
51
- }
52
-
53
- export async function updateMarker(
54
- db: Db,
55
- space: string,
56
- expectedFrom: string,
57
- destination: {
58
- readonly storageHash: string;
59
- readonly profileHash: string;
60
- readonly invariants?: readonly string[];
61
- },
62
- ): Promise<boolean> {
63
- return defaultControlAdapter.updateMarker(
64
- controlDriverFromDb(db),
65
- space,
66
- expectedFrom,
67
- destination,
68
- );
69
- }
70
-
71
- export async function readLedger(db: Db, space?: string): Promise<readonly LedgerEntryRecord[]> {
72
- return defaultControlAdapter.readLedger(controlDriverFromDb(db), space);
73
- }
74
-
75
- export async function writeLedgerEntry(
76
- db: Db,
77
- space: string,
78
- entry: {
79
- readonly edgeId: string;
80
- readonly from: string;
81
- readonly to: string;
82
- readonly migrationName: string;
83
- readonly migrationHash: string;
84
- readonly operations: readonly unknown[];
85
- },
86
- ): Promise<void> {
87
- await defaultControlAdapter.writeLedgerEntry(controlDriverFromDb(db), space, entry);
88
- }
89
-
90
20
  export const mongoAdapterDescriptor: MongoControlAdapterDescriptor<'mongo'> = {
91
21
  kind: 'adapter',
92
22
  id: 'mongo',