@prisma-next/family-mongo 0.5.0-dev.7 → 0.5.0-dev.71

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,9 +1,9 @@
1
- import { ControlFamilyDescriptor, ControlFamilyInstance, ControlStack, MigratableTargetDescriptor, SchemaViewCapable } from "@prisma-next/framework-components/control";
1
+ import { ControlFamilyDescriptor, ControlFamilyInstance, ControlStack, MigratableTargetDescriptor, OperationPreviewCapable, SchemaViewCapable } from "@prisma-next/framework-components/control";
2
2
  import { Contract } from "@prisma-next/contract/types";
3
3
  import { MongoSchemaIR } from "@prisma-next/mongo-schema-ir";
4
4
 
5
5
  //#region src/core/control-instance.d.ts
6
- interface MongoControlFamilyInstance extends ControlFamilyInstance<'mongo', MongoSchemaIR>, SchemaViewCapable<MongoSchemaIR> {
6
+ interface MongoControlFamilyInstance extends ControlFamilyInstance<'mongo', MongoSchemaIR>, SchemaViewCapable<MongoSchemaIR>, OperationPreviewCapable {
7
7
  validateContract(contractJson: unknown): Contract;
8
8
  }
9
9
  declare function createMongoFamilyInstance(_controlStack: ControlStack): MongoControlFamilyInstance;
@@ -20,7 +20,7 @@ declare const mongoFamilyDescriptor: ControlFamilyDescriptor<'mongo', MongoContr
20
20
  * itself back to such a file; `MongoMigrationPlanner.emptyMigration()`
21
21
  * returns the same shape for `migration new`. Users run the scaffolded
22
22
  * `migration.ts` directly (via `node migration.ts`) to self-emit
23
- * `ops.json` and attest the `migrationId`.
23
+ * `ops.json` and attest the `migrationHash`.
24
24
  */
25
25
  declare const mongoTargetDescriptor: MigratableTargetDescriptor<'mongo', 'mongo', MongoControlFamilyInstance>;
26
26
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/control-instance.ts","../src/core/control-descriptor.ts","../src/core/mongo-target-descriptor.ts"],"sourcesContent":[],"mappings":";;;;;UA2BiB,0BAAA,SACP,+BAA+B,gBACrC,kBAAkB;2CACqB;AAH3C;AACyC,iBAqRzB,yBAAA,CArRyB,aAAA,EAqRgB,YArRhB,CAAA,EAqR+B,0BArR/B;;;cCL5B,uBAAuB,iCAAiC;;;;;;ADIrE;;;;;;;AAsRgB,cEtRH,qBFsR4B,EEtRL,0BFsRoC,CAAA,OAAA,EAAA,OAA0B,EEnRhG,0BFmRgG,CAAA"}
1
+ {"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/control-instance.ts","../src/core/control-descriptor.ts","../src/core/mongo-target-descriptor.ts"],"mappings":";;;;;UAoCiB,0BAAA,SACP,qBAAA,UAA+B,aAAA,GACrC,iBAAA,CAAkB,aAAA,GAClB,uBAAA;EACF,gBAAA,CAAiB,YAAA,YAAwB,QAAA;AAAA;AAAA,iBAgU3B,yBAAA,CAA0B,aAAA,EAAe,YAAA,GAAe,0BAAA;;;cCjV3D,qBAAA,EAAuB,uBAAA,UAAiC,0BAAA;;;;;;ADarE;;;;;;;cETa,qBAAA,EAAuB,0BAAA,mBAGlC,0BAAA"}
package/dist/control.mjs CHANGED
@@ -1,13 +1,12 @@
1
1
  import { mongoEmission } from "@prisma-next/mongo-emitter";
2
2
  import { createMongoRunnerDeps, extractDb, introspectSchema } from "@prisma-next/adapter-mongo/control";
3
- import { SchemaTreeNode, VERIFY_CODE_HASH_MISMATCH, VERIFY_CODE_MARKER_MISSING, VERIFY_CODE_TARGET_MISMATCH } from "@prisma-next/framework-components/control";
3
+ import { APP_SPACE_ID, SchemaTreeNode, VERIFY_CODE_HASH_MISMATCH, VERIFY_CODE_MARKER_MISSING, VERIFY_CODE_TARGET_MISMATCH } from "@prisma-next/framework-components/control";
4
4
  import { validateMongoContract } from "@prisma-next/mongo-contract";
5
- import { MongoMigrationPlanner, MongoMigrationRunner, contractToMongoSchemaIR, initMarker, readMarker, updateMarker } from "@prisma-next/target-mongo/control";
5
+ import { MongoMigrationPlanner, MongoMigrationRunner, contractToMongoSchemaIR, formatMongoOperations, initMarker, readMarker, updateMarker } from "@prisma-next/target-mongo/control";
6
6
  import { verifyMongoSchema } from "@prisma-next/target-mongo/schema-verify";
7
7
  import { ifDefined } from "@prisma-next/utils/defined";
8
8
  import { MongoDriverImpl } from "@prisma-next/driver-mongo";
9
9
  import mongoTargetDescriptorMeta from "@prisma-next/target-mongo/pack";
10
-
11
10
  //#region src/core/schema-to-view.ts
12
11
  function mongoSchemaToView(schema) {
13
12
  const collectionNodes = schema.collections.map((collection) => collectionToSchemaNode(collection.name, collection));
@@ -99,7 +98,6 @@ function collectionToSchemaNode(name, collection) {
99
98
  ...ifDefined("children", children.length > 0 ? children : void 0)
100
99
  });
101
100
  }
102
-
103
101
  //#endregion
104
102
  //#region src/core/control-instance.ts
105
103
  function extractDb$1(driver) {
@@ -180,6 +178,14 @@ var MongoFamilyInstance = class {
180
178
  }
181
179
  });
182
180
  }
181
+ schemaVerifyAgainstSchema(options) {
182
+ return verifyMongoSchema({
183
+ contract: validateMongoContract(options.contract).contract,
184
+ schema: options.schema,
185
+ strict: options.strict,
186
+ frameworkComponents: options.frameworkComponents
187
+ });
188
+ }
183
189
  async sign(options) {
184
190
  const { driver, contract: rawContract, contractPath, configPath } = options;
185
191
  const startTime = Date.now();
@@ -240,14 +246,29 @@ var MongoFamilyInstance = class {
240
246
  };
241
247
  }
242
248
  async readMarker(options) {
249
+ if (options.space !== APP_SPACE_ID) throw new Error(`Mongo target does not yet support per-space contract markers. readMarker was called with space="${options.space}", but only "${APP_SPACE_ID}" is supported. Per-space marker support is tracked separately for Mongo and is not part of the SQL-family contract-spaces work.`);
243
250
  return readMarker(extractDb$1(options.driver));
244
251
  }
252
+ async readAllMarkers(options) {
253
+ const appMarker = await this.readMarker({
254
+ ...options,
255
+ space: APP_SPACE_ID
256
+ });
257
+ if (appMarker === null) return /* @__PURE__ */ new Map();
258
+ return new Map([[APP_SPACE_ID, appMarker]]);
259
+ }
245
260
  async introspect(options) {
246
261
  return introspectSchema(extractDb$1(options.driver));
247
262
  }
248
263
  toSchemaView(schema) {
249
264
  return mongoSchemaToView(schema);
250
265
  }
266
+ toOperationPreview(operations) {
267
+ return { statements: formatMongoOperations(operations).map((text) => ({
268
+ text,
269
+ language: "mongodb-shell"
270
+ })) };
271
+ }
251
272
  };
252
273
  function buildVerifyResult(opts) {
253
274
  return {
@@ -276,7 +297,6 @@ function buildVerifyResult(opts) {
276
297
  function createMongoFamilyInstance(_controlStack) {
277
298
  return new MongoFamilyInstance();
278
299
  }
279
-
280
300
  //#endregion
281
301
  //#region src/core/control-descriptor.ts
282
302
  var MongoFamilyDescriptor = class {
@@ -290,7 +310,6 @@ var MongoFamilyDescriptor = class {
290
310
  }
291
311
  };
292
312
  const mongoFamilyDescriptor = new MongoFamilyDescriptor();
293
-
294
313
  //#endregion
295
314
  //#region src/core/mongo-target-descriptor.ts
296
315
  /**
@@ -301,7 +320,7 @@ const mongoFamilyDescriptor = new MongoFamilyDescriptor();
301
320
  * itself back to such a file; `MongoMigrationPlanner.emptyMigration()`
302
321
  * returns the same shape for `migration new`. Users run the scaffolded
303
322
  * `migration.ts` directly (via `node migration.ts`) to self-emit
304
- * `ops.json` and attest the `migrationId`.
323
+ * `ops.json` and attest the `migrationHash`.
305
324
  */
306
325
  const mongoTargetDescriptor = {
307
326
  ...mongoTargetDescriptorMeta,
@@ -331,7 +350,7 @@ const mongoTargetDescriptor = {
331
350
  };
332
351
  }
333
352
  };
334
-
335
353
  //#endregion
336
354
  export { createMongoFamilyInstance, mongoFamilyDescriptor, mongoTargetDescriptor };
355
+
337
356
  //# sourceMappingURL=control.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"control.mjs","names":["children: SchemaTreeNode[]","options: string[]","validatorChildren: SchemaTreeNode[]","optLabels: string[]","extractDb","previousHashes: { storageHash?: string; profileHash?: string } | undefined","summary: string","mongoFamilyDescriptor: ControlFamilyDescriptor<'mongo', MongoControlFamilyInstance>","mongoTargetDescriptor: MigratableTargetDescriptor<\n 'mongo',\n 'mongo',\n MongoControlFamilyInstance\n>","cachedDeps: MongoRunnerDependencies | undefined"],"sources":["../src/core/schema-to-view.ts","../src/core/control-instance.ts","../src/core/control-descriptor.ts","../src/core/mongo-target-descriptor.ts"],"sourcesContent":["import type { CoreSchemaView } from '@prisma-next/framework-components/control';\nimport { SchemaTreeNode } from '@prisma-next/framework-components/control';\nimport type { MongoSchemaCollection, MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport { ifDefined } from '@prisma-next/utils/defined';\n\nexport function mongoSchemaToView(schema: MongoSchemaIR): CoreSchemaView {\n const collectionNodes = schema.collections.map((collection) =>\n collectionToSchemaNode(collection.name, collection),\n );\n\n return {\n root: new SchemaTreeNode({\n kind: 'root',\n id: 'mongo-schema',\n label: 'database',\n ...ifDefined('children', collectionNodes.length > 0 ? collectionNodes : undefined),\n }),\n };\n}\n\nfunction collectionToSchemaNode(name: string, collection: MongoSchemaCollection): SchemaTreeNode {\n const children: SchemaTreeNode[] = [];\n\n for (const index of collection.indexes) {\n const keysSummary = index.keys\n .map((k) => {\n if (k.direction === 1) return k.field;\n if (k.direction === -1) return `${k.field} desc`;\n return `${k.field} ${k.direction}`;\n })\n .join(', ');\n const prefix = index.unique ? 'unique index' : 'index';\n const options: string[] = [];\n if (index.sparse) options.push('sparse');\n if (index.expireAfterSeconds != null) options.push(`ttl: ${index.expireAfterSeconds}s`);\n if (index.partialFilterExpression) options.push('partial');\n const optsSuffix = options.length > 0 ? ` (${options.join(', ')})` : '';\n\n children.push(\n new SchemaTreeNode({\n kind: 'index',\n id: `index-${name}-${index.keys.map((k) => `${k.field}_${k.direction}`).join('_')}`,\n label: `${prefix} (${keysSummary})${optsSuffix}`,\n meta: {\n keys: index.keys,\n unique: index.unique,\n ...ifDefined('sparse', index.sparse || undefined),\n ...ifDefined('expireAfterSeconds', index.expireAfterSeconds ?? undefined),\n ...ifDefined('partialFilterExpression', index.partialFilterExpression ?? undefined),\n },\n }),\n );\n }\n\n if (collection.validator) {\n const validatorChildren: SchemaTreeNode[] = [];\n const jsonSchema = collection.validator.jsonSchema as Record<string, unknown>;\n const properties = jsonSchema['properties'] as\n | Record<string, Record<string, unknown>>\n | undefined;\n const required = new Set((jsonSchema['required'] as string[] | undefined) ?? []);\n\n if (properties) {\n for (const [propName, propDef] of Object.entries(properties)) {\n const bsonType = (propDef['bsonType'] as string) ?? 'unknown';\n const suffix = required.has(propName) ? ' (required)' : '';\n validatorChildren.push(\n new SchemaTreeNode({\n kind: 'field',\n id: `field-${name}-${propName}`,\n label: `${propName}: ${bsonType}${suffix}`,\n }),\n );\n }\n }\n\n children.push(\n new SchemaTreeNode({\n kind: 'field',\n id: `validator-${name}`,\n label: `validator (level: ${collection.validator.validationLevel}, action: ${collection.validator.validationAction})`,\n meta: {\n validationLevel: collection.validator.validationLevel,\n validationAction: collection.validator.validationAction,\n jsonSchema: collection.validator.jsonSchema,\n },\n ...ifDefined('children', validatorChildren.length > 0 ? validatorChildren : undefined),\n }),\n );\n }\n\n if (collection.options) {\n const opts = collection.options;\n const optLabels: string[] = [];\n if (opts.capped) optLabels.push('capped');\n if (opts.timeseries) optLabels.push('timeseries');\n if (opts.collation) optLabels.push('collation');\n if (opts.changeStreamPreAndPostImages) optLabels.push('changeStreamPreAndPostImages');\n if (opts.clusteredIndex) optLabels.push('clusteredIndex');\n\n if (optLabels.length > 0) {\n children.push(\n new SchemaTreeNode({\n kind: 'field',\n id: `options-${name}`,\n label: `options (${optLabels.join(', ')})`,\n meta: {\n ...ifDefined('capped', opts.capped ?? undefined),\n ...ifDefined('timeseries', opts.timeseries ?? undefined),\n ...ifDefined('collation', opts.collation ?? undefined),\n ...ifDefined(\n 'changeStreamPreAndPostImages',\n opts.changeStreamPreAndPostImages ?? undefined,\n ),\n ...ifDefined('clusteredIndex', opts.clusteredIndex ?? undefined),\n },\n }),\n );\n }\n }\n\n return new SchemaTreeNode({\n kind: 'collection',\n id: `collection-${name}`,\n label: `collection ${name}`,\n ...ifDefined('children', children.length > 0 ? children : undefined),\n });\n}\n","import { introspectSchema } from '@prisma-next/adapter-mongo/control';\nimport type { Contract, ContractMarkerRecord } from '@prisma-next/contract/types';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n ControlStack,\n CoreSchemaView,\n SchemaViewCapable,\n SignDatabaseResult,\n VerifyDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/framework-components/control';\nimport {\n VERIFY_CODE_HASH_MISMATCH,\n VERIFY_CODE_MARKER_MISSING,\n VERIFY_CODE_TARGET_MISMATCH,\n} from '@prisma-next/framework-components/control';\nimport type { MongoContract } from '@prisma-next/mongo-contract';\nimport { validateMongoContract } from '@prisma-next/mongo-contract';\nimport type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport { initMarker, readMarker, updateMarker } from '@prisma-next/target-mongo/control';\nimport { verifyMongoSchema } from '@prisma-next/target-mongo/schema-verify';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { Db } from 'mongodb';\nimport { mongoSchemaToView } from './schema-to-view';\n\nexport interface MongoControlFamilyInstance\n extends ControlFamilyInstance<'mongo', MongoSchemaIR>,\n SchemaViewCapable<MongoSchemaIR> {\n validateContract(contractJson: unknown): Contract;\n}\n\nfunction extractDb(driver: ControlDriverInstance<'mongo', string>): Db {\n const mongoDriver = driver as ControlDriverInstance<'mongo', string> & { db?: Db };\n if (!mongoDriver.db) {\n throw new Error(\n 'Mongo control driver does not expose a db property. ' +\n 'Use createMongoControlDriver() from @prisma-next/adapter-mongo/control.',\n );\n }\n return mongoDriver.db;\n}\n\nclass MongoFamilyInstance implements MongoControlFamilyInstance {\n readonly familyId = 'mongo' as const;\n\n validateContract(contractJson: unknown): Contract {\n const validated = validateMongoContract<MongoContract>(contractJson);\n // MongoContract and Contract share structure but are typed independently;\n // validateMongoContract guarantees the shape, so the double cast is safe.\n return validated.contract as unknown as Contract;\n }\n\n async verify(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract: unknown;\n readonly expectedTargetId: string;\n readonly contractPath: string;\n readonly configPath?: string;\n }): Promise<VerifyDatabaseResult> {\n const { driver, contract: rawContract, expectedTargetId, contractPath, configPath } = options;\n const startTime = Date.now();\n\n const validated = validateMongoContract<MongoContract>(rawContract);\n const contract = validated.contract;\n\n const contractStorageHash = contract.storage.storageHash;\n const contractProfileHash = contract.profileHash;\n const contractTarget = contract.target;\n\n const baseOpts = {\n contractStorageHash,\n contractProfileHash,\n expectedTargetId,\n contractPath,\n ...ifDefined('configPath', configPath),\n };\n\n if (contractTarget !== expectedTargetId) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_TARGET_MISMATCH,\n summary: 'Target mismatch',\n actualTargetId: contractTarget,\n totalTime: Date.now() - startTime,\n });\n }\n\n const db = extractDb(driver);\n const marker = await readMarker(db);\n\n if (!marker) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_MARKER_MISSING,\n summary: 'Marker missing',\n totalTime: Date.now() - startTime,\n });\n }\n\n if (marker.storageHash !== contractStorageHash) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_HASH_MISMATCH,\n summary: 'Hash mismatch',\n marker,\n totalTime: Date.now() - startTime,\n });\n }\n\n if (contractProfileHash && marker.profileHash !== contractProfileHash) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_HASH_MISMATCH,\n summary: 'Hash mismatch',\n marker,\n totalTime: Date.now() - startTime,\n });\n }\n\n return buildVerifyResult({\n ...baseOpts,\n ok: true,\n summary: 'Database matches contract',\n marker,\n totalTime: Date.now() - startTime,\n });\n }\n\n async schemaVerify(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract: unknown;\n readonly strict: boolean;\n readonly contractPath: string;\n readonly configPath?: string;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'mongo', string>>;\n }): Promise<VerifyDatabaseSchemaResult> {\n const { driver, contract: rawContract, strict, contractPath, configPath } = options;\n\n const validated = validateMongoContract<MongoContract>(rawContract);\n const contract = validated.contract;\n\n const db = extractDb(driver);\n const liveIR = await introspectSchema(db);\n\n return verifyMongoSchema({\n contract,\n schema: liveIR,\n strict,\n frameworkComponents: options.frameworkComponents,\n context: {\n contractPath,\n ...ifDefined('configPath', configPath),\n },\n });\n }\n\n async sign(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract: unknown;\n readonly contractPath: string;\n readonly configPath?: string;\n }): Promise<SignDatabaseResult> {\n const { driver, contract: rawContract, contractPath, configPath } = options;\n const startTime = Date.now();\n\n const validated = validateMongoContract<MongoContract>(rawContract);\n const contract = validated.contract;\n\n const contractStorageHash = contract.storage.storageHash;\n const contractProfileHash = contract.profileHash;\n\n const db = extractDb(driver);\n\n const existingMarker = await readMarker(db);\n\n let markerCreated = false;\n let markerUpdated = false;\n let previousHashes: { storageHash?: string; profileHash?: string } | undefined;\n\n if (!existingMarker) {\n await initMarker(db, {\n storageHash: contractStorageHash,\n profileHash: contractProfileHash,\n });\n markerCreated = true;\n } else {\n const storageHashMatches = existingMarker.storageHash === contractStorageHash;\n const profileHashMatches = existingMarker.profileHash === contractProfileHash;\n\n if (!storageHashMatches || !profileHashMatches) {\n previousHashes = {\n storageHash: existingMarker.storageHash,\n profileHash: existingMarker.profileHash,\n };\n const updated = await updateMarker(db, existingMarker.storageHash, {\n storageHash: contractStorageHash,\n profileHash: contractProfileHash,\n });\n if (!updated) {\n throw new Error('CAS conflict: marker was modified by another process during sign');\n }\n markerUpdated = true;\n }\n }\n\n let summary: string;\n if (markerCreated) {\n summary = 'Database signed (marker created)';\n } else if (markerUpdated) {\n summary = `Database signed (marker updated from ${previousHashes?.storageHash ?? 'unknown'})`;\n } else {\n summary = 'Database already signed with this contract';\n }\n\n return {\n ok: true,\n summary,\n contract: {\n storageHash: contractStorageHash,\n profileHash: contractProfileHash,\n },\n target: {\n expected: contract.target,\n actual: contract.target,\n },\n marker: {\n created: markerCreated,\n updated: markerUpdated,\n ...ifDefined('previous', previousHashes),\n },\n meta: {\n contractPath,\n ...ifDefined('configPath', configPath),\n },\n timings: {\n total: Date.now() - startTime,\n },\n };\n }\n\n async readMarker(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n }): Promise<ContractMarkerRecord | null> {\n const db = extractDb(options.driver);\n return readMarker(db);\n }\n\n async introspect(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract?: unknown;\n }): Promise<MongoSchemaIR> {\n const db = extractDb(options.driver);\n return introspectSchema(db);\n }\n\n toSchemaView(schema: MongoSchemaIR): CoreSchemaView {\n return mongoSchemaToView(schema);\n }\n}\n\nfunction buildVerifyResult(opts: {\n ok: boolean;\n code?: string;\n summary: string;\n contractStorageHash: string;\n contractProfileHash?: string;\n marker?: ContractMarkerRecord;\n expectedTargetId: string;\n actualTargetId?: string;\n contractPath: string;\n configPath?: string;\n totalTime: number;\n}): VerifyDatabaseResult {\n return {\n ok: opts.ok,\n ...ifDefined('code', opts.code),\n summary: opts.summary,\n contract: {\n storageHash: opts.contractStorageHash,\n ...ifDefined('profileHash', opts.contractProfileHash),\n },\n ...ifDefined(\n 'marker',\n opts.marker\n ? { storageHash: opts.marker.storageHash, profileHash: opts.marker.profileHash }\n : undefined,\n ),\n target: {\n expected: opts.expectedTargetId,\n ...ifDefined('actual', opts.actualTargetId),\n },\n meta: {\n contractPath: opts.contractPath,\n ...ifDefined('configPath', opts.configPath),\n },\n timings: { total: opts.totalTime },\n };\n}\n\nexport function createMongoFamilyInstance(_controlStack: ControlStack): MongoControlFamilyInstance {\n return new MongoFamilyInstance();\n}\n","import type {\n ControlFamilyDescriptor,\n ControlStack,\n} from '@prisma-next/framework-components/control';\nimport { mongoEmission } from '@prisma-next/mongo-emitter';\nimport { createMongoFamilyInstance, type MongoControlFamilyInstance } from './control-instance';\n\nclass MongoFamilyDescriptor\n implements ControlFamilyDescriptor<'mongo', MongoControlFamilyInstance>\n{\n readonly kind = 'family' as const;\n readonly id = 'mongo';\n readonly familyId = 'mongo' as const;\n readonly version = '0.0.1';\n readonly emission = mongoEmission;\n\n create<TTargetId extends string>(\n stack: ControlStack<'mongo', TTargetId>,\n ): MongoControlFamilyInstance {\n return createMongoFamilyInstance(stack);\n }\n}\n\nexport const mongoFamilyDescriptor: ControlFamilyDescriptor<'mongo', MongoControlFamilyInstance> =\n new MongoFamilyDescriptor();\n","import { createMongoRunnerDeps, extractDb } from '@prisma-next/adapter-mongo/control';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { MongoDriverImpl } from '@prisma-next/driver-mongo';\nimport type {\n MigratableTargetDescriptor,\n MigrationRunner,\n} from '@prisma-next/framework-components/control';\nimport type { MongoContract } from '@prisma-next/mongo-contract';\nimport {\n contractToMongoSchemaIR,\n MongoMigrationPlanner,\n MongoMigrationRunner,\n type MongoRunnerDependencies,\n} from '@prisma-next/target-mongo/control';\nimport mongoTargetDescriptorMeta from '@prisma-next/target-mongo/pack';\nimport type { MongoControlFamilyInstance } from './control-instance';\n\n/**\n * `migration.ts` default-exports a `Migration` subclass whose `operations`\n * getter returns the ordered list of operations and whose `describe()`\n * returns the manifest identity metadata. `MongoMigrationPlanner.plan()`\n * returns a `MigrationPlanWithAuthoringSurface` that knows how to render\n * itself back to such a file; `MongoMigrationPlanner.emptyMigration()`\n * returns the same shape for `migration new`. Users run the scaffolded\n * `migration.ts` directly (via `node migration.ts`) to self-emit\n * `ops.json` and attest the `migrationId`.\n */\nexport const mongoTargetDescriptor: MigratableTargetDescriptor<\n 'mongo',\n 'mongo',\n MongoControlFamilyInstance\n> = {\n ...mongoTargetDescriptorMeta,\n migrations: {\n createPlanner(_family: MongoControlFamilyInstance) {\n return new MongoMigrationPlanner();\n },\n createRunner(family: MongoControlFamilyInstance) {\n // Deps are bound to the first driver passed to execute() and cached for\n // subsequent calls. Callers must not change the driver between calls.\n let cachedDeps: MongoRunnerDependencies | undefined;\n const runner: MigrationRunner<'mongo', 'mongo'> = {\n async execute(options) {\n cachedDeps ??= createMongoRunnerDeps(\n options.driver,\n MongoDriverImpl.fromDb(extractDb(options.driver)),\n family,\n );\n const { driver: _, ...runnerOptions } = options;\n // The framework `MigrationRunner` interface types `destinationContract`\n // as `unknown`; the Mongo runner narrows to `MongoContract`. Validation\n // happens upstream — `migration apply` calls\n // `familyInstance.validateContract(migration.toContract)` before\n // routing the contract here (see\n // `packages/1-framework/3-tooling/cli/src/control-api/operations/migration-apply.ts`),\n // so this cast simply preserves the framework signature without\n // weakening the runner's typed surface or duplicating validation.\n return new MongoMigrationRunner(cachedDeps).execute({\n ...runnerOptions,\n destinationContract: runnerOptions.destinationContract as MongoContract,\n });\n },\n };\n return runner;\n },\n contractToSchema(contract: Contract | null) {\n return contractToMongoSchemaIR(contract as MongoContract | null);\n },\n },\n create() {\n return { familyId: 'mongo' as const, targetId: 'mongo' as const };\n },\n};\n"],"mappings":";;;;;;;;;;;AAKA,SAAgB,kBAAkB,QAAuC;CACvE,MAAM,kBAAkB,OAAO,YAAY,KAAK,eAC9C,uBAAuB,WAAW,MAAM,WAAW,CACpD;AAED,QAAO,EACL,MAAM,IAAI,eAAe;EACvB,MAAM;EACN,IAAI;EACJ,OAAO;EACP,GAAG,UAAU,YAAY,gBAAgB,SAAS,IAAI,kBAAkB,OAAU;EACnF,CAAC,EACH;;AAGH,SAAS,uBAAuB,MAAc,YAAmD;CAC/F,MAAMA,WAA6B,EAAE;AAErC,MAAK,MAAM,SAAS,WAAW,SAAS;EACtC,MAAM,cAAc,MAAM,KACvB,KAAK,MAAM;AACV,OAAI,EAAE,cAAc,EAAG,QAAO,EAAE;AAChC,OAAI,EAAE,cAAc,GAAI,QAAO,GAAG,EAAE,MAAM;AAC1C,UAAO,GAAG,EAAE,MAAM,GAAG,EAAE;IACvB,CACD,KAAK,KAAK;EACb,MAAM,SAAS,MAAM,SAAS,iBAAiB;EAC/C,MAAMC,UAAoB,EAAE;AAC5B,MAAI,MAAM,OAAQ,SAAQ,KAAK,SAAS;AACxC,MAAI,MAAM,sBAAsB,KAAM,SAAQ,KAAK,QAAQ,MAAM,mBAAmB,GAAG;AACvF,MAAI,MAAM,wBAAyB,SAAQ,KAAK,UAAU;EAC1D,MAAM,aAAa,QAAQ,SAAS,IAAI,KAAK,QAAQ,KAAK,KAAK,CAAC,KAAK;AAErE,WAAS,KACP,IAAI,eAAe;GACjB,MAAM;GACN,IAAI,SAAS,KAAK,GAAG,MAAM,KAAK,KAAK,MAAM,GAAG,EAAE,MAAM,GAAG,EAAE,YAAY,CAAC,KAAK,IAAI;GACjF,OAAO,GAAG,OAAO,IAAI,YAAY,GAAG;GACpC,MAAM;IACJ,MAAM,MAAM;IACZ,QAAQ,MAAM;IACd,GAAG,UAAU,UAAU,MAAM,UAAU,OAAU;IACjD,GAAG,UAAU,sBAAsB,MAAM,sBAAsB,OAAU;IACzE,GAAG,UAAU,2BAA2B,MAAM,2BAA2B,OAAU;IACpF;GACF,CAAC,CACH;;AAGH,KAAI,WAAW,WAAW;EACxB,MAAMC,oBAAsC,EAAE;EAC9C,MAAM,aAAa,WAAW,UAAU;EACxC,MAAM,aAAa,WAAW;EAG9B,MAAM,WAAW,IAAI,IAAK,WAAW,eAAwC,EAAE,CAAC;AAEhF,MAAI,WACF,MAAK,MAAM,CAAC,UAAU,YAAY,OAAO,QAAQ,WAAW,EAAE;GAC5D,MAAM,WAAY,QAAQ,eAA0B;GACpD,MAAM,SAAS,SAAS,IAAI,SAAS,GAAG,gBAAgB;AACxD,qBAAkB,KAChB,IAAI,eAAe;IACjB,MAAM;IACN,IAAI,SAAS,KAAK,GAAG;IACrB,OAAO,GAAG,SAAS,IAAI,WAAW;IACnC,CAAC,CACH;;AAIL,WAAS,KACP,IAAI,eAAe;GACjB,MAAM;GACN,IAAI,aAAa;GACjB,OAAO,qBAAqB,WAAW,UAAU,gBAAgB,YAAY,WAAW,UAAU,iBAAiB;GACnH,MAAM;IACJ,iBAAiB,WAAW,UAAU;IACtC,kBAAkB,WAAW,UAAU;IACvC,YAAY,WAAW,UAAU;IAClC;GACD,GAAG,UAAU,YAAY,kBAAkB,SAAS,IAAI,oBAAoB,OAAU;GACvF,CAAC,CACH;;AAGH,KAAI,WAAW,SAAS;EACtB,MAAM,OAAO,WAAW;EACxB,MAAMC,YAAsB,EAAE;AAC9B,MAAI,KAAK,OAAQ,WAAU,KAAK,SAAS;AACzC,MAAI,KAAK,WAAY,WAAU,KAAK,aAAa;AACjD,MAAI,KAAK,UAAW,WAAU,KAAK,YAAY;AAC/C,MAAI,KAAK,6BAA8B,WAAU,KAAK,+BAA+B;AACrF,MAAI,KAAK,eAAgB,WAAU,KAAK,iBAAiB;AAEzD,MAAI,UAAU,SAAS,EACrB,UAAS,KACP,IAAI,eAAe;GACjB,MAAM;GACN,IAAI,WAAW;GACf,OAAO,YAAY,UAAU,KAAK,KAAK,CAAC;GACxC,MAAM;IACJ,GAAG,UAAU,UAAU,KAAK,UAAU,OAAU;IAChD,GAAG,UAAU,cAAc,KAAK,cAAc,OAAU;IACxD,GAAG,UAAU,aAAa,KAAK,aAAa,OAAU;IACtD,GAAG,UACD,gCACA,KAAK,gCAAgC,OACtC;IACD,GAAG,UAAU,kBAAkB,KAAK,kBAAkB,OAAU;IACjE;GACF,CAAC,CACH;;AAIL,QAAO,IAAI,eAAe;EACxB,MAAM;EACN,IAAI,cAAc;EAClB,OAAO,cAAc;EACrB,GAAG,UAAU,YAAY,SAAS,SAAS,IAAI,WAAW,OAAU;EACrE,CAAC;;;;;AC7FJ,SAASC,YAAU,QAAoD;CACrE,MAAM,cAAc;AACpB,KAAI,CAAC,YAAY,GACf,OAAM,IAAI,MACR,8HAED;AAEH,QAAO,YAAY;;AAGrB,IAAM,sBAAN,MAAgE;CAC9D,AAAS,WAAW;CAEpB,iBAAiB,cAAiC;AAIhD,SAHkB,sBAAqC,aAAa,CAGnD;;CAGnB,MAAM,OAAO,SAMqB;EAChC,MAAM,EAAE,QAAQ,UAAU,aAAa,kBAAkB,cAAc,eAAe;EACtF,MAAM,YAAY,KAAK,KAAK;EAG5B,MAAM,WADY,sBAAqC,YAAY,CACxC;EAE3B,MAAM,sBAAsB,SAAS,QAAQ;EAC7C,MAAM,sBAAsB,SAAS;EACrC,MAAM,iBAAiB,SAAS;EAEhC,MAAM,WAAW;GACf;GACA;GACA;GACA;GACA,GAAG,UAAU,cAAc,WAAW;GACvC;AAED,MAAI,mBAAmB,iBACrB,QAAO,kBAAkB;GACvB,GAAG;GACH,IAAI;GACJ,MAAM;GACN,SAAS;GACT,gBAAgB;GAChB,WAAW,KAAK,KAAK,GAAG;GACzB,CAAC;EAIJ,MAAM,SAAS,MAAM,WADVA,YAAU,OAAO,CACO;AAEnC,MAAI,CAAC,OACH,QAAO,kBAAkB;GACvB,GAAG;GACH,IAAI;GACJ,MAAM;GACN,SAAS;GACT,WAAW,KAAK,KAAK,GAAG;GACzB,CAAC;AAGJ,MAAI,OAAO,gBAAgB,oBACzB,QAAO,kBAAkB;GACvB,GAAG;GACH,IAAI;GACJ,MAAM;GACN,SAAS;GACT;GACA,WAAW,KAAK,KAAK,GAAG;GACzB,CAAC;AAGJ,MAAI,uBAAuB,OAAO,gBAAgB,oBAChD,QAAO,kBAAkB;GACvB,GAAG;GACH,IAAI;GACJ,MAAM;GACN,SAAS;GACT;GACA,WAAW,KAAK,KAAK,GAAG;GACzB,CAAC;AAGJ,SAAO,kBAAkB;GACvB,GAAG;GACH,IAAI;GACJ,SAAS;GACT;GACA,WAAW,KAAK,KAAK,GAAG;GACzB,CAAC;;CAGJ,MAAM,aAAa,SAOqB;EACtC,MAAM,EAAE,QAAQ,UAAU,aAAa,QAAQ,cAAc,eAAe;EAG5E,MAAM,WADY,sBAAqC,YAAY,CACxC;AAK3B,SAAO,kBAAkB;GACvB;GACA,QAJa,MAAM,iBADVA,YAAU,OAAO,CACa;GAKvC;GACA,qBAAqB,QAAQ;GAC7B,SAAS;IACP;IACA,GAAG,UAAU,cAAc,WAAW;IACvC;GACF,CAAC;;CAGJ,MAAM,KAAK,SAKqB;EAC9B,MAAM,EAAE,QAAQ,UAAU,aAAa,cAAc,eAAe;EACpE,MAAM,YAAY,KAAK,KAAK;EAG5B,MAAM,WADY,sBAAqC,YAAY,CACxC;EAE3B,MAAM,sBAAsB,SAAS,QAAQ;EAC7C,MAAM,sBAAsB,SAAS;EAErC,MAAM,KAAKA,YAAU,OAAO;EAE5B,MAAM,iBAAiB,MAAM,WAAW,GAAG;EAE3C,IAAI,gBAAgB;EACpB,IAAI,gBAAgB;EACpB,IAAIC;AAEJ,MAAI,CAAC,gBAAgB;AACnB,SAAM,WAAW,IAAI;IACnB,aAAa;IACb,aAAa;IACd,CAAC;AACF,mBAAgB;SACX;GACL,MAAM,qBAAqB,eAAe,gBAAgB;GAC1D,MAAM,qBAAqB,eAAe,gBAAgB;AAE1D,OAAI,CAAC,sBAAsB,CAAC,oBAAoB;AAC9C,qBAAiB;KACf,aAAa,eAAe;KAC5B,aAAa,eAAe;KAC7B;AAKD,QAAI,CAJY,MAAM,aAAa,IAAI,eAAe,aAAa;KACjE,aAAa;KACb,aAAa;KACd,CAAC,CAEA,OAAM,IAAI,MAAM,mEAAmE;AAErF,oBAAgB;;;EAIpB,IAAIC;AACJ,MAAI,cACF,WAAU;WACD,cACT,WAAU,wCAAwC,gBAAgB,eAAe,UAAU;MAE3F,WAAU;AAGZ,SAAO;GACL,IAAI;GACJ;GACA,UAAU;IACR,aAAa;IACb,aAAa;IACd;GACD,QAAQ;IACN,UAAU,SAAS;IACnB,QAAQ,SAAS;IAClB;GACD,QAAQ;IACN,SAAS;IACT,SAAS;IACT,GAAG,UAAU,YAAY,eAAe;IACzC;GACD,MAAM;IACJ;IACA,GAAG,UAAU,cAAc,WAAW;IACvC;GACD,SAAS,EACP,OAAO,KAAK,KAAK,GAAG,WACrB;GACF;;CAGH,MAAM,WAAW,SAEwB;AAEvC,SAAO,WADIF,YAAU,QAAQ,OAAO,CACf;;CAGvB,MAAM,WAAW,SAGU;AAEzB,SAAO,iBADIA,YAAU,QAAQ,OAAO,CACT;;CAG7B,aAAa,QAAuC;AAClD,SAAO,kBAAkB,OAAO;;;AAIpC,SAAS,kBAAkB,MAYF;AACvB,QAAO;EACL,IAAI,KAAK;EACT,GAAG,UAAU,QAAQ,KAAK,KAAK;EAC/B,SAAS,KAAK;EACd,UAAU;GACR,aAAa,KAAK;GAClB,GAAG,UAAU,eAAe,KAAK,oBAAoB;GACtD;EACD,GAAG,UACD,UACA,KAAK,SACD;GAAE,aAAa,KAAK,OAAO;GAAa,aAAa,KAAK,OAAO;GAAa,GAC9E,OACL;EACD,QAAQ;GACN,UAAU,KAAK;GACf,GAAG,UAAU,UAAU,KAAK,eAAe;GAC5C;EACD,MAAM;GACJ,cAAc,KAAK;GACnB,GAAG,UAAU,cAAc,KAAK,WAAW;GAC5C;EACD,SAAS,EAAE,OAAO,KAAK,WAAW;EACnC;;AAGH,SAAgB,0BAA0B,eAAyD;AACjG,QAAO,IAAI,qBAAqB;;;;;AC3SlC,IAAM,wBAAN,MAEA;CACE,AAAS,OAAO;CAChB,AAAS,KAAK;CACd,AAAS,WAAW;CACpB,AAAS,UAAU;CACnB,AAAS,WAAW;CAEpB,OACE,OAC4B;AAC5B,SAAO,0BAA0B,MAAM;;;AAI3C,MAAaG,wBACX,IAAI,uBAAuB;;;;;;;;;;;;;;ACG7B,MAAaC,wBAIT;CACF,GAAG;CACH,YAAY;EACV,cAAc,SAAqC;AACjD,UAAO,IAAI,uBAAuB;;EAEpC,aAAa,QAAoC;GAG/C,IAAIC;AAuBJ,UAtBkD,EAChD,MAAM,QAAQ,SAAS;AACrB,mBAAe,sBACb,QAAQ,QACR,gBAAgB,OAAO,UAAU,QAAQ,OAAO,CAAC,EACjD,OACD;IACD,MAAM,EAAE,QAAQ,GAAG,GAAG,kBAAkB;AASxC,WAAO,IAAI,qBAAqB,WAAW,CAAC,QAAQ;KAClD,GAAG;KACH,qBAAqB,cAAc;KACpC,CAAC;MAEL;;EAGH,iBAAiB,UAA2B;AAC1C,UAAO,wBAAwB,SAAiC;;EAEnE;CACD,SAAS;AACP,SAAO;GAAE,UAAU;GAAkB,UAAU;GAAkB;;CAEpE"}
1
+ {"version":3,"file":"control.mjs","names":["extractDb"],"sources":["../src/core/schema-to-view.ts","../src/core/control-instance.ts","../src/core/control-descriptor.ts","../src/core/mongo-target-descriptor.ts"],"sourcesContent":["import type { CoreSchemaView } from '@prisma-next/framework-components/control';\nimport { SchemaTreeNode } from '@prisma-next/framework-components/control';\nimport type { MongoSchemaCollection, MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport { ifDefined } from '@prisma-next/utils/defined';\n\nexport function mongoSchemaToView(schema: MongoSchemaIR): CoreSchemaView {\n const collectionNodes = schema.collections.map((collection) =>\n collectionToSchemaNode(collection.name, collection),\n );\n\n return {\n root: new SchemaTreeNode({\n kind: 'root',\n id: 'mongo-schema',\n label: 'database',\n ...ifDefined('children', collectionNodes.length > 0 ? collectionNodes : undefined),\n }),\n };\n}\n\nfunction collectionToSchemaNode(name: string, collection: MongoSchemaCollection): SchemaTreeNode {\n const children: SchemaTreeNode[] = [];\n\n for (const index of collection.indexes) {\n const keysSummary = index.keys\n .map((k) => {\n if (k.direction === 1) return k.field;\n if (k.direction === -1) return `${k.field} desc`;\n return `${k.field} ${k.direction}`;\n })\n .join(', ');\n const prefix = index.unique ? 'unique index' : 'index';\n const options: string[] = [];\n if (index.sparse) options.push('sparse');\n if (index.expireAfterSeconds != null) options.push(`ttl: ${index.expireAfterSeconds}s`);\n if (index.partialFilterExpression) options.push('partial');\n const optsSuffix = options.length > 0 ? ` (${options.join(', ')})` : '';\n\n children.push(\n new SchemaTreeNode({\n kind: 'index',\n id: `index-${name}-${index.keys.map((k) => `${k.field}_${k.direction}`).join('_')}`,\n label: `${prefix} (${keysSummary})${optsSuffix}`,\n meta: {\n keys: index.keys,\n unique: index.unique,\n ...ifDefined('sparse', index.sparse || undefined),\n ...ifDefined('expireAfterSeconds', index.expireAfterSeconds ?? undefined),\n ...ifDefined('partialFilterExpression', index.partialFilterExpression ?? undefined),\n },\n }),\n );\n }\n\n if (collection.validator) {\n const validatorChildren: SchemaTreeNode[] = [];\n const jsonSchema = collection.validator.jsonSchema as Record<string, unknown>;\n const properties = jsonSchema['properties'] as\n | Record<string, Record<string, unknown>>\n | undefined;\n const required = new Set((jsonSchema['required'] as string[] | undefined) ?? []);\n\n if (properties) {\n for (const [propName, propDef] of Object.entries(properties)) {\n const bsonType = (propDef['bsonType'] as string) ?? 'unknown';\n const suffix = required.has(propName) ? ' (required)' : '';\n validatorChildren.push(\n new SchemaTreeNode({\n kind: 'field',\n id: `field-${name}-${propName}`,\n label: `${propName}: ${bsonType}${suffix}`,\n }),\n );\n }\n }\n\n children.push(\n new SchemaTreeNode({\n kind: 'field',\n id: `validator-${name}`,\n label: `validator (level: ${collection.validator.validationLevel}, action: ${collection.validator.validationAction})`,\n meta: {\n validationLevel: collection.validator.validationLevel,\n validationAction: collection.validator.validationAction,\n jsonSchema: collection.validator.jsonSchema,\n },\n ...ifDefined('children', validatorChildren.length > 0 ? validatorChildren : undefined),\n }),\n );\n }\n\n if (collection.options) {\n const opts = collection.options;\n const optLabels: string[] = [];\n if (opts.capped) optLabels.push('capped');\n if (opts.timeseries) optLabels.push('timeseries');\n if (opts.collation) optLabels.push('collation');\n if (opts.changeStreamPreAndPostImages) optLabels.push('changeStreamPreAndPostImages');\n if (opts.clusteredIndex) optLabels.push('clusteredIndex');\n\n if (optLabels.length > 0) {\n children.push(\n new SchemaTreeNode({\n kind: 'field',\n id: `options-${name}`,\n label: `options (${optLabels.join(', ')})`,\n meta: {\n ...ifDefined('capped', opts.capped ?? undefined),\n ...ifDefined('timeseries', opts.timeseries ?? undefined),\n ...ifDefined('collation', opts.collation ?? undefined),\n ...ifDefined(\n 'changeStreamPreAndPostImages',\n opts.changeStreamPreAndPostImages ?? undefined,\n ),\n ...ifDefined('clusteredIndex', opts.clusteredIndex ?? undefined),\n },\n }),\n );\n }\n }\n\n return new SchemaTreeNode({\n kind: 'collection',\n id: `collection-${name}`,\n label: `collection ${name}`,\n ...ifDefined('children', children.length > 0 ? children : undefined),\n });\n}\n","import { introspectSchema } from '@prisma-next/adapter-mongo/control';\nimport type { Contract, ContractMarkerRecord } from '@prisma-next/contract/types';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n ControlStack,\n CoreSchemaView,\n MigrationPlanOperation,\n OperationPreview,\n OperationPreviewCapable,\n SchemaViewCapable,\n SignDatabaseResult,\n VerifyDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/framework-components/control';\nimport {\n APP_SPACE_ID,\n VERIFY_CODE_HASH_MISMATCH,\n VERIFY_CODE_MARKER_MISSING,\n VERIFY_CODE_TARGET_MISMATCH,\n} from '@prisma-next/framework-components/control';\nimport type { MongoContract } from '@prisma-next/mongo-contract';\nimport { validateMongoContract } from '@prisma-next/mongo-contract';\nimport type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport {\n formatMongoOperations,\n initMarker,\n readMarker,\n updateMarker,\n} from '@prisma-next/target-mongo/control';\nimport { verifyMongoSchema } from '@prisma-next/target-mongo/schema-verify';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { Db } from 'mongodb';\nimport { mongoSchemaToView } from './schema-to-view';\n\nexport interface MongoControlFamilyInstance\n extends ControlFamilyInstance<'mongo', MongoSchemaIR>,\n SchemaViewCapable<MongoSchemaIR>,\n OperationPreviewCapable {\n validateContract(contractJson: unknown): Contract;\n}\n\nfunction extractDb(driver: ControlDriverInstance<'mongo', string>): Db {\n const mongoDriver = driver as ControlDriverInstance<'mongo', string> & { db?: Db };\n if (!mongoDriver.db) {\n throw new Error(\n 'Mongo control driver does not expose a db property. ' +\n 'Use createMongoControlDriver() from @prisma-next/adapter-mongo/control.',\n );\n }\n return mongoDriver.db;\n}\n\nclass MongoFamilyInstance implements MongoControlFamilyInstance {\n readonly familyId = 'mongo' as const;\n\n validateContract(contractJson: unknown): Contract {\n const validated = validateMongoContract<MongoContract>(contractJson);\n // MongoContract and Contract share structure but are typed independently;\n // validateMongoContract guarantees the shape, so the double cast is safe.\n return validated.contract as unknown as Contract;\n }\n\n async verify(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract: unknown;\n readonly expectedTargetId: string;\n readonly contractPath: string;\n readonly configPath?: string;\n }): Promise<VerifyDatabaseResult> {\n const { driver, contract: rawContract, expectedTargetId, contractPath, configPath } = options;\n const startTime = Date.now();\n\n const validated = validateMongoContract<MongoContract>(rawContract);\n const contract = validated.contract;\n\n const contractStorageHash = contract.storage.storageHash;\n const contractProfileHash = contract.profileHash;\n const contractTarget = contract.target;\n\n const baseOpts = {\n contractStorageHash,\n contractProfileHash,\n expectedTargetId,\n contractPath,\n ...ifDefined('configPath', configPath),\n };\n\n if (contractTarget !== expectedTargetId) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_TARGET_MISMATCH,\n summary: 'Target mismatch',\n actualTargetId: contractTarget,\n totalTime: Date.now() - startTime,\n });\n }\n\n const db = extractDb(driver);\n const marker = await readMarker(db);\n\n if (!marker) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_MARKER_MISSING,\n summary: 'Marker missing',\n totalTime: Date.now() - startTime,\n });\n }\n\n if (marker.storageHash !== contractStorageHash) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_HASH_MISMATCH,\n summary: 'Hash mismatch',\n marker,\n totalTime: Date.now() - startTime,\n });\n }\n\n if (contractProfileHash && marker.profileHash !== contractProfileHash) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_HASH_MISMATCH,\n summary: 'Hash mismatch',\n marker,\n totalTime: Date.now() - startTime,\n });\n }\n\n return buildVerifyResult({\n ...baseOpts,\n ok: true,\n summary: 'Database matches contract',\n marker,\n totalTime: Date.now() - startTime,\n });\n }\n\n async schemaVerify(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract: unknown;\n readonly strict: boolean;\n readonly contractPath: string;\n readonly configPath?: string;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'mongo', string>>;\n }): Promise<VerifyDatabaseSchemaResult> {\n const { driver, contract: rawContract, strict, contractPath, configPath } = options;\n\n const validated = validateMongoContract<MongoContract>(rawContract);\n const contract = validated.contract;\n\n const db = extractDb(driver);\n const liveIR = await introspectSchema(db);\n\n return verifyMongoSchema({\n contract,\n schema: liveIR,\n strict,\n frameworkComponents: options.frameworkComponents,\n context: {\n contractPath,\n ...ifDefined('configPath', configPath),\n },\n });\n }\n\n schemaVerifyAgainstSchema(options: {\n readonly contract: unknown;\n readonly schema: MongoSchemaIR;\n readonly strict: boolean;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'mongo', string>>;\n }): VerifyDatabaseSchemaResult {\n const validated = validateMongoContract<MongoContract>(options.contract);\n return verifyMongoSchema({\n contract: validated.contract,\n schema: options.schema,\n strict: options.strict,\n frameworkComponents: options.frameworkComponents,\n });\n }\n\n async sign(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract: unknown;\n readonly contractPath: string;\n readonly configPath?: string;\n }): Promise<SignDatabaseResult> {\n const { driver, contract: rawContract, contractPath, configPath } = options;\n const startTime = Date.now();\n\n const validated = validateMongoContract<MongoContract>(rawContract);\n const contract = validated.contract;\n\n const contractStorageHash = contract.storage.storageHash;\n const contractProfileHash = contract.profileHash;\n\n const db = extractDb(driver);\n\n const existingMarker = await readMarker(db);\n\n let markerCreated = false;\n let markerUpdated = false;\n let previousHashes: { storageHash?: string; profileHash?: string } | undefined;\n\n if (!existingMarker) {\n await initMarker(db, {\n storageHash: contractStorageHash,\n profileHash: contractProfileHash,\n });\n markerCreated = true;\n } else {\n const storageHashMatches = existingMarker.storageHash === contractStorageHash;\n const profileHashMatches = existingMarker.profileHash === contractProfileHash;\n\n if (!storageHashMatches || !profileHashMatches) {\n previousHashes = {\n storageHash: existingMarker.storageHash,\n profileHash: existingMarker.profileHash,\n };\n const updated = await updateMarker(db, existingMarker.storageHash, {\n storageHash: contractStorageHash,\n profileHash: contractProfileHash,\n });\n if (!updated) {\n throw new Error('CAS conflict: marker was modified by another process during sign');\n }\n markerUpdated = true;\n }\n }\n\n let summary: string;\n if (markerCreated) {\n summary = 'Database signed (marker created)';\n } else if (markerUpdated) {\n summary = `Database signed (marker updated from ${previousHashes?.storageHash ?? 'unknown'})`;\n } else {\n summary = 'Database already signed with this contract';\n }\n\n return {\n ok: true,\n summary,\n contract: {\n storageHash: contractStorageHash,\n profileHash: contractProfileHash,\n },\n target: {\n expected: contract.target,\n actual: contract.target,\n },\n marker: {\n created: markerCreated,\n updated: markerUpdated,\n ...ifDefined('previous', previousHashes),\n },\n meta: {\n contractPath,\n ...ifDefined('configPath', configPath),\n },\n timings: {\n total: Date.now() - startTime,\n },\n };\n }\n\n async readMarker(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly space: string;\n }): Promise<ContractMarkerRecord | null> {\n if (options.space !== APP_SPACE_ID) {\n throw new Error(\n 'Mongo target does not yet support per-space contract markers. ' +\n `readMarker was called with space=\"${options.space}\", but only \"${APP_SPACE_ID}\" is supported. ` +\n 'Per-space marker support is tracked separately for Mongo and is not part of the SQL-family contract-spaces work.',\n );\n }\n const db = extractDb(options.driver);\n return readMarker(db);\n }\n\n // Mongo does not yet participate in the per-space mechanism — the\n // `space` column was introduced in the SQL family's marker only.\n // The bridge: surface the single app marker keyed by APP_SPACE_ID so\n // the per-space verifier sees a coherent input shape; per-space mongo\n // support is a future extension.\n async readAllMarkers(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n }): Promise<ReadonlyMap<string, ContractMarkerRecord>> {\n const appMarker = await this.readMarker({ ...options, space: APP_SPACE_ID });\n if (appMarker === null) return new Map();\n return new Map([[APP_SPACE_ID, appMarker]]);\n }\n\n async introspect(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract?: unknown;\n }): Promise<MongoSchemaIR> {\n const db = extractDb(options.driver);\n return introspectSchema(db);\n }\n\n toSchemaView(schema: MongoSchemaIR): CoreSchemaView {\n return mongoSchemaToView(schema);\n }\n\n toOperationPreview(operations: readonly MigrationPlanOperation[]): OperationPreview {\n return {\n statements: formatMongoOperations(operations).map((text) => ({\n text,\n language: 'mongodb-shell',\n })),\n };\n }\n}\n\nfunction buildVerifyResult(opts: {\n ok: boolean;\n code?: string;\n summary: string;\n contractStorageHash: string;\n contractProfileHash?: string;\n marker?: ContractMarkerRecord;\n expectedTargetId: string;\n actualTargetId?: string;\n contractPath: string;\n configPath?: string;\n totalTime: number;\n}): VerifyDatabaseResult {\n return {\n ok: opts.ok,\n ...ifDefined('code', opts.code),\n summary: opts.summary,\n contract: {\n storageHash: opts.contractStorageHash,\n ...ifDefined('profileHash', opts.contractProfileHash),\n },\n ...ifDefined(\n 'marker',\n opts.marker\n ? { storageHash: opts.marker.storageHash, profileHash: opts.marker.profileHash }\n : undefined,\n ),\n target: {\n expected: opts.expectedTargetId,\n ...ifDefined('actual', opts.actualTargetId),\n },\n meta: {\n contractPath: opts.contractPath,\n ...ifDefined('configPath', opts.configPath),\n },\n timings: { total: opts.totalTime },\n };\n}\n\nexport function createMongoFamilyInstance(_controlStack: ControlStack): MongoControlFamilyInstance {\n return new MongoFamilyInstance();\n}\n","import type {\n ControlFamilyDescriptor,\n ControlStack,\n} from '@prisma-next/framework-components/control';\nimport { mongoEmission } from '@prisma-next/mongo-emitter';\nimport { createMongoFamilyInstance, type MongoControlFamilyInstance } from './control-instance';\n\nclass MongoFamilyDescriptor\n implements ControlFamilyDescriptor<'mongo', MongoControlFamilyInstance>\n{\n readonly kind = 'family' as const;\n readonly id = 'mongo';\n readonly familyId = 'mongo' as const;\n readonly version = '0.0.1';\n readonly emission = mongoEmission;\n\n create<TTargetId extends string>(\n stack: ControlStack<'mongo', TTargetId>,\n ): MongoControlFamilyInstance {\n return createMongoFamilyInstance(stack);\n }\n}\n\nexport const mongoFamilyDescriptor: ControlFamilyDescriptor<'mongo', MongoControlFamilyInstance> =\n new MongoFamilyDescriptor();\n","import { createMongoRunnerDeps, extractDb } from '@prisma-next/adapter-mongo/control';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { MongoDriverImpl } from '@prisma-next/driver-mongo';\nimport type {\n MigratableTargetDescriptor,\n MigrationRunner,\n} from '@prisma-next/framework-components/control';\nimport type { MongoContract } from '@prisma-next/mongo-contract';\nimport {\n contractToMongoSchemaIR,\n MongoMigrationPlanner,\n MongoMigrationRunner,\n type MongoRunnerDependencies,\n} from '@prisma-next/target-mongo/control';\nimport mongoTargetDescriptorMeta from '@prisma-next/target-mongo/pack';\nimport type { MongoControlFamilyInstance } from './control-instance';\n\n/**\n * `migration.ts` default-exports a `Migration` subclass whose `operations`\n * getter returns the ordered list of operations and whose `describe()`\n * returns the manifest identity metadata. `MongoMigrationPlanner.plan()`\n * returns a `MigrationPlanWithAuthoringSurface` that knows how to render\n * itself back to such a file; `MongoMigrationPlanner.emptyMigration()`\n * returns the same shape for `migration new`. Users run the scaffolded\n * `migration.ts` directly (via `node migration.ts`) to self-emit\n * `ops.json` and attest the `migrationHash`.\n */\nexport const mongoTargetDescriptor: MigratableTargetDescriptor<\n 'mongo',\n 'mongo',\n MongoControlFamilyInstance\n> = {\n ...mongoTargetDescriptorMeta,\n migrations: {\n createPlanner(_family: MongoControlFamilyInstance) {\n return new MongoMigrationPlanner();\n },\n createRunner(family: MongoControlFamilyInstance) {\n // Deps are bound to the first driver passed to execute() and cached for\n // subsequent calls. Callers must not change the driver between calls.\n let cachedDeps: MongoRunnerDependencies | undefined;\n const runner: MigrationRunner<'mongo', 'mongo'> = {\n async execute(options) {\n cachedDeps ??= createMongoRunnerDeps(\n options.driver,\n MongoDriverImpl.fromDb(extractDb(options.driver)),\n family,\n );\n const { driver: _, ...runnerOptions } = options;\n // The framework `MigrationRunner` interface types `destinationContract`\n // as `unknown`; the Mongo runner narrows to `MongoContract`. Validation\n // happens upstream — `migration apply` calls\n // `familyInstance.validateContract(migration.toContract)` before\n // routing the contract here (see\n // `packages/1-framework/3-tooling/cli/src/control-api/operations/migration-apply.ts`),\n // so this cast simply preserves the framework signature without\n // weakening the runner's typed surface or duplicating validation.\n return new MongoMigrationRunner(cachedDeps).execute({\n ...runnerOptions,\n destinationContract: runnerOptions.destinationContract as MongoContract,\n });\n },\n };\n return runner;\n },\n contractToSchema(contract: Contract | null) {\n return contractToMongoSchemaIR(contract as MongoContract | null);\n },\n },\n create() {\n return { familyId: 'mongo' as const, targetId: 'mongo' as const };\n },\n};\n"],"mappings":"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"}
@@ -2,7 +2,6 @@ import { Migration } from "@prisma-next/migration-tools/migration";
2
2
  import { AnyMongoMigrationOperation } from "@prisma-next/mongo-query-ast/control";
3
3
 
4
4
  //#region src/core/mongo-migration.d.ts
5
-
6
5
  /**
7
6
  * Family-owned base class for Mongo migrations.
8
7
  *
@@ -1 +1 @@
1
- {"version":3,"file":"migration.d.mts","names":[],"sources":["../src/core/mongo-migration.ts"],"sourcesContent":[],"mappings":";;;;;;;AAiBA;;;;;;;;;;;;uBAAsB,cAAA,SAAuB,UAAU"}
1
+ {"version":3,"file":"migration.d.mts","names":[],"sources":["../src/core/mongo-migration.ts"],"mappings":";;;;;;AAiBA;;;;;;;;;;;;uBAAsB,cAAA,SAAuB,SAAA,CAAU,0BAAA;EAAA,SAC5C,QAAA;AAAA"}
@@ -1,5 +1,4 @@
1
1
  import { Migration } from "@prisma-next/migration-tools/migration";
2
-
3
2
  //#region src/core/mongo-migration.ts
4
3
  /**
5
4
  * Family-owned base class for Mongo migrations.
@@ -18,7 +17,7 @@ import { Migration } from "@prisma-next/migration-tools/migration";
18
17
  var MongoMigration = class extends Migration {
19
18
  targetId = "mongo";
20
19
  };
21
-
22
20
  //#endregion
23
21
  export { MongoMigration as Migration };
22
+
24
23
  //# sourceMappingURL=migration.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"migration.mjs","names":[],"sources":["../src/core/mongo-migration.ts"],"sourcesContent":["import { Migration } from '@prisma-next/migration-tools/migration';\nimport type { AnyMongoMigrationOperation } from '@prisma-next/mongo-query-ast/control';\n\n/**\n * Family-owned base class for Mongo migrations.\n *\n * Provides the fixed `targetId = 'mongo'` so that user-authored migrations\n * and renderer-generated scaffolds (e.g. the output of\n * `renderCallsToTypeScript`) inherit it directly and don't have to re-declare\n * the abstract `targetId` member from `Migration`.\n *\n * The operation type parameter is `AnyMongoMigrationOperation` — the union\n * of DDL-shaped `MongoMigrationPlanOperation` and `MongoDataTransformOperation` —\n * so subclasses can return a mix of schema operations (e.g. `createIndex`,\n * `setValidation`) and data-transform operations (e.g. `dataTransform`).\n * Mirrors the generic parameter used by `PlannerProducedMongoMigration`.\n */\nexport abstract class MongoMigration extends Migration<AnyMongoMigrationOperation> {\n readonly targetId = 'mongo' as const;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,IAAsB,iBAAtB,cAA6C,UAAsC;CACjF,AAAS,WAAW"}
1
+ {"version":3,"file":"migration.mjs","names":[],"sources":["../src/core/mongo-migration.ts"],"sourcesContent":["import { Migration } from '@prisma-next/migration-tools/migration';\nimport type { AnyMongoMigrationOperation } from '@prisma-next/mongo-query-ast/control';\n\n/**\n * Family-owned base class for Mongo migrations.\n *\n * Provides the fixed `targetId = 'mongo'` so that user-authored migrations\n * and renderer-generated scaffolds (e.g. the output of\n * `renderCallsToTypeScript`) inherit it directly and don't have to re-declare\n * the abstract `targetId` member from `Migration`.\n *\n * The operation type parameter is `AnyMongoMigrationOperation` — the union\n * of DDL-shaped `MongoMigrationPlanOperation` and `MongoDataTransformOperation` —\n * so subclasses can return a mix of schema operations (e.g. `createIndex`,\n * `setValidation`) and data-transform operations (e.g. `dataTransform`).\n * Mirrors the generic parameter used by `PlannerProducedMongoMigration`.\n */\nexport abstract class MongoMigration extends Migration<AnyMongoMigrationOperation> {\n readonly targetId = 'mongo' as const;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAiBA,IAAsB,iBAAtB,cAA6C,UAAsC;CACjF,WAAoB"}
@@ -1 +1 @@
1
- {"version":3,"file":"pack.d.mts","names":[],"sources":["../src/exports/pack.ts"],"sourcesContent":[],"mappings":";cAAM;EAAA,SAAA,IAAA,EAAA,QAKI"}
1
+ {"version":3,"file":"pack.d.mts","names":[],"sources":["../src/exports/pack.ts"],"mappings":";cAAM,eAAA;EAAA"}
package/dist/pack.mjs CHANGED
@@ -5,8 +5,7 @@ const mongoFamilyPack = {
5
5
  familyId: "mongo",
6
6
  version: "0.0.1"
7
7
  };
8
- var pack_default = mongoFamilyPack;
9
-
10
8
  //#endregion
11
- export { pack_default as default };
9
+ export { mongoFamilyPack as default };
10
+
12
11
  //# sourceMappingURL=pack.mjs.map
package/dist/pack.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"pack.mjs","names":[],"sources":["../src/exports/pack.ts"],"sourcesContent":["const mongoFamilyPack = {\n kind: 'family',\n id: 'mongo',\n familyId: 'mongo',\n version: '0.0.1',\n} as const;\n\nexport default mongoFamilyPack;\n"],"mappings":";AAAA,MAAM,kBAAkB;CACtB,MAAM;CACN,IAAI;CACJ,UAAU;CACV,SAAS;CACV;AAED,mBAAe"}
1
+ {"version":3,"file":"pack.mjs","names":[],"sources":["../src/exports/pack.ts"],"sourcesContent":["const mongoFamilyPack = {\n kind: 'family',\n id: 'mongo',\n familyId: 'mongo',\n version: '0.0.1',\n} as const;\n\nexport default mongoFamilyPack;\n"],"mappings":";AAAA,MAAM,kBAAkB;CACtB,MAAM;CACN,IAAI;CACJ,UAAU;CACV,SAAS;CACV"}
@@ -1,3 +1,2 @@
1
1
  import { verifyMongoSchema } from "@prisma-next/target-mongo/schema-verify";
2
-
3
- export { verifyMongoSchema };
2
+ export { verifyMongoSchema };
package/package.json CHANGED
@@ -1,32 +1,33 @@
1
1
  {
2
2
  "name": "@prisma-next/family-mongo",
3
- "version": "0.5.0-dev.7",
3
+ "version": "0.5.0-dev.71",
4
+ "license": "Apache-2.0",
4
5
  "type": "module",
5
6
  "sideEffects": false,
6
7
  "description": "Mongo family descriptor for Prisma Next",
7
8
  "dependencies": {
8
9
  "mongodb": "^6.16.0",
9
10
  "pathe": "^2.0.3",
10
- "@prisma-next/contract": "0.5.0-dev.7",
11
- "@prisma-next/emitter": "0.5.0-dev.7",
12
- "@prisma-next/driver-mongo": "0.5.0-dev.7",
13
- "@prisma-next/errors": "0.5.0-dev.7",
14
- "@prisma-next/mongo-contract": "0.5.0-dev.7",
15
- "@prisma-next/migration-tools": "0.5.0-dev.7",
16
- "@prisma-next/adapter-mongo": "0.5.0-dev.7",
17
- "@prisma-next/framework-components": "0.5.0-dev.7",
18
- "@prisma-next/mongo-emitter": "0.5.0-dev.7",
19
- "@prisma-next/mongo-query-ast": "0.5.0-dev.7",
20
- "@prisma-next/mongo-schema-ir": "0.5.0-dev.7",
21
- "@prisma-next/target-mongo": "0.5.0-dev.7",
22
- "@prisma-next/utils": "0.5.0-dev.7"
11
+ "@prisma-next/adapter-mongo": "0.5.0-dev.71",
12
+ "@prisma-next/contract": "0.5.0-dev.71",
13
+ "@prisma-next/driver-mongo": "0.5.0-dev.71",
14
+ "@prisma-next/emitter": "0.5.0-dev.71",
15
+ "@prisma-next/errors": "0.5.0-dev.71",
16
+ "@prisma-next/framework-components": "0.5.0-dev.71",
17
+ "@prisma-next/migration-tools": "0.5.0-dev.71",
18
+ "@prisma-next/mongo-contract": "0.5.0-dev.71",
19
+ "@prisma-next/mongo-emitter": "0.5.0-dev.71",
20
+ "@prisma-next/mongo-schema-ir": "0.5.0-dev.71",
21
+ "@prisma-next/mongo-query-ast": "0.5.0-dev.71",
22
+ "@prisma-next/utils": "0.5.0-dev.71",
23
+ "@prisma-next/target-mongo": "0.5.0-dev.71"
23
24
  },
24
25
  "devDependencies": {
25
- "tsdown": "0.18.4",
26
+ "tsdown": "0.22.0",
26
27
  "typescript": "5.9.3",
27
- "vitest": "4.0.17",
28
- "@prisma-next/mongo-contract-ts": "0.5.0-dev.7",
28
+ "vitest": "4.1.5",
29
29
  "@prisma-next/tsconfig": "0.0.0",
30
+ "@prisma-next/mongo-contract-ts": "0.5.0-dev.71",
30
31
  "@prisma-next/tsdown": "0.0.0"
31
32
  },
32
33
  "files": [
@@ -6,12 +6,16 @@ import type {
6
6
  ControlFamilyInstance,
7
7
  ControlStack,
8
8
  CoreSchemaView,
9
+ MigrationPlanOperation,
10
+ OperationPreview,
11
+ OperationPreviewCapable,
9
12
  SchemaViewCapable,
10
13
  SignDatabaseResult,
11
14
  VerifyDatabaseResult,
12
15
  VerifyDatabaseSchemaResult,
13
16
  } from '@prisma-next/framework-components/control';
14
17
  import {
18
+ APP_SPACE_ID,
15
19
  VERIFY_CODE_HASH_MISMATCH,
16
20
  VERIFY_CODE_MARKER_MISSING,
17
21
  VERIFY_CODE_TARGET_MISMATCH,
@@ -19,7 +23,12 @@ import {
19
23
  import type { MongoContract } from '@prisma-next/mongo-contract';
20
24
  import { validateMongoContract } from '@prisma-next/mongo-contract';
21
25
  import type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';
22
- import { initMarker, readMarker, updateMarker } from '@prisma-next/target-mongo/control';
26
+ import {
27
+ formatMongoOperations,
28
+ initMarker,
29
+ readMarker,
30
+ updateMarker,
31
+ } from '@prisma-next/target-mongo/control';
23
32
  import { verifyMongoSchema } from '@prisma-next/target-mongo/schema-verify';
24
33
  import { ifDefined } from '@prisma-next/utils/defined';
25
34
  import type { Db } from 'mongodb';
@@ -27,7 +36,8 @@ import { mongoSchemaToView } from './schema-to-view';
27
36
 
28
37
  export interface MongoControlFamilyInstance
29
38
  extends ControlFamilyInstance<'mongo', MongoSchemaIR>,
30
- SchemaViewCapable<MongoSchemaIR> {
39
+ SchemaViewCapable<MongoSchemaIR>,
40
+ OperationPreviewCapable {
31
41
  validateContract(contractJson: unknown): Contract;
32
42
  }
33
43
 
@@ -160,6 +170,21 @@ class MongoFamilyInstance implements MongoControlFamilyInstance {
160
170
  });
161
171
  }
162
172
 
173
+ schemaVerifyAgainstSchema(options: {
174
+ readonly contract: unknown;
175
+ readonly schema: MongoSchemaIR;
176
+ readonly strict: boolean;
177
+ readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'mongo', string>>;
178
+ }): VerifyDatabaseSchemaResult {
179
+ const validated = validateMongoContract<MongoContract>(options.contract);
180
+ return verifyMongoSchema({
181
+ contract: validated.contract,
182
+ schema: options.schema,
183
+ strict: options.strict,
184
+ frameworkComponents: options.frameworkComponents,
185
+ });
186
+ }
187
+
163
188
  async sign(options: {
164
189
  readonly driver: ControlDriverInstance<'mongo', string>;
165
190
  readonly contract: unknown;
@@ -246,11 +271,32 @@ class MongoFamilyInstance implements MongoControlFamilyInstance {
246
271
 
247
272
  async readMarker(options: {
248
273
  readonly driver: ControlDriverInstance<'mongo', string>;
274
+ readonly space: string;
249
275
  }): Promise<ContractMarkerRecord | null> {
276
+ if (options.space !== APP_SPACE_ID) {
277
+ throw new Error(
278
+ 'Mongo target does not yet support per-space contract markers. ' +
279
+ `readMarker was called with space="${options.space}", but only "${APP_SPACE_ID}" is supported. ` +
280
+ 'Per-space marker support is tracked separately for Mongo and is not part of the SQL-family contract-spaces work.',
281
+ );
282
+ }
250
283
  const db = extractDb(options.driver);
251
284
  return readMarker(db);
252
285
  }
253
286
 
287
+ // Mongo does not yet participate in the per-space mechanism — the
288
+ // `space` column was introduced in the SQL family's marker only.
289
+ // The bridge: surface the single app marker keyed by APP_SPACE_ID so
290
+ // the per-space verifier sees a coherent input shape; per-space mongo
291
+ // support is a future extension.
292
+ async readAllMarkers(options: {
293
+ readonly driver: ControlDriverInstance<'mongo', string>;
294
+ }): Promise<ReadonlyMap<string, ContractMarkerRecord>> {
295
+ const appMarker = await this.readMarker({ ...options, space: APP_SPACE_ID });
296
+ if (appMarker === null) return new Map();
297
+ return new Map([[APP_SPACE_ID, appMarker]]);
298
+ }
299
+
254
300
  async introspect(options: {
255
301
  readonly driver: ControlDriverInstance<'mongo', string>;
256
302
  readonly contract?: unknown;
@@ -262,6 +308,15 @@ class MongoFamilyInstance implements MongoControlFamilyInstance {
262
308
  toSchemaView(schema: MongoSchemaIR): CoreSchemaView {
263
309
  return mongoSchemaToView(schema);
264
310
  }
311
+
312
+ toOperationPreview(operations: readonly MigrationPlanOperation[]): OperationPreview {
313
+ return {
314
+ statements: formatMongoOperations(operations).map((text) => ({
315
+ text,
316
+ language: 'mongodb-shell',
317
+ })),
318
+ };
319
+ }
265
320
  }
266
321
 
267
322
  function buildVerifyResult(opts: {
@@ -23,7 +23,7 @@ import type { MongoControlFamilyInstance } from './control-instance';
23
23
  * itself back to such a file; `MongoMigrationPlanner.emptyMigration()`
24
24
  * returns the same shape for `migration new`. Users run the scaffolded
25
25
  * `migration.ts` directly (via `node migration.ts`) to self-emit
26
- * `ops.json` and attest the `migrationId`.
26
+ * `ops.json` and attest the `migrationHash`.
27
27
  */
28
28
  export const mongoTargetDescriptor: MigratableTargetDescriptor<
29
29
  'mongo',