@prisma-next/adapter-mongo 0.12.0-dev.5 → 0.12.0-dev.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/control.d.mts +34 -65
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +140 -150
- package/dist/control.mjs.map +1 -1
- package/package.json +22 -22
- package/src/core/marker-ledger.ts +10 -190
- package/src/core/mongo-control-adapter.ts +180 -13
- package/src/core/mongo-control-driver.ts +5 -27
- package/src/core/runner-deps.ts +13 -10
- package/src/exports/control.ts +73 -11
package/dist/control.d.mts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { t as createMongoAdapter } from "./mongo-adapter-JuKx_-h9.mjs";
|
|
2
|
-
import { Db, Document
|
|
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";
|
|
5
6
|
import { MongoControlAdapter, MongoControlAdapterDescriptor } from "@prisma-next/family-mongo/control-adapter";
|
|
6
|
-
import {
|
|
7
|
+
import { MongoAdapter, MongoControlDriverInstance, MongoControlDriverInstance as MongoControlDriverInstance$1, MongoDriver } from "@prisma-next/mongo-lowering";
|
|
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,68 +27,12 @@ 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
34
|
* SPI by extracting the underlying `Db` from the framework-shaped driver
|
|
91
|
-
*
|
|
35
|
+
* per call.
|
|
92
36
|
*/
|
|
93
37
|
declare class MongoControlAdapterImpl implements MongoControlAdapter<'mongo'> {
|
|
94
38
|
readonly familyId: "mongo";
|
|
@@ -109,15 +53,16 @@ declare class MongoControlAdapterImpl implements MongoControlAdapter<'mongo'> {
|
|
|
109
53
|
readonly edgeId: string;
|
|
110
54
|
readonly from: string;
|
|
111
55
|
readonly to: string;
|
|
56
|
+
readonly migrationName: string;
|
|
57
|
+
readonly migrationHash: string;
|
|
58
|
+
readonly operations: readonly unknown[];
|
|
112
59
|
}): Promise<void>;
|
|
60
|
+
readLedger(driver: ControlDriverInstance<'mongo', 'mongo'>, space?: string): Promise<readonly LedgerEntryRecord[]>;
|
|
113
61
|
introspectSchema(driver: ControlDriverInstance<'mongo', 'mongo'>): Promise<MongoSchemaIR>;
|
|
114
62
|
}
|
|
115
63
|
//#endregion
|
|
116
64
|
//#region src/core/mongo-control-driver.d.ts
|
|
117
|
-
|
|
118
|
-
readonly db: Db;
|
|
119
|
-
}
|
|
120
|
-
declare function createMongoControlDriver(db: Db, client: MongoClient): MongoControlDriverInstance;
|
|
65
|
+
declare function isMongoControlDriver(driver: ControlDriverInstance<'mongo', string>): driver is MongoControlDriverInstance$1;
|
|
121
66
|
//#endregion
|
|
122
67
|
//#region src/core/runner-deps.d.ts
|
|
123
68
|
declare function extractDb(driver: ControlDriverInstance<'mongo', 'mongo'>): Db;
|
|
@@ -143,6 +88,9 @@ interface MarkerOperations {
|
|
|
143
88
|
readonly edgeId: string;
|
|
144
89
|
readonly from: string;
|
|
145
90
|
readonly to: string;
|
|
91
|
+
readonly migrationName: string;
|
|
92
|
+
readonly migrationHash: string;
|
|
93
|
+
readonly operations: readonly unknown[];
|
|
146
94
|
}): Promise<void>;
|
|
147
95
|
}
|
|
148
96
|
interface MongoRunnerDependencies {
|
|
@@ -165,7 +113,28 @@ interface MongoRunnerDependencies {
|
|
|
165
113
|
declare function createMongoRunnerDeps(controlDriver: ControlDriverInstance<'mongo', 'mongo'>, driver: MongoDriver, _family: ControlFamilyInstance<'mongo', MongoSchemaIR>, controlAdapter?: MongoControlAdapter<'mongo'>): MongoRunnerDependencies;
|
|
166
114
|
//#endregion
|
|
167
115
|
//#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>;
|
|
168
137
|
declare const mongoAdapterDescriptor: MongoControlAdapterDescriptor<'mongo'>;
|
|
169
138
|
//#endregion
|
|
170
|
-
export { type MarkerOperations, MongoCommandExecutor, MongoControlAdapterImpl, type MongoControlDriverInstance, MongoInspectionExecutor, type MongoRunnerDependencies, createMongoAdapter,
|
|
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 };
|
|
171
140
|
//# sourceMappingURL=control.d.mts.map
|
package/dist/control.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/command-executor.ts","../src/core/introspect-schema.ts","../src/core/
|
|
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
|
@@ -4,6 +4,7 @@ import { MongoServerError } from "mongodb";
|
|
|
4
4
|
import { keysToKeySpec } from "@prisma-next/mongo-query-ast/control";
|
|
5
5
|
import { MongoSchemaCollection, MongoSchemaCollectionOptions, MongoSchemaIR, MongoSchemaIndex, MongoSchemaValidator } from "@prisma-next/mongo-schema-ir";
|
|
6
6
|
import { parseMarkerRowSafely, withMarkerReadErrorHandling } from "@prisma-next/errors/execution";
|
|
7
|
+
import { ledgerOriginFromStored } from "@prisma-next/migration-tools/ledger-origin";
|
|
7
8
|
import { type } from "arktype";
|
|
8
9
|
//#region src/core/command-executor.ts
|
|
9
10
|
var MongoCommandExecutor = class {
|
|
@@ -167,17 +168,7 @@ async function introspectSchema(db) {
|
|
|
167
168
|
//#region src/core/marker-ledger.ts
|
|
168
169
|
const COLLECTION = "_prisma_migrations";
|
|
169
170
|
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
|
-
*/
|
|
171
|
+
const MONGO_LEDGER_COLLECTION = `_prisma_migrations ledger documents in ${COLLECTION}`;
|
|
181
172
|
const MongoMarkerDocSchema = type({
|
|
182
173
|
space: "string",
|
|
183
174
|
storageHash: "string",
|
|
@@ -219,121 +210,16 @@ async function executeInsertOne(db, cmd) {
|
|
|
219
210
|
async function executeFindOneAndUpdate(db, cmd) {
|
|
220
211
|
return db.collection(cmd.collection).findOneAndUpdate(cmd.filter, cmd.update, { upsert: cmd.upsert });
|
|
221
212
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
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
|
-
}));
|
|
213
|
+
//#endregion
|
|
214
|
+
//#region src/core/mongo-control-driver.ts
|
|
215
|
+
function isMongoControlDriver(driver) {
|
|
216
|
+
return driver.familyId === "mongo" && driver.targetId === "mongo";
|
|
330
217
|
}
|
|
331
218
|
//#endregion
|
|
332
219
|
//#region src/core/runner-deps.ts
|
|
333
220
|
function extractDb(driver) {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
return mongoDriver.db;
|
|
221
|
+
if (!isMongoControlDriver(driver)) throw new Error("Expected a Mongo control driver created by mongoControlDriver.create() from `@prisma-next/driver-mongo/control`.");
|
|
222
|
+
return driver.db;
|
|
337
223
|
}
|
|
338
224
|
/**
|
|
339
225
|
* Build the runner-dependencies envelope. `controlAdapter` is the
|
|
@@ -365,53 +251,157 @@ function createMongoRunnerDeps(controlDriver, driver, _family, controlAdapter =
|
|
|
365
251
|
* Mongo control adapter for control-plane operations like introspection
|
|
366
252
|
* and marker-ledger CAS. Implements the family-level `MongoControlAdapter`
|
|
367
253
|
* SPI by extracting the underlying `Db` from the framework-shaped driver
|
|
368
|
-
*
|
|
254
|
+
* per call.
|
|
369
255
|
*/
|
|
370
256
|
var MongoControlAdapterImpl = class {
|
|
371
257
|
familyId = "mongo";
|
|
372
258
|
targetId = "mongo";
|
|
373
259
|
async readMarker(driver, space) {
|
|
374
|
-
|
|
260
|
+
const db = extractDb(driver);
|
|
261
|
+
const doc = (await withMarkerReadErrorHandling(() => executeAggregate(db, new RawAggregateCommand(COLLECTION, [{ $match: {
|
|
262
|
+
_id: space,
|
|
263
|
+
space
|
|
264
|
+
} }, { $limit: 1 }])), {
|
|
265
|
+
space,
|
|
266
|
+
markerLocation: MONGO_MARKER_COLLECTION
|
|
267
|
+
}))[0];
|
|
268
|
+
if (!doc) return null;
|
|
269
|
+
return parseMongoMarkerDocSafely(doc, space);
|
|
375
270
|
}
|
|
376
271
|
async readAllMarkers(driver) {
|
|
377
|
-
|
|
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
|
+
} }])), {
|
|
278
|
+
space: "app",
|
|
279
|
+
markerLocation: MONGO_MARKER_COLLECTION
|
|
280
|
+
});
|
|
281
|
+
const out = /* @__PURE__ */ new Map();
|
|
282
|
+
for (const doc of docs) {
|
|
283
|
+
const space = doc["space"];
|
|
284
|
+
/* 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`. */
|
|
285
|
+
if (typeof space !== "string") continue;
|
|
286
|
+
out.set(space, parseMongoMarkerDocSafely(doc, space));
|
|
287
|
+
}
|
|
288
|
+
return out;
|
|
378
289
|
}
|
|
379
290
|
async initMarker(driver, space, destination) {
|
|
380
|
-
await
|
|
291
|
+
await executeInsertOne(extractDb(driver), new RawInsertOneCommand(COLLECTION, {
|
|
292
|
+
_id: space,
|
|
293
|
+
space,
|
|
294
|
+
storageHash: destination.storageHash,
|
|
295
|
+
profileHash: destination.profileHash,
|
|
296
|
+
contractJson: null,
|
|
297
|
+
canonicalVersion: null,
|
|
298
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
299
|
+
appTag: null,
|
|
300
|
+
meta: {},
|
|
301
|
+
invariants: destination.invariants ?? []
|
|
302
|
+
}));
|
|
381
303
|
}
|
|
382
304
|
async updateMarker(driver, space, expectedFrom, destination) {
|
|
383
|
-
|
|
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;
|
|
384
323
|
}
|
|
385
324
|
async writeLedgerEntry(driver, space, entry) {
|
|
386
|
-
await
|
|
325
|
+
await executeInsertOne(extractDb(driver), new RawInsertOneCommand(COLLECTION, {
|
|
326
|
+
type: "ledger",
|
|
327
|
+
space,
|
|
328
|
+
edgeId: entry.edgeId,
|
|
329
|
+
from: entry.from,
|
|
330
|
+
to: entry.to,
|
|
331
|
+
migrationName: entry.migrationName,
|
|
332
|
+
migrationHash: entry.migrationHash,
|
|
333
|
+
operations: entry.operations,
|
|
334
|
+
appliedAt: /* @__PURE__ */ new Date()
|
|
335
|
+
}));
|
|
336
|
+
}
|
|
337
|
+
async readLedger(driver, space) {
|
|
338
|
+
const db = extractDb(driver);
|
|
339
|
+
const ledgerContext = {
|
|
340
|
+
space: space ?? "*",
|
|
341
|
+
markerLocation: MONGO_LEDGER_COLLECTION
|
|
342
|
+
};
|
|
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);
|
|
346
|
+
const entries = [];
|
|
347
|
+
for (const doc of docs) {
|
|
348
|
+
const migrationName = doc["migrationName"];
|
|
349
|
+
const migrationHash = doc["migrationHash"];
|
|
350
|
+
const from = doc["from"];
|
|
351
|
+
const to = doc["to"];
|
|
352
|
+
const docSpace = doc["space"];
|
|
353
|
+
if (typeof migrationName !== "string" || typeof migrationHash !== "string") continue;
|
|
354
|
+
if (typeof from !== "string" || typeof to !== "string") continue;
|
|
355
|
+
if (typeof docSpace !== "string") continue;
|
|
356
|
+
const appliedAt = doc["appliedAt"];
|
|
357
|
+
const appliedAtDate = appliedAt instanceof Date ? appliedAt : appliedAt !== void 0 ? new Date(String(appliedAt)) : /* @__PURE__ */ new Date();
|
|
358
|
+
const operations = doc["operations"];
|
|
359
|
+
const opList = Array.isArray(operations) ? operations : [];
|
|
360
|
+
entries.push({
|
|
361
|
+
space: docSpace,
|
|
362
|
+
migrationName,
|
|
363
|
+
migrationHash,
|
|
364
|
+
from: ledgerOriginFromStored(from),
|
|
365
|
+
to,
|
|
366
|
+
appliedAt: appliedAtDate,
|
|
367
|
+
operationCount: opList.length
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
return entries;
|
|
387
371
|
}
|
|
388
372
|
async introspectSchema(driver) {
|
|
389
373
|
return introspectSchema(extractDb(driver));
|
|
390
374
|
}
|
|
391
375
|
};
|
|
392
376
|
//#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
377
|
//#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
|
+
}
|
|
415
405
|
const mongoAdapterDescriptor = {
|
|
416
406
|
kind: "adapter",
|
|
417
407
|
id: "mongo",
|
|
@@ -444,6 +434,6 @@ const mongoAdapterDescriptor = {
|
|
|
444
434
|
}
|
|
445
435
|
};
|
|
446
436
|
//#endregion
|
|
447
|
-
export { MongoCommandExecutor, MongoControlAdapterImpl, MongoInspectionExecutor, createMongoAdapter,
|
|
437
|
+
export { MongoCommandExecutor, MongoControlAdapterImpl, MongoInspectionExecutor, createMongoAdapter, createMongoRunnerDeps, mongoAdapterDescriptor as default, mongoAdapterDescriptor, extractDb, initMarker, introspectSchema, isMongoControlDriver, readAllMarkers, readLedger, readMarker, updateMarker, writeLedgerEntry };
|
|
448
438
|
|
|
449
439
|
//# sourceMappingURL=control.mjs.map
|