@prisma-next/adapter-mongo 0.12.0 → 0.13.0-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,11 @@
1
- import { t as createMongoAdapter } from "./mongo-adapter-JuKx_-h9.mjs";
2
- import { Db, Document, MongoClient } from "mongodb";
1
+ import { t as createMongoAdapter } from "./mongo-adapter-Ch21r_Sr.mjs";
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
5
  import { MongoControlAdapter, MongoControlAdapterDescriptor } from "@prisma-next/family-mongo/control-adapter";
6
- import { ContractMarkerRecord } from "@prisma-next/contract/types";
6
+ import { MongoAdapter, MongoControlDriverInstance, MongoControlDriverInstance as MongoControlDriverInstance$1, MongoDriver } from "@prisma-next/mongo-lowering";
7
+ import { ContractMarkerRecord, LedgerEntryRecord } from "@prisma-next/contract/types";
7
8
  import { ControlDriverInstance, ControlFamilyInstance } from "@prisma-next/framework-components/control";
8
- import { MongoAdapter, MongoDriver } from "@prisma-next/mongo-lowering";
9
9
 
10
10
  //#region src/core/command-executor.d.ts
11
11
  declare class MongoCommandExecutor implements MongoDdlCommandVisitor<Promise<void>> {
@@ -27,70 +27,18 @@ declare class MongoInspectionExecutor implements MongoInspectionCommandVisitor<P
27
27
  //#region src/core/introspect-schema.d.ts
28
28
  declare function introspectSchema(db: Db): Promise<MongoSchemaIR>;
29
29
  //#endregion
30
- //#region src/core/marker-ledger.d.ts
31
- /**
32
- * Reads the marker document for the given contract space, or returns
33
- * `null` if no marker has been written for that space yet. Each space
34
- * owns one row keyed by `_id: <space>` — see ADR 212 for the per-space
35
- * mechanism this enables.
36
- */
37
- declare function readMarker(db: Db, space: string): Promise<ContractMarkerRecord | null>;
38
- /**
39
- * Reads every marker doc in the collection (one per contract space)
40
- * and returns them keyed by `space`. Used by the per-space verifier
41
- * to detect marker-vs-on-disk drift and orphan marker rows. Returns
42
- * an empty map when no marker docs have been written yet.
43
- *
44
- * Marker docs are keyed by `_id: <space>` (string); ledger entries
45
- * live in the same collection but use a driver-generated `ObjectId`
46
- * `_id` plus `type: 'ledger'`. The filter selects string-keyed docs
47
- * with a `space` field, which excludes ledger entries by construction.
48
- */
49
- declare function readAllMarkers(db: Db): Promise<ReadonlyMap<string, ContractMarkerRecord>>;
50
- declare function initMarker(db: Db, space: string, destination: {
51
- readonly storageHash: string;
52
- readonly profileHash: string;
53
- readonly invariants?: readonly string[];
54
- }): Promise<void>;
55
- /**
56
- * Updates the marker doc for the given space atomically (CAS on
57
- * `expectedFrom`).
58
- *
59
- * `destination.invariants`:
60
- * - `undefined` → existing field left untouched.
61
- * - explicit value → merged into the existing field server-side via an
62
- * aggregation pipeline (`$setUnion + $sortArray`), atomic at the
63
- * document level. `[]` is a no-op merge.
64
- */
65
- declare function updateMarker(db: Db, space: string, expectedFrom: string, destination: {
66
- readonly storageHash: string;
67
- readonly profileHash: string;
68
- readonly invariants?: readonly string[];
69
- }): Promise<boolean>;
70
- /**
71
- * Appends a ledger entry for the given space. Ledger entries co-exist
72
- * with marker docs in the same collection; marker docs use `_id: <space>`
73
- * (string), ledger entries use `type: 'ledger'` plus a driver-generated
74
- * ObjectId. Reads partition the two by filter shape.
75
- *
76
- * The same `edgeId` may legitimately recur across different spaces (e.g.
77
- * a synthetic ∅→head edge on first apply), so the ledger key is
78
- * `(space, edgeId)` — the doc carries `space` for partitioned reads.
79
- */
80
- declare function writeLedgerEntry(db: Db, space: string, entry: {
81
- readonly edgeId: string;
82
- readonly from: string;
83
- readonly to: string;
84
- }): Promise<void>;
85
- //#endregion
86
30
  //#region src/core/mongo-control-adapter.d.ts
87
31
  /**
88
32
  * Mongo control adapter for control-plane operations like introspection
89
33
  * and marker-ledger CAS. Implements the family-level `MongoControlAdapter`
90
- * SPI by extracting the underlying `Db` from the framework-shaped driver
91
- * and forwarding to the wire-level helpers in this package.
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()`.
92
39
  */
93
40
  declare class MongoControlAdapterImpl implements MongoControlAdapter<'mongo'> {
41
+ #private;
94
42
  readonly familyId: "mongo";
95
43
  readonly targetId: "mongo";
96
44
  readMarker(driver: ControlDriverInstance<'mongo', 'mongo'>, space: string): Promise<ContractMarkerRecord | null>;
@@ -109,15 +57,16 @@ declare class MongoControlAdapterImpl implements MongoControlAdapter<'mongo'> {
109
57
  readonly edgeId: string;
110
58
  readonly from: string;
111
59
  readonly to: string;
60
+ readonly migrationName: string;
61
+ readonly migrationHash: string;
62
+ readonly operations: readonly unknown[];
112
63
  }): Promise<void>;
64
+ readLedger(driver: ControlDriverInstance<'mongo', 'mongo'>, space?: string): Promise<readonly LedgerEntryRecord[]>;
113
65
  introspectSchema(driver: ControlDriverInstance<'mongo', 'mongo'>): Promise<MongoSchemaIR>;
114
66
  }
115
67
  //#endregion
116
68
  //#region src/core/mongo-control-driver.d.ts
117
- interface MongoControlDriverInstance extends ControlDriverInstance<'mongo', 'mongo'> {
118
- readonly db: Db;
119
- }
120
- declare function createMongoControlDriver(db: Db, client: MongoClient): MongoControlDriverInstance;
69
+ declare function isMongoControlDriver(driver: ControlDriverInstance<'mongo', string>): driver is MongoControlDriverInstance$1;
121
70
  //#endregion
122
71
  //#region src/core/runner-deps.d.ts
123
72
  declare function extractDb(driver: ControlDriverInstance<'mongo', 'mongo'>): Db;
@@ -143,6 +92,9 @@ interface MarkerOperations {
143
92
  readonly edgeId: string;
144
93
  readonly from: string;
145
94
  readonly to: string;
95
+ readonly migrationName: string;
96
+ readonly migrationHash: string;
97
+ readonly operations: readonly unknown[];
146
98
  }): Promise<void>;
147
99
  }
148
100
  interface MongoRunnerDependencies {
@@ -167,5 +119,5 @@ declare function createMongoRunnerDeps(controlDriver: ControlDriverInstance<'mon
167
119
  //#region src/exports/control.d.ts
168
120
  declare const mongoAdapterDescriptor: MongoControlAdapterDescriptor<'mongo'>;
169
121
  //#endregion
170
- export { type MarkerOperations, MongoCommandExecutor, MongoControlAdapterImpl, type MongoControlDriverInstance, MongoInspectionExecutor, type MongoRunnerDependencies, createMongoAdapter, createMongoControlDriver, createMongoRunnerDeps, mongoAdapterDescriptor as default, mongoAdapterDescriptor, extractDb, initMarker, introspectSchema, readAllMarkers, readMarker, updateMarker, writeLedgerEntry };
122
+ export { type MarkerOperations, MongoCommandExecutor, MongoControlAdapterImpl, type MongoControlDriverInstance, MongoInspectionExecutor, type MongoRunnerDependencies, createMongoAdapter, createMongoRunnerDeps, mongoAdapterDescriptor as default, mongoAdapterDescriptor, extractDb, introspectSchema, isMongoControlDriver };
171
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/marker-ledger.ts","../src/core/mongo-control-adapter.ts","../src/core/mongo-control-driver.ts","../src/core/runner-deps.ts","../src/exports/control.ts"],"mappings":"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"}
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":"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"}
package/dist/control.mjs CHANGED
@@ -1,9 +1,13 @@
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";
1
+ import { r as mongoCodecDescriptors, t as createMongoAdapter } from "./mongo-adapter-ifsSo1o1.mjs";
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";
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";
7
11
  import { type } from "arktype";
8
12
  //#region src/core/command-executor.ts
9
13
  var MongoCommandExecutor = class {
@@ -167,17 +171,7 @@ async function introspectSchema(db) {
167
171
  //#region src/core/marker-ledger.ts
168
172
  const COLLECTION = "_prisma_migrations";
169
173
  const MONGO_MARKER_COLLECTION = `_prisma_migrations marker documents in ${COLLECTION}`;
170
- /**
171
- * Marker doc shape.
172
- *
173
- * Same fields as the SQL marker row but camelCase + Mongo-native types:
174
- * `Date` is BSON-hydrated, `meta` is a native object (not JSON-stringified),
175
- * `_id` and any extension fields are tolerated. `invariants?` is optional —
176
- * absent reads as `[]` (schemaless default); present-but-malformed throws.
177
- *
178
- * `space` is required: every marker doc is keyed by its space id (`_id`)
179
- * and stamped with a matching `space` field for partitioned reads.
180
- */
174
+ const MONGO_LEDGER_COLLECTION = `_prisma_migrations ledger documents in ${COLLECTION}`;
181
175
  const MongoMarkerDocSchema = type({
182
176
  space: "string",
183
177
  storageHash: "string",
@@ -210,130 +204,19 @@ function parseMongoMarkerDocSafely(doc, space) {
210
204
  markerLocation: MONGO_MARKER_COLLECTION
211
205
  });
212
206
  }
213
- async function executeAggregate(db, cmd) {
214
- return db.collection(cmd.collection).aggregate(cmd.pipeline).toArray();
215
- }
216
- async function executeInsertOne(db, cmd) {
217
- await db.collection(cmd.collection).insertOne(cmd.document);
218
- }
219
- async function executeFindOneAndUpdate(db, cmd) {
220
- return db.collection(cmd.collection).findOneAndUpdate(cmd.filter, cmd.update, { upsert: cmd.upsert });
221
- }
222
- /**
223
- * Reads the marker document for the given contract space, or returns
224
- * `null` if no marker has been written for that space yet. Each space
225
- * owns one row keyed by `_id: <space>` — see ADR 212 for the per-space
226
- * mechanism this enables.
227
- */
228
- async function readMarker(db, space) {
229
- const doc = (await withMarkerReadErrorHandling(() => executeAggregate(db, new RawAggregateCommand(COLLECTION, [{ $match: {
230
- _id: space,
231
- space
232
- } }, { $limit: 1 }])), {
233
- space,
234
- markerLocation: MONGO_MARKER_COLLECTION
235
- }))[0];
236
- if (!doc) return null;
237
- return parseMongoMarkerDocSafely(doc, space);
238
- }
239
- /**
240
- * Reads every marker doc in the collection (one per contract space)
241
- * and returns them keyed by `space`. Used by the per-space verifier
242
- * to detect marker-vs-on-disk drift and orphan marker rows. Returns
243
- * an empty map when no marker docs have been written yet.
244
- *
245
- * Marker docs are keyed by `_id: <space>` (string); ledger entries
246
- * live in the same collection but use a driver-generated `ObjectId`
247
- * `_id` plus `type: 'ledger'`. The filter selects string-keyed docs
248
- * with a `space` field, which excludes ledger entries by construction.
249
- */
250
- async function readAllMarkers(db) {
251
- const docs = await withMarkerReadErrorHandling(() => executeAggregate(db, new RawAggregateCommand(COLLECTION, [{ $match: {
252
- _id: { $type: "string" },
253
- space: { $type: "string" },
254
- $expr: { $eq: ["$_id", "$space"] }
255
- } }])), {
256
- space: "app",
257
- markerLocation: MONGO_MARKER_COLLECTION
258
- });
259
- const out = /* @__PURE__ */ new Map();
260
- for (const doc of docs) {
261
- const space = doc["space"];
262
- /* 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`. */
263
- if (typeof space !== "string") continue;
264
- out.set(space, parseMongoMarkerDocSafely(doc, space));
265
- }
266
- return out;
267
- }
268
- async function initMarker(db, space, destination) {
269
- await executeInsertOne(db, new RawInsertOneCommand(COLLECTION, {
270
- _id: space,
271
- space,
272
- storageHash: destination.storageHash,
273
- profileHash: destination.profileHash,
274
- contractJson: null,
275
- canonicalVersion: null,
276
- updatedAt: /* @__PURE__ */ new Date(),
277
- appTag: null,
278
- meta: {},
279
- invariants: destination.invariants ?? []
280
- }));
281
- }
282
- /**
283
- * Updates the marker doc for the given space atomically (CAS on
284
- * `expectedFrom`).
285
- *
286
- * `destination.invariants`:
287
- * - `undefined` → existing field left untouched.
288
- * - explicit value → merged into the existing field server-side via an
289
- * aggregation pipeline (`$setUnion + $sortArray`), atomic at the
290
- * document level. `[]` is a no-op merge.
291
- */
292
- async function updateMarker(db, space, expectedFrom, destination) {
293
- const setBase = {
294
- storageHash: destination.storageHash,
295
- profileHash: destination.profileHash,
296
- updatedAt: /* @__PURE__ */ new Date()
297
- };
298
- const update = destination.invariants === void 0 ? { $set: setBase } : [{ $set: {
299
- ...setBase,
300
- invariants: { $sortArray: {
301
- input: { $setUnion: [{ $ifNull: ["$invariants", []] }, destination.invariants] },
302
- sortBy: 1
303
- } }
304
- } }];
305
- return await executeFindOneAndUpdate(db, new RawFindOneAndUpdateCommand(COLLECTION, {
306
- _id: space,
307
- space,
308
- storageHash: expectedFrom
309
- }, update, false)) !== null;
310
- }
311
- /**
312
- * Appends a ledger entry for the given space. Ledger entries co-exist
313
- * with marker docs in the same collection; marker docs use `_id: <space>`
314
- * (string), ledger entries use `type: 'ledger'` plus a driver-generated
315
- * ObjectId. Reads partition the two by filter shape.
316
- *
317
- * The same `edgeId` may legitimately recur across different spaces (e.g.
318
- * a synthetic ∅→head edge on first apply), so the ledger key is
319
- * `(space, edgeId)` — the doc carries `space` for partitioned reads.
320
- */
321
- async function writeLedgerEntry(db, space, entry) {
322
- await executeInsertOne(db, new RawInsertOneCommand(COLLECTION, {
323
- type: "ledger",
324
- space,
325
- edgeId: entry.edgeId,
326
- from: entry.from,
327
- to: entry.to,
328
- appliedAt: /* @__PURE__ */ new Date()
329
- }));
207
+ //#endregion
208
+ //#region src/core/marker-ledger-collection.ts
209
+ const MARKER_LEDGER_COLLECTION = "_prisma_migrations";
210
+ //#endregion
211
+ //#region src/core/mongo-control-driver.ts
212
+ function isMongoControlDriver(driver) {
213
+ return driver.familyId === "mongo" && driver.targetId === "mongo" && "execute" in driver && typeof driver.execute === "function";
330
214
  }
331
215
  //#endregion
332
216
  //#region src/core/runner-deps.ts
333
217
  function extractDb(driver) {
334
- const mongoDriver = driver;
335
- if (!mongoDriver.db) throw new Error("Mongo control driver does not expose a db property. Use mongoControlDriver.create() from `@prisma-next/driver-mongo/control`.");
336
- return mongoDriver.db;
218
+ if (!isMongoControlDriver(driver)) throw new Error("Expected a Mongo control driver created by mongoControlDriver.create() from `@prisma-next/driver-mongo/control`.");
219
+ return driver.db;
337
220
  }
338
221
  /**
339
222
  * Build the runner-dependencies envelope. `controlAdapter` is the
@@ -364,53 +247,166 @@ function createMongoRunnerDeps(controlDriver, driver, _family, controlAdapter =
364
247
  /**
365
248
  * Mongo control adapter for control-plane operations like introspection
366
249
  * and marker-ledger CAS. Implements the family-level `MongoControlAdapter`
367
- * SPI by extracting the underlying `Db` from the framework-shaped driver
368
- * and forwarding to the wire-level helpers in this package.
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()`.
369
255
  */
370
256
  var MongoControlAdapterImpl = class {
371
257
  familyId = "mongo";
372
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
+ }
373
307
  async readMarker(driver, space) {
374
- return readMarker(extractDb(driver), space);
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()), {
309
+ space,
310
+ markerLocation: MONGO_MARKER_COLLECTION
311
+ }))[0];
312
+ if (!doc) return null;
313
+ return parseMongoMarkerDocSafely(doc, space);
375
314
  }
376
315
  async readAllMarkers(driver) {
377
- return readAllMarkers(extractDb(driver));
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()), {
317
+ space: "app",
318
+ markerLocation: MONGO_MARKER_COLLECTION
319
+ });
320
+ const out = /* @__PURE__ */ new Map();
321
+ for (const doc of docs) {
322
+ const space = doc["space"];
323
+ /* 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`. */
324
+ if (typeof space !== "string") continue;
325
+ out.set(space, parseMongoMarkerDocSafely(doc, space));
326
+ }
327
+ return out;
378
328
  }
379
329
  async initMarker(driver, space, destination) {
380
- await initMarker(extractDb(driver), space, destination);
330
+ const document = {
331
+ _id: space,
332
+ space,
333
+ storageHash: destination.storageHash,
334
+ profileHash: destination.profileHash,
335
+ contractJson: null,
336
+ canonicalVersion: null,
337
+ updatedAt: /* @__PURE__ */ new Date(),
338
+ appTag: null,
339
+ meta: {},
340
+ invariants: [...destination.invariants ?? []]
341
+ };
342
+ await this.#execute(driver, this.#markerLedgerCollection.insertOne(document));
381
343
  }
382
344
  async updateMarker(driver, space, expectedFrom, destination) {
383
- return updateMarker(extractDb(driver), space, expectedFrom, destination);
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;
384
356
  }
385
357
  async writeLedgerEntry(driver, space, entry) {
386
- await writeLedgerEntry(extractDb(driver), space, entry);
358
+ const document = {
359
+ type: "ledger",
360
+ space,
361
+ edgeId: entry.edgeId,
362
+ from: entry.from,
363
+ to: entry.to,
364
+ migrationName: entry.migrationName,
365
+ migrationHash: entry.migrationHash,
366
+ operations: blindCast(entry.operations),
367
+ appliedAt: /* @__PURE__ */ new Date()
368
+ };
369
+ await this.#execute(driver, this.#markerLedgerCollection.insertOne(document));
370
+ }
371
+ async readLedger(driver, space) {
372
+ const ledgerContext = {
373
+ space: space ?? "*",
374
+ markerLocation: MONGO_LEDGER_COLLECTION
375
+ };
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);
379
+ const entries = [];
380
+ for (const doc of docs) {
381
+ const migrationName = doc["migrationName"];
382
+ const migrationHash = doc["migrationHash"];
383
+ const from = doc["from"];
384
+ const to = doc["to"];
385
+ const docSpace = doc["space"];
386
+ if (typeof migrationName !== "string" || typeof migrationHash !== "string") continue;
387
+ if (typeof from !== "string" || typeof to !== "string") continue;
388
+ if (typeof docSpace !== "string") continue;
389
+ const appliedAt = doc["appliedAt"];
390
+ const appliedAtDate = appliedAt instanceof Date ? appliedAt : appliedAt !== void 0 ? new Date(String(appliedAt)) : /* @__PURE__ */ new Date();
391
+ const operations = doc["operations"];
392
+ const opList = Array.isArray(operations) ? operations : [];
393
+ entries.push({
394
+ space: docSpace,
395
+ migrationName,
396
+ migrationHash,
397
+ from: ledgerOriginFromStored(from),
398
+ to,
399
+ appliedAt: appliedAtDate,
400
+ operationCount: opList.length
401
+ });
402
+ }
403
+ return entries;
387
404
  }
388
405
  async introspectSchema(driver) {
389
406
  return introspectSchema(extractDb(driver));
390
407
  }
391
408
  };
392
409
  //#endregion
393
- //#region src/core/mongo-control-driver.ts
394
- var MongoControlDriverImpl = class {
395
- familyId = "mongo";
396
- targetId = "mongo";
397
- db;
398
- #client;
399
- constructor(db, client) {
400
- this.db = db;
401
- this.#client = client;
402
- }
403
- query() {
404
- throw new Error("MongoDB control driver does not support SQL queries");
405
- }
406
- async close() {
407
- await this.#client.close();
408
- }
409
- };
410
- function createMongoControlDriver(db, client) {
411
- return new MongoControlDriverImpl(db, client);
412
- }
413
- //#endregion
414
410
  //#region src/exports/control.ts
415
411
  const mongoAdapterDescriptor = {
416
412
  kind: "adapter",
@@ -444,6 +440,6 @@ const mongoAdapterDescriptor = {
444
440
  }
445
441
  };
446
442
  //#endregion
447
- export { MongoCommandExecutor, MongoControlAdapterImpl, MongoInspectionExecutor, createMongoAdapter, createMongoControlDriver, createMongoRunnerDeps, mongoAdapterDescriptor as default, mongoAdapterDescriptor, extractDb, initMarker, introspectSchema, readAllMarkers, readMarker, updateMarker, writeLedgerEntry };
443
+ export { MongoCommandExecutor, MongoControlAdapterImpl, MongoInspectionExecutor, createMongoAdapter, createMongoRunnerDeps, mongoAdapterDescriptor as default, mongoAdapterDescriptor, extractDb, introspectSchema, isMongoControlDriver };
448
444
 
449
445
  //# sourceMappingURL=control.mjs.map