@prisma-next/family-mongo 0.12.0-dev.3 → 0.12.0-dev.31

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,6 +1,6 @@
1
1
  import { MongoSchemaIR } from "@prisma-next/mongo-schema-ir";
2
2
  import { ControlAdapterDescriptor, ControlAdapterInstance, ControlDriverInstance } from "@prisma-next/framework-components/control";
3
- import { ContractMarkerRecord } from "@prisma-next/contract/types";
3
+ import { ContractMarkerRecord, LedgerEntryRecord } from "@prisma-next/contract/types";
4
4
 
5
5
  //#region src/core/control-adapter.d.ts
6
6
  /**
@@ -58,7 +58,15 @@ interface MongoControlAdapter<TTarget extends string = string> extends ControlAd
58
58
  readonly edgeId: string;
59
59
  readonly from: string;
60
60
  readonly to: string;
61
+ readonly migrationName: string;
62
+ readonly migrationHash: string;
63
+ readonly operations: readonly unknown[];
61
64
  }): Promise<void>;
65
+ /**
66
+ * Reads the per-migration ledger journal in apply order. When `space` is
67
+ * omitted, returns rows for every space.
68
+ */
69
+ readLedger(driver: ControlDriverInstance<'mongo', TTarget>, space?: string): Promise<readonly LedgerEntryRecord[]>;
62
70
  /**
63
71
  * Introspects the live database and returns a `MongoSchemaIR`.
64
72
  */
@@ -1 +1 @@
1
- {"version":3,"file":"control-adapter.d.mts","names":[],"sources":["../src/core/control-adapter.ts"],"mappings":";;;;;;;AAqBA;;;;;;;;;;;UAAiB,mBAAA,0CACP,sBAAA,UAAgC,OAAA;EAoBrC;;;;;;EAbH,UAAA,CACE,MAAA,EAAQ,qBAAA,UAA+B,OAAA,GACvC,KAAA,WACC,OAAA,CAAQ,oBAAA;EA+C8B;;;;;;EAvCzC,cAAA,CACE,MAAA,EAAQ,qBAAA,UAA+B,OAAA,IACtC,OAAA,CAAQ,WAAA,SAAoB,oBAAA;EApBvB;;;EAyBR,UAAA,CACE,MAAA,EAAQ,qBAAA,UAA+B,OAAA,GACvC,KAAA,UACA,WAAA;IAAA,SACW,WAAA;IAAA,SACA,WAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EAzBsC;;;;;EAgCzC,YAAA,CACE,MAAA,EAAQ,qBAAA,UAA+B,OAAA,GACvC,KAAA,UACA,YAAA,UACA,WAAA;IAAA,SACW,WAAA;IAAA,SACA,WAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EA7BQ;;;;;EAoCX,gBAAA,CACE,MAAA,EAAQ,qBAAA,UAA+B,OAAA,GACvC,KAAA,UACA,KAAA;IAAA,SAAkB,MAAA;IAAA,SAAyB,IAAA;IAAA,SAAuB,EAAA;EAAA,IACjE,OAAA;EAhCD;;;EAqCF,gBAAA,CAAiB,MAAA,EAAQ,qBAAA,UAA+B,OAAA,IAAW,OAAA,CAAQ,aAAA;AAAA;;;;;;UAQ5D,6BAAA,0CACP,wBAAA,UAAkC,OAAA,EAAS,mBAAA,CAAoB,OAAA"}
1
+ {"version":3,"file":"control-adapter.d.mts","names":[],"sources":["../src/core/control-adapter.ts"],"mappings":";;;;;;;AAqBA;;;;;;;;;;;UAAiB,mBAAA,0CACP,sBAAA,UAAgC,OAAA;EAoBrC;;;;;;EAbH,UAAA,CACE,MAAA,EAAQ,qBAAA,UAA+B,OAAA,GACvC,KAAA,WACC,OAAA,CAAQ,oBAAA;EA+C8B;;;;;;EAvCzC,cAAA,CACE,MAAA,EAAQ,qBAAA,UAA+B,OAAA,IACtC,OAAA,CAAQ,WAAA,SAAoB,oBAAA;EA6DyB;;;EAxDxD,UAAA,CACE,MAAA,EAAQ,qBAAA,UAA+B,OAAA,GACvC,KAAA,UACA,WAAA;IAAA,SACW,WAAA;IAAA,SACA,WAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EAjCK;;;;;EAwCR,YAAA,CACE,MAAA,EAAQ,qBAAA,UAA+B,OAAA,GACvC,KAAA,UACA,YAAA,UACA,WAAA;IAAA,SACW,WAAA;IAAA,SACA,WAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EA9BO;;;;;EAqCV,gBAAA,CACE,MAAA,EAAQ,qBAAA,UAA+B,OAAA,GACvC,KAAA,UACA,KAAA;IAAA,SACW,MAAA;IAAA,SACA,IAAA;IAAA,SACA,EAAA;IAAA,SACA,aAAA;IAAA,SACA,aAAA;IAAA,SACA,UAAA;EAAA,IAEV,OAAA;EApCU;;;;EA0Cb,UAAA,CACE,MAAA,EAAQ,qBAAA,UAA+B,OAAA,GACvC,KAAA,YACC,OAAA,UAAiB,iBAAA;EAnCqB;;;EAwCzC,gBAAA,CAAiB,MAAA,EAAQ,qBAAA,UAA+B,OAAA,IAAW,OAAA,CAAQ,aAAA;AAAA;;;;;;UAQ5D,6BAAA,0CACP,wBAAA,UAAkC,OAAA,EAAS,mBAAA,CAAoB,OAAA"}
@@ -1,7 +1,7 @@
1
1
  import { MongoSchemaIR } from "@prisma-next/mongo-schema-ir";
2
2
  import { ContractSerializer, ContractSpace, ControlExtensionDescriptor, ControlFamilyDescriptor, ControlFamilyInstance, ControlStack, MigratableTargetDescriptor, MigrationPlanOperation, OperationPreview, OperationPreviewCapable, SchemaIssue, SchemaVerificationNode, SchemaVerifier, SchemaViewCapable } from "@prisma-next/framework-components/control";
3
3
  import { MongoContract, MongoStorageShape } from "@prisma-next/mongo-contract";
4
- import { Contract } from "@prisma-next/contract/types";
4
+ import { Contract, ControlPolicy } from "@prisma-next/contract/types";
5
5
 
6
6
  //#region src/core/contract-to-schema.d.ts
7
7
  declare function contractToMongoSchemaIR(contract: MongoContract | null): MongoSchemaIR;
@@ -73,7 +73,7 @@ declare function formatMongoOperations(operations: readonly MigrationPlanOperati
73
73
  declare function mongoOperationsToPreview(operations: readonly MigrationPlanOperation[]): OperationPreview;
74
74
  //#endregion
75
75
  //#region src/core/schema-diff.d.ts
76
- declare function diffMongoSchemas(live: MongoSchemaIR, expected: MongoSchemaIR, strict: boolean): {
76
+ declare function diffMongoSchemas(live: MongoSchemaIR, expected: MongoSchemaIR, strict: boolean, collectionControlPolicy: (collectionName: string) => ControlPolicy): {
77
77
  root: SchemaVerificationNode;
78
78
  issues: SchemaIssue[];
79
79
  counts: {
@@ -1 +1 @@
1
- {"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/contract-to-schema.ts","../src/core/control-instance.ts","../src/core/control-descriptor.ts","../src/core/control-target-descriptor.ts","../src/core/control-types.ts","../src/core/operation-preview.ts","../src/core/schema-diff.ts","../src/core/schema-verify/canonicalize-introspection.ts"],"mappings":";;;;;;iBAyEgB,uBAAA,CAAwB,QAAA,EAAU,aAAA,UAAuB,aAAa;;;UCxCrE,0BAAA,SACP,qBAAA,UAA+B,aAAA,GACrC,iBAAA,CAAkB,aAAA,GAClB,uBAAA;;;ADqCJ;;;;;;;;EC1BE,mBAAA,CAAoB,YAAA,YAAwB,QAAA;AAAA;AAAA,iBAmF9B,yBAAA,CAA0B,YAAA,EAAc,YAAA,GAAe,0BAA0B;;;cC3GpF,qBAAA,EAAuB,uBAAuB,UAAU,0BAAA;;;;;AFkDrE;;;;;;;;AAAsF;;UGpDrE,4BAAA,mBAA+C,aAAA,GAAgB,aAAA,UACtE,0BAAA,mBAA6C,0BAAA;EAAA,SAC5C,kBAAA,EAAoB,kBAAA,CAAmB,SAAA;EAAA,SACvC,cAAA,EAAgB,cAAA,CAAe,SAAA,EAAW,aAAA;AAAA;;;;;;;AHiDrD;;;;;;;;AAAsF;;;UIpDrE,+BAAA,SACP,0BAAA;EAAA,SACC,aAAA,GAAgB,aAAA,CAAc,aAAA,CAAc,iBAAA;AAAA;;;iBC6EvC,qBAAA,CAAsB,UAA6C,WAAxB,sBAAsB;;;;;AL3BjF;iBKgDgB,wBAAA,CACd,UAAA,WAAqB,sBAAA,KACpB,gBAAgB;;;iBC/GH,gBAAA,CACd,IAAA,EAAM,aAAA,EACN,QAAA,EAAU,aAAA,EACV,MAAA;EAEA,IAAA,EAAM,sBAAA;EACN,MAAA,EAAQ,WAAA;EACR,MAAA;IAAU,IAAA;IAAc,IAAA;IAAc,IAAA;IAAc,UAAA;EAAA;AAAA;;;UCWrC,oBAAA;EAAA,SACN,IAAA,EAAM,aAAA;EAAA,SACN,QAAA,EAAU,aAAa;AAAA;AAAA,iBAGlB,kCAAA,CACd,IAAA,EAAM,aAAA,EACN,QAAA,EAAU,aAAA,GACT,oBAAA"}
1
+ {"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/contract-to-schema.ts","../src/core/control-instance.ts","../src/core/control-descriptor.ts","../src/core/control-target-descriptor.ts","../src/core/control-types.ts","../src/core/operation-preview.ts","../src/core/schema-diff.ts","../src/core/schema-verify/canonicalize-introspection.ts"],"mappings":";;;;;;iBAyEgB,uBAAA,CAAwB,QAAA,EAAU,aAAA,UAAuB,aAAa;;;UCpCrE,0BAAA,SACP,qBAAA,UAA+B,aAAA,GACrC,iBAAA,CAAkB,aAAA,GAClB,uBAAA;;;ADiCJ;;;;;;;;ECtBE,mBAAA,CAAoB,YAAA,YAAwB,QAAA;AAAA;AAAA,iBAsE9B,yBAAA,CAA0B,YAAA,EAAc,YAAA,GAAe,0BAA0B;;;cClGpF,qBAAA,EAAuB,uBAAuB,UAAU,0BAAA;;;;;AFkDrE;;;;;;;;AAAsF;;UGpDrE,4BAAA,mBAA+C,aAAA,GAAgB,aAAA,UACtE,0BAAA,mBAA6C,0BAAA;EAAA,SAC5C,kBAAA,EAAoB,kBAAA,CAAmB,SAAA;EAAA,SACvC,cAAA,EAAgB,cAAA,CAAe,SAAA,EAAW,aAAA;AAAA;;;;;;;AHiDrD;;;;;;;;AAAsF;;;UIpDrE,+BAAA,SACP,0BAAA;EAAA,SACC,aAAA,GAAgB,aAAA,CAAc,aAAA,CAAc,iBAAA;AAAA;;;iBC6EvC,qBAAA,CAAsB,UAA6C,WAAxB,sBAAsB;;;;;AL3BjF;iBKgDgB,wBAAA,CACd,UAAA,WAAqB,sBAAA,KACpB,gBAAgB;;;iBC7GH,gBAAA,CACd,IAAA,EAAM,aAAA,EACN,QAAA,EAAU,aAAA,EACV,MAAA,WACA,uBAAA,GAA0B,cAAA,aAA2B,aAAA;EAErD,IAAA,EAAM,sBAAA;EACN,MAAA,EAAQ,WAAA;EACR,MAAA;IAAU,IAAA;IAAc,IAAA;IAAc,IAAA;IAAc,UAAA;EAAA;AAAA;;;UCQrC,oBAAA;EAAA,SACN,IAAA,EAAM,aAAA;EAAA,SACN,QAAA,EAAU,aAAa;AAAA;AAAA,iBAGlB,kCAAA,CACd,IAAA,EAAM,aAAA,EACN,QAAA,EAAU,aAAA,GACT,oBAAA"}
package/dist/control.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { i as contractToMongoSchemaIR, n as canonicalizeSchemasForVerification, r as diffMongoSchemas, t as verifyMongoSchema } from "./verify-mongo-schema-Bhxvdah3.mjs";
1
+ import { i as contractToMongoSchemaIR, n as canonicalizeSchemasForVerification, r as diffMongoSchemas, t as verifyMongoSchema } from "./verify-mongo-schema-CFRMURgz.mjs";
2
2
  import { t as MongoContractSerializer } from "./mongo-contract-serializer-DAoKJxiP.mjs";
3
3
  import { mongoEmission } from "@prisma-next/mongo-emitter";
4
4
  import { APP_SPACE_ID, SchemaTreeNode, VERIFY_CODE_HASH_MISMATCH, VERIFY_CODE_MARKER_MISSING, VERIFY_CODE_TARGET_MISMATCH } from "@prisma-next/framework-components/control";
@@ -199,9 +199,6 @@ function deserializeMongoContract(contractJson) {
199
199
  function asValidatedMongoContract(contract) {
200
200
  return contract;
201
201
  }
202
- function isMongoControlAdapter(value) {
203
- return typeof value === "object" && value !== null && "readMarker" in value && typeof value.readMarker === "function" && "readAllMarkers" in value && typeof value.readAllMarkers === "function" && "introspectSchema" in value && typeof value.introspectSchema === "function";
204
- }
205
202
  function buildVerifyResult(opts) {
206
203
  return {
207
204
  ok: opts.ok,
@@ -242,9 +239,7 @@ function createMongoFamilyInstance(controlStack) {
242
239
  const adapter = controlStack.adapter;
243
240
  const getControlAdapter = () => {
244
241
  if (!adapter) throw new Error("Mongo family requires an adapter descriptor in ControlStack");
245
- const controlAdapter = adapter.create(controlStack);
246
- if (!isMongoControlAdapter(controlAdapter)) throw new Error("Adapter does not implement MongoControlAdapter (missing readMarker, readAllMarkers, or introspectSchema)");
247
- return controlAdapter;
242
+ return adapter.create(controlStack);
248
243
  };
249
244
  const asMongoDriver = (driver) => driver;
250
245
  return {
@@ -380,6 +375,9 @@ function createMongoFamilyInstance(controlStack) {
380
375
  async readAllMarkers(options) {
381
376
  return getControlAdapter().readAllMarkers(asMongoDriver(options.driver));
382
377
  },
378
+ async readLedger(options) {
379
+ return getControlAdapter().readLedger(asMongoDriver(options.driver), options.space);
380
+ },
383
381
  async introspect(options) {
384
382
  return getControlAdapter().introspectSchema(asMongoDriver(options.driver));
385
383
  },
@@ -1 +1 @@
1
- {"version":3,"file":"control.mjs","names":[],"sources":["../src/core/operation-preview.ts","../src/core/schema-to-view.ts","../src/core/control-instance.ts","../src/core/control-descriptor.ts"],"sourcesContent":["import type {\n MigrationPlanOperation,\n OperationPreview,\n} from '@prisma-next/framework-components/control';\nimport type {\n CollModCommand,\n CreateCollectionCommand,\n CreateIndexCommand,\n DropCollectionCommand,\n DropIndexCommand,\n MongoDdlCommandVisitor,\n MongoIndexKey,\n} from '@prisma-next/mongo-query-ast/control';\n\nfunction formatKeySpec(keys: ReadonlyArray<MongoIndexKey>): string {\n const entries = keys.map((k) => `${JSON.stringify(k.field)}: ${JSON.stringify(k.direction)}`);\n return `{ ${entries.join(', ')} }`;\n}\n\nfunction formatOptions(cmd: CreateIndexCommand): string | undefined {\n const parts: string[] = [];\n if (cmd.unique) parts.push('unique: true');\n if (cmd.sparse) parts.push('sparse: true');\n if (cmd.expireAfterSeconds !== undefined)\n parts.push(`expireAfterSeconds: ${cmd.expireAfterSeconds}`);\n if (cmd.name) parts.push(`name: ${JSON.stringify(cmd.name)}`);\n if (cmd.collation) parts.push(`collation: ${JSON.stringify(cmd.collation)}`);\n if (cmd.weights) parts.push(`weights: ${JSON.stringify(cmd.weights)}`);\n if (cmd.default_language) parts.push(`default_language: ${JSON.stringify(cmd.default_language)}`);\n if (cmd.language_override)\n parts.push(`language_override: ${JSON.stringify(cmd.language_override)}`);\n if (cmd.wildcardProjection)\n parts.push(`wildcardProjection: ${JSON.stringify(cmd.wildcardProjection)}`);\n if (cmd.partialFilterExpression)\n parts.push(`partialFilterExpression: ${JSON.stringify(cmd.partialFilterExpression)}`);\n if (parts.length === 0) return undefined;\n return `{ ${parts.join(', ')} }`;\n}\n\nfunction formatCreateCollectionOptions(cmd: CreateCollectionCommand): string | undefined {\n const parts: string[] = [];\n if (cmd.capped) parts.push('capped: true');\n if (cmd.size !== undefined) parts.push(`size: ${cmd.size}`);\n if (cmd.max !== undefined) parts.push(`max: ${cmd.max}`);\n if (cmd.timeseries) parts.push(`timeseries: ${JSON.stringify(cmd.timeseries)}`);\n if (cmd.collation) parts.push(`collation: ${JSON.stringify(cmd.collation)}`);\n if (cmd.clusteredIndex) parts.push(`clusteredIndex: ${JSON.stringify(cmd.clusteredIndex)}`);\n if (cmd.validator) parts.push(`validator: ${JSON.stringify(cmd.validator)}`);\n if (cmd.validationLevel) parts.push(`validationLevel: ${JSON.stringify(cmd.validationLevel)}`);\n if (cmd.validationAction) parts.push(`validationAction: ${JSON.stringify(cmd.validationAction)}`);\n if (cmd.changeStreamPreAndPostImages)\n parts.push(`changeStreamPreAndPostImages: ${JSON.stringify(cmd.changeStreamPreAndPostImages)}`);\n if (parts.length === 0) return undefined;\n return `{ ${parts.join(', ')} }`;\n}\n\nclass MongoDdlCommandFormatter implements MongoDdlCommandVisitor<string> {\n createIndex(cmd: CreateIndexCommand): string {\n const keySpec = formatKeySpec(cmd.keys);\n const opts = formatOptions(cmd);\n return opts\n ? `db.${cmd.collection}.createIndex(${keySpec}, ${opts})`\n : `db.${cmd.collection}.createIndex(${keySpec})`;\n }\n\n dropIndex(cmd: DropIndexCommand): string {\n return `db.${cmd.collection}.dropIndex(${JSON.stringify(cmd.name)})`;\n }\n\n createCollection(cmd: CreateCollectionCommand): string {\n const opts = formatCreateCollectionOptions(cmd);\n return opts\n ? `db.createCollection(${JSON.stringify(cmd.collection)}, ${opts})`\n : `db.createCollection(${JSON.stringify(cmd.collection)})`;\n }\n\n dropCollection(cmd: DropCollectionCommand): string {\n return `db.${cmd.collection}.drop()`;\n }\n\n collMod(cmd: CollModCommand): string {\n const parts: string[] = [`collMod: ${JSON.stringify(cmd.collection)}`];\n if (cmd.validator) parts.push(`validator: ${JSON.stringify(cmd.validator)}`);\n if (cmd.validationLevel) parts.push(`validationLevel: ${JSON.stringify(cmd.validationLevel)}`);\n if (cmd.validationAction)\n parts.push(`validationAction: ${JSON.stringify(cmd.validationAction)}`);\n if (cmd.changeStreamPreAndPostImages)\n parts.push(\n `changeStreamPreAndPostImages: ${JSON.stringify(cmd.changeStreamPreAndPostImages)}`,\n );\n return `db.runCommand({ ${parts.join(', ')} })`;\n }\n}\n\nconst formatter = new MongoDdlCommandFormatter();\n\ninterface MongoExecuteStep {\n readonly command: { readonly accept: <R>(visitor: MongoDdlCommandVisitor<R>) => R };\n}\n\nexport function formatMongoOperations(operations: readonly MigrationPlanOperation[]): string[] {\n const statements: string[] = [];\n for (const operation of operations) {\n const candidate = operation as unknown as Record<string, unknown>;\n if (!('execute' in candidate) || !Array.isArray(candidate['execute'])) {\n continue;\n }\n for (const step of candidate['execute'] as MongoExecuteStep[]) {\n if (step.command && typeof step.command.accept === 'function') {\n statements.push(step.command.accept(formatter));\n }\n }\n }\n return statements;\n}\n\n/**\n * Wraps `formatMongoOperations` into the family-agnostic\n * `OperationPreview` shape. Each statement carries\n * `language: 'mongodb-shell'`. Mirrors `sqlOperationsToPreview`.\n */\nexport function mongoOperationsToPreview(\n operations: readonly MigrationPlanOperation[],\n): OperationPreview {\n return {\n statements: formatMongoOperations(operations).map((text) => ({\n text,\n language: 'mongodb-shell',\n })),\n };\n}\n","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 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 { assertDescriptorSelfConsistency } from '@prisma-next/migration-tools/spaces';\nimport type { MongoContract } from '@prisma-next/mongo-contract';\nimport { mongoContractCanonicalizationHooks } from '@prisma-next/mongo-contract/canonicalization-hooks';\nimport type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { MongoControlAdapter, MongoControlAdapterDescriptor } from './control-adapter';\nimport type { MongoControlExtensionDescriptor } from './control-types';\nimport { MongoContractSerializer } from './ir/mongo-contract-serializer';\nimport { mongoOperationsToPreview } from './operation-preview';\nimport { mongoSchemaToView } from './schema-to-view';\nimport { verifyMongoSchema } from './schema-verify/verify-mongo-schema';\n\nexport interface MongoControlFamilyInstance\n extends ControlFamilyInstance<'mongo', MongoSchemaIR>,\n SchemaViewCapable<MongoSchemaIR>,\n OperationPreviewCapable {\n /**\n * The family seam-of-record for on-disk contract reads. Structurally\n * validates the JSON envelope, then casts to the framework `Contract`\n * shape; the per-target serializer (held on the Mongo target\n * descriptor) does the class-form wrap for downstream consumers, so\n * the family only needs the validated data. The single named entry\n * point every CLI on-disk read crosses (TML-2536) — `as Contract`\n * casts in production package sources are a serializer-bypass smell\n * guarded by `pnpm lint:no-contract-cast`.\n */\n deserializeContract(contractJson: unknown): Contract;\n}\n\nfunction deserializeMongoContract(contractJson: unknown): MongoContract {\n // Structural validation only — the per-target serializer wraps the\n // result in a class-form `MongoTargetContract` for downstream\n // consumers (CLI, runner). The family-instance methods only read\n // hash/target fields off the validated shape, so the unwrapped\n // `MongoContract` is sufficient here and avoids a family→target\n // runtime dep.\n return new MongoContractSerializer().deserializeContract(contractJson);\n}\n\n/**\n * Family-method contract input. By the time control-plane methods\n * (`verify`, `verifySchema`, `sign`, …) are invoked through the CLI\n * control client (`client.ts`), the input has already been threaded\n * through `familyInstance.deserializeContract`. The value is therefore a\n * class-form `MongoTargetContract` (or a structurally-equivalent\n * envelope post-deserialization) and must NOT be re-fed through\n * structural validation (arktype rejects extra keys like `namespaces`).\n *\n * The parameter type on the framework SPI is `unknown` for variance\n * reasons (so the family can express its own contract type without\n * leaking it to the framework). This helper recovers the validated\n * shape with a single narrow cast.\n */\nfunction asValidatedMongoContract(contract: unknown): MongoContract {\n return contract as MongoContract;\n}\n\nfunction isMongoControlAdapter(value: unknown): value is MongoControlAdapter<'mongo'> {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'readMarker' in value &&\n typeof (value as { readMarker: unknown }).readMarker === 'function' &&\n 'readAllMarkers' in value &&\n typeof (value as { readAllMarkers: unknown }).readAllMarkers === 'function' &&\n 'introspectSchema' in value &&\n typeof (value as { introspectSchema: unknown }).introspectSchema === 'function'\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 // Descriptor self-consistency check.\n // Each extension that exposes a `contractSpace` must publish a\n // `headRef.hash` that matches the canonical hash recomputed from its\n // `contractJson`. A stale value would silently corrupt every downstream\n // boundary that trusts `headRef.hash` as the canonical identity (drift\n // detection, on-disk artefact emission, runner marker writes). Failing\n // fast at descriptor-load time turns \"extension author shipped an\n // inconsistent descriptor\" into an explicit, actionable error\n // (`MIGRATION.DESCRIPTOR_HEAD_HASH_MISMATCH`) rather than a confusing\n // mismatch surfacing several layers downstream. Mirrors the SQL family.\n const extensions = (controlStack.extensionPacks ??\n []) as readonly MongoControlExtensionDescriptor[];\n for (const extension of extensions) {\n if (extension.contractSpace) {\n const { contractJson, headRef } = extension.contractSpace;\n assertDescriptorSelfConsistency({\n extensionId: extension.id,\n target: contractJson.target,\n targetFamily: contractJson.targetFamily,\n storage: contractJson.storage,\n headRefHash: headRef.hash,\n ...mongoContractCanonicalizationHooks,\n });\n }\n }\n\n // Mongo dispatch surface. Every wire-level operation routes through\n // the adapter resolved from the control stack; the family carries no\n // direct imports of target/adapter/driver internals. Mirrors the SQL\n // family's `getControlAdapter()` helper.\n const adapter = controlStack.adapter as MongoControlAdapterDescriptor<'mongo'> | undefined;\n const getControlAdapter = (): MongoControlAdapter<'mongo'> => {\n if (!adapter) {\n throw new Error('Mongo family requires an adapter descriptor in ControlStack');\n }\n const controlAdapter = adapter.create(controlStack as ControlStack<'mongo', 'mongo'>);\n if (!isMongoControlAdapter(controlAdapter)) {\n throw new Error(\n 'Adapter does not implement MongoControlAdapter (missing readMarker, readAllMarkers, or introspectSchema)',\n );\n }\n return controlAdapter;\n };\n\n // The family-level driver type is `ControlDriverInstance<'mongo', string>`,\n // but the SPI methods are typed against `<'mongo', 'mongo'>`. Today's only\n // Mongo target is `'mongo'`, so the runtime values are identical; the cast\n // satisfies the structural type-system mismatch on `targetId`.\n const asMongoDriver = (\n driver: ControlDriverInstance<'mongo', string>,\n ): ControlDriverInstance<'mongo', 'mongo'> => driver as ControlDriverInstance<'mongo', 'mongo'>;\n\n return {\n familyId: 'mongo' as const,\n\n deserializeContract(contractJson: unknown): Contract {\n // The deserialized class form (MongoTargetContract, owned by\n // target-mongo) and the framework Contract are structurally\n // compatible — same fields, just a class instance on the storage\n // envelope. The cast preserves the framework signature.\n return deserializeMongoContract(contractJson) as unknown as Contract;\n },\n\n async verify(options): Promise<VerifyDatabaseResult> {\n const { driver, contract: rawContract, expectedTargetId, contractPath, configPath } = options;\n const startTime = Date.now();\n\n const contract = asValidatedMongoContract(rawContract);\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 marker = await getControlAdapter().readMarker(asMongoDriver(driver), APP_SPACE_ID);\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 verifySchema(options: {\n readonly contract: unknown;\n readonly schema: MongoSchemaIR;\n readonly strict: boolean;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'mongo', string>>;\n }): VerifyDatabaseSchemaResult {\n const contract = asValidatedMongoContract(options.contract);\n return verifyMongoSchema({\n contract,\n schema: options.schema,\n strict: options.strict,\n frameworkComponents: options.frameworkComponents,\n });\n },\n\n async sign(options): Promise<SignDatabaseResult> {\n const { driver, contract: rawContract, contractPath, configPath } = options;\n const startTime = Date.now();\n\n const contract = asValidatedMongoContract(rawContract);\n\n const contractStorageHash = contract.storage.storageHash;\n const contractProfileHash = contract.profileHash;\n\n const controlAdapter = getControlAdapter();\n const mongoDriver = asMongoDriver(driver);\n\n const existingMarker = await controlAdapter.readMarker(mongoDriver, APP_SPACE_ID);\n\n let markerCreated = false;\n let markerUpdated = false;\n let previousHashes: { storageHash?: string; profileHash?: string } | undefined;\n\n if (!existingMarker) {\n await controlAdapter.initMarker(mongoDriver, APP_SPACE_ID, {\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 controlAdapter.updateMarker(\n mongoDriver,\n APP_SPACE_ID,\n existingMarker.storageHash,\n {\n storageHash: contractStorageHash,\n profileHash: contractProfileHash,\n },\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): Promise<ContractMarkerRecord | null> {\n return getControlAdapter().readMarker(asMongoDriver(options.driver), options.space);\n },\n\n async readAllMarkers(options): Promise<ReadonlyMap<string, ContractMarkerRecord>> {\n return getControlAdapter().readAllMarkers(asMongoDriver(options.driver));\n },\n\n async introspect(options): Promise<MongoSchemaIR> {\n return getControlAdapter().introspectSchema(asMongoDriver(options.driver));\n },\n\n toSchemaView(schema: MongoSchemaIR): CoreSchemaView {\n return mongoSchemaToView(schema);\n },\n\n toOperationPreview(operations: readonly MigrationPlanOperation[]): OperationPreview {\n return mongoOperationsToPreview(operations);\n },\n };\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"],"mappings":"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"}
1
+ {"version":3,"file":"control.mjs","names":[],"sources":["../src/core/operation-preview.ts","../src/core/schema-to-view.ts","../src/core/control-instance.ts","../src/core/control-descriptor.ts"],"sourcesContent":["import type {\n MigrationPlanOperation,\n OperationPreview,\n} from '@prisma-next/framework-components/control';\nimport type {\n CollModCommand,\n CreateCollectionCommand,\n CreateIndexCommand,\n DropCollectionCommand,\n DropIndexCommand,\n MongoDdlCommandVisitor,\n MongoIndexKey,\n} from '@prisma-next/mongo-query-ast/control';\n\nfunction formatKeySpec(keys: ReadonlyArray<MongoIndexKey>): string {\n const entries = keys.map((k) => `${JSON.stringify(k.field)}: ${JSON.stringify(k.direction)}`);\n return `{ ${entries.join(', ')} }`;\n}\n\nfunction formatOptions(cmd: CreateIndexCommand): string | undefined {\n const parts: string[] = [];\n if (cmd.unique) parts.push('unique: true');\n if (cmd.sparse) parts.push('sparse: true');\n if (cmd.expireAfterSeconds !== undefined)\n parts.push(`expireAfterSeconds: ${cmd.expireAfterSeconds}`);\n if (cmd.name) parts.push(`name: ${JSON.stringify(cmd.name)}`);\n if (cmd.collation) parts.push(`collation: ${JSON.stringify(cmd.collation)}`);\n if (cmd.weights) parts.push(`weights: ${JSON.stringify(cmd.weights)}`);\n if (cmd.default_language) parts.push(`default_language: ${JSON.stringify(cmd.default_language)}`);\n if (cmd.language_override)\n parts.push(`language_override: ${JSON.stringify(cmd.language_override)}`);\n if (cmd.wildcardProjection)\n parts.push(`wildcardProjection: ${JSON.stringify(cmd.wildcardProjection)}`);\n if (cmd.partialFilterExpression)\n parts.push(`partialFilterExpression: ${JSON.stringify(cmd.partialFilterExpression)}`);\n if (parts.length === 0) return undefined;\n return `{ ${parts.join(', ')} }`;\n}\n\nfunction formatCreateCollectionOptions(cmd: CreateCollectionCommand): string | undefined {\n const parts: string[] = [];\n if (cmd.capped) parts.push('capped: true');\n if (cmd.size !== undefined) parts.push(`size: ${cmd.size}`);\n if (cmd.max !== undefined) parts.push(`max: ${cmd.max}`);\n if (cmd.timeseries) parts.push(`timeseries: ${JSON.stringify(cmd.timeseries)}`);\n if (cmd.collation) parts.push(`collation: ${JSON.stringify(cmd.collation)}`);\n if (cmd.clusteredIndex) parts.push(`clusteredIndex: ${JSON.stringify(cmd.clusteredIndex)}`);\n if (cmd.validator) parts.push(`validator: ${JSON.stringify(cmd.validator)}`);\n if (cmd.validationLevel) parts.push(`validationLevel: ${JSON.stringify(cmd.validationLevel)}`);\n if (cmd.validationAction) parts.push(`validationAction: ${JSON.stringify(cmd.validationAction)}`);\n if (cmd.changeStreamPreAndPostImages)\n parts.push(`changeStreamPreAndPostImages: ${JSON.stringify(cmd.changeStreamPreAndPostImages)}`);\n if (parts.length === 0) return undefined;\n return `{ ${parts.join(', ')} }`;\n}\n\nclass MongoDdlCommandFormatter implements MongoDdlCommandVisitor<string> {\n createIndex(cmd: CreateIndexCommand): string {\n const keySpec = formatKeySpec(cmd.keys);\n const opts = formatOptions(cmd);\n return opts\n ? `db.${cmd.collection}.createIndex(${keySpec}, ${opts})`\n : `db.${cmd.collection}.createIndex(${keySpec})`;\n }\n\n dropIndex(cmd: DropIndexCommand): string {\n return `db.${cmd.collection}.dropIndex(${JSON.stringify(cmd.name)})`;\n }\n\n createCollection(cmd: CreateCollectionCommand): string {\n const opts = formatCreateCollectionOptions(cmd);\n return opts\n ? `db.createCollection(${JSON.stringify(cmd.collection)}, ${opts})`\n : `db.createCollection(${JSON.stringify(cmd.collection)})`;\n }\n\n dropCollection(cmd: DropCollectionCommand): string {\n return `db.${cmd.collection}.drop()`;\n }\n\n collMod(cmd: CollModCommand): string {\n const parts: string[] = [`collMod: ${JSON.stringify(cmd.collection)}`];\n if (cmd.validator) parts.push(`validator: ${JSON.stringify(cmd.validator)}`);\n if (cmd.validationLevel) parts.push(`validationLevel: ${JSON.stringify(cmd.validationLevel)}`);\n if (cmd.validationAction)\n parts.push(`validationAction: ${JSON.stringify(cmd.validationAction)}`);\n if (cmd.changeStreamPreAndPostImages)\n parts.push(\n `changeStreamPreAndPostImages: ${JSON.stringify(cmd.changeStreamPreAndPostImages)}`,\n );\n return `db.runCommand({ ${parts.join(', ')} })`;\n }\n}\n\nconst formatter = new MongoDdlCommandFormatter();\n\ninterface MongoExecuteStep {\n readonly command: { readonly accept: <R>(visitor: MongoDdlCommandVisitor<R>) => R };\n}\n\nexport function formatMongoOperations(operations: readonly MigrationPlanOperation[]): string[] {\n const statements: string[] = [];\n for (const operation of operations) {\n const candidate = operation as unknown as Record<string, unknown>;\n if (!('execute' in candidate) || !Array.isArray(candidate['execute'])) {\n continue;\n }\n for (const step of candidate['execute'] as MongoExecuteStep[]) {\n if (step.command && typeof step.command.accept === 'function') {\n statements.push(step.command.accept(formatter));\n }\n }\n }\n return statements;\n}\n\n/**\n * Wraps `formatMongoOperations` into the family-agnostic\n * `OperationPreview` shape. Each statement carries\n * `language: 'mongodb-shell'`. Mirrors `sqlOperationsToPreview`.\n */\nexport function mongoOperationsToPreview(\n operations: readonly MigrationPlanOperation[],\n): OperationPreview {\n return {\n statements: formatMongoOperations(operations).map((text) => ({\n text,\n language: 'mongodb-shell',\n })),\n };\n}\n","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 type {\n Contract,\n ContractMarkerRecord,\n LedgerEntryRecord,\n} 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 { assertDescriptorSelfConsistency } from '@prisma-next/migration-tools/spaces';\nimport type { MongoContract } from '@prisma-next/mongo-contract';\nimport { mongoContractCanonicalizationHooks } from '@prisma-next/mongo-contract/canonicalization-hooks';\nimport type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { MongoControlAdapter, MongoControlAdapterDescriptor } from './control-adapter';\nimport type { MongoControlExtensionDescriptor } from './control-types';\nimport { MongoContractSerializer } from './ir/mongo-contract-serializer';\nimport { mongoOperationsToPreview } from './operation-preview';\nimport { mongoSchemaToView } from './schema-to-view';\nimport { verifyMongoSchema } from './schema-verify/verify-mongo-schema';\n\nexport interface MongoControlFamilyInstance\n extends ControlFamilyInstance<'mongo', MongoSchemaIR>,\n SchemaViewCapable<MongoSchemaIR>,\n OperationPreviewCapable {\n /**\n * The family seam-of-record for on-disk contract reads. Structurally\n * validates the JSON envelope, then casts to the framework `Contract`\n * shape; the per-target serializer (held on the Mongo target\n * descriptor) does the class-form wrap for downstream consumers, so\n * the family only needs the validated data. The single named entry\n * point every CLI on-disk read crosses (TML-2536) — `as Contract`\n * casts in production package sources are a serializer-bypass smell\n * guarded by `pnpm lint:no-contract-cast`.\n */\n deserializeContract(contractJson: unknown): Contract;\n}\n\nfunction deserializeMongoContract(contractJson: unknown): MongoContract {\n // Structural validation only — the per-target serializer wraps the\n // result in a class-form `MongoTargetContract` for downstream\n // consumers (CLI, runner). The family-instance methods only read\n // hash/target fields off the validated shape, so the unwrapped\n // `MongoContract` is sufficient here and avoids a family→target\n // runtime dep.\n return new MongoContractSerializer().deserializeContract(contractJson);\n}\n\n/**\n * Family-method contract input. By the time control-plane methods\n * (`verify`, `verifySchema`, `sign`, …) are invoked through the CLI\n * control client (`client.ts`), the input has already been threaded\n * through `familyInstance.deserializeContract`. The value is therefore a\n * class-form `MongoTargetContract` (or a structurally-equivalent\n * envelope post-deserialization) and must NOT be re-fed through\n * structural validation (arktype rejects extra keys like `namespaces`).\n *\n * The parameter type on the framework SPI is `unknown` for variance\n * reasons (so the family can express its own contract type without\n * leaking it to the framework). This helper recovers the validated\n * shape with a single narrow cast.\n */\nfunction asValidatedMongoContract(contract: unknown): MongoContract {\n return contract as MongoContract;\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 // Descriptor self-consistency check.\n // Each extension that exposes a `contractSpace` must publish a\n // `headRef.hash` that matches the canonical hash recomputed from its\n // `contractJson`. A stale value would silently corrupt every downstream\n // boundary that trusts `headRef.hash` as the canonical identity (drift\n // detection, on-disk artefact emission, runner marker writes). Failing\n // fast at descriptor-load time turns \"extension author shipped an\n // inconsistent descriptor\" into an explicit, actionable error\n // (`MIGRATION.DESCRIPTOR_HEAD_HASH_MISMATCH`) rather than a confusing\n // mismatch surfacing several layers downstream. Mirrors the SQL family.\n const extensions = (controlStack.extensionPacks ??\n []) as readonly MongoControlExtensionDescriptor[];\n for (const extension of extensions) {\n if (extension.contractSpace) {\n const { contractJson, headRef } = extension.contractSpace;\n assertDescriptorSelfConsistency({\n extensionId: extension.id,\n target: contractJson.target,\n targetFamily: contractJson.targetFamily,\n storage: contractJson.storage,\n headRefHash: headRef.hash,\n ...mongoContractCanonicalizationHooks,\n });\n }\n }\n\n // Mongo dispatch surface. Every wire-level operation routes through\n // the adapter resolved from the control stack; the family carries no\n // direct imports of target/adapter/driver internals. Mirrors the SQL\n // family's `getControlAdapter()` helper.\n const adapter = controlStack.adapter as MongoControlAdapterDescriptor<'mongo'> | undefined;\n const getControlAdapter = (): MongoControlAdapter<'mongo'> => {\n if (!adapter) {\n throw new Error('Mongo family requires an adapter descriptor in ControlStack');\n }\n return adapter.create(controlStack as ControlStack<'mongo', 'mongo'>);\n };\n\n // The family-level driver type is `ControlDriverInstance<'mongo', string>`,\n // but the SPI methods are typed against `<'mongo', 'mongo'>`. Today's only\n // Mongo target is `'mongo'`, so the runtime values are identical; the cast\n // satisfies the structural type-system mismatch on `targetId`.\n const asMongoDriver = (\n driver: ControlDriverInstance<'mongo', string>,\n ): ControlDriverInstance<'mongo', 'mongo'> => driver as ControlDriverInstance<'mongo', 'mongo'>;\n\n return {\n familyId: 'mongo' as const,\n\n deserializeContract(contractJson: unknown): Contract {\n // The deserialized class form (MongoTargetContract, owned by\n // target-mongo) and the framework Contract are structurally\n // compatible — same fields, just a class instance on the storage\n // envelope. The cast preserves the framework signature.\n return deserializeMongoContract(contractJson) as unknown as Contract;\n },\n\n async verify(options): Promise<VerifyDatabaseResult> {\n const { driver, contract: rawContract, expectedTargetId, contractPath, configPath } = options;\n const startTime = Date.now();\n\n const contract = asValidatedMongoContract(rawContract);\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 marker = await getControlAdapter().readMarker(asMongoDriver(driver), APP_SPACE_ID);\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 verifySchema(options: {\n readonly contract: unknown;\n readonly schema: MongoSchemaIR;\n readonly strict: boolean;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'mongo', string>>;\n }): VerifyDatabaseSchemaResult {\n const contract = asValidatedMongoContract(options.contract);\n return verifyMongoSchema({\n contract,\n schema: options.schema,\n strict: options.strict,\n frameworkComponents: options.frameworkComponents,\n });\n },\n\n async sign(options): Promise<SignDatabaseResult> {\n const { driver, contract: rawContract, contractPath, configPath } = options;\n const startTime = Date.now();\n\n const contract = asValidatedMongoContract(rawContract);\n\n const contractStorageHash = contract.storage.storageHash;\n const contractProfileHash = contract.profileHash;\n\n const controlAdapter = getControlAdapter();\n const mongoDriver = asMongoDriver(driver);\n\n const existingMarker = await controlAdapter.readMarker(mongoDriver, APP_SPACE_ID);\n\n let markerCreated = false;\n let markerUpdated = false;\n let previousHashes: { storageHash?: string; profileHash?: string } | undefined;\n\n if (!existingMarker) {\n await controlAdapter.initMarker(mongoDriver, APP_SPACE_ID, {\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 controlAdapter.updateMarker(\n mongoDriver,\n APP_SPACE_ID,\n existingMarker.storageHash,\n {\n storageHash: contractStorageHash,\n profileHash: contractProfileHash,\n },\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): Promise<ContractMarkerRecord | null> {\n return getControlAdapter().readMarker(asMongoDriver(options.driver), options.space);\n },\n\n async readAllMarkers(options): Promise<ReadonlyMap<string, ContractMarkerRecord>> {\n return getControlAdapter().readAllMarkers(asMongoDriver(options.driver));\n },\n\n async readLedger(options): Promise<readonly LedgerEntryRecord[]> {\n return getControlAdapter().readLedger(asMongoDriver(options.driver), options.space);\n },\n\n async introspect(options): Promise<MongoSchemaIR> {\n return getControlAdapter().introspectSchema(asMongoDriver(options.driver));\n },\n\n toSchemaView(schema: MongoSchemaIR): CoreSchemaView {\n return mongoSchemaToView(schema);\n },\n\n toOperationPreview(operations: readonly MigrationPlanOperation[]): OperationPreview {\n return mongoOperationsToPreview(operations);\n },\n };\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"],"mappings":"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"}
package/dist/ir.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { ContractSerializer, SchemaIssue, SchemaVerifier, SchemaVerifyOptions, SchemaVerifyResult } from "@prisma-next/framework-components/control";
2
- import { MongoContract, MongoStorage } from "@prisma-next/mongo-contract";
2
+ import { MongoCollection, MongoContract, MongoStorage } from "@prisma-next/mongo-contract";
3
3
  import { Type } from "arktype";
4
+ import { ControlPolicy } from "@prisma-next/contract/types";
4
5
  import { Namespace } from "@prisma-next/framework-components/ir";
5
6
  import * as _$_prisma_next_contract_hashing0 from "@prisma-next/contract/hashing";
6
7
  import { JsonObject } from "@prisma-next/utils/json";
@@ -113,8 +114,11 @@ declare class MongoContractSerializer extends MongoContractSerializerBase<MongoC
113
114
  */
114
115
  declare abstract class MongoSchemaVerifierBase<TContract extends {
115
116
  readonly storage: MongoStorage;
117
+ readonly defaultControlPolicy?: ControlPolicy;
116
118
  }, TSchema> implements SchemaVerifier<TContract, TSchema> {
117
119
  verifySchema(options: SchemaVerifyOptions<TContract, TSchema>): SchemaVerifyResult;
120
+ protected effectiveCollectionControlPolicy(contract: TContract, collection: MongoCollection | undefined): ControlPolicy;
121
+ protected collectionControlPolicyForName(contract: TContract, collectionName: string): ControlPolicy;
118
122
  protected verifyCommonMongoSchema(options: SchemaVerifyOptions<TContract, TSchema>): readonly SchemaIssue[];
119
123
  /**
120
124
  * Per-namespace verification hook. Receives the namespace metadata plus
package/dist/ir.d.mts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ir.d.mts","names":[],"sources":["../src/core/ir/mongo-contract-serializer-base.ts","../src/core/ir/mongo-contract-serializer.ts","../src/core/ir/mongo-schema-verifier-base.ts"],"mappings":";;;;;;;;;;;;AAmCA;;;;;;;;;;;;;;;;;uBAAsB,2BAAA,uBACT,kBAAA,CAAmB,SAAA;EAAA,iBAEb,cAAA;cAEL,kBAAA,GAAqB,WAAA,SAAoB,IAAA;EAUrD,mBAAA,WAA8B,SAAA,GAAY,SAAA,CAAA,CAAW,IAAA,YAAgB,CAAA;EAKrE,iBAAA,CAAkB,QAAA,EAAU,SAAA,GAAY,UAAA;EAnBV;;;;;;EAgC9B,mBAAA,EAbkD,gCAAA,CAa/B,sBAAA;EAlBC;;;;;;;;;;;;;;;;EAAA,UAoCV,2BAAA,CAA4B,IAAA,YAAgB,aAAA;EAmCG;;;;;;EAAA,UAA/C,oBAAA,CAAqB,QAAA,EAAU,aAAA,GAAgB,aAAA;;;;AC5G3D;;;;;qBDkJqB,uBAAA,CAAwB,SAAA,EAAW,aAAA,GAAgB,SAAA;AAAA;;;;;;;;;AA5HxE;;;;cCtBa,uBAAA,SAAgC,2BAAA,CAA4B,aAAA;EAAA,UAC7D,uBAAA,CAAwB,SAAA,EAAW,aAAA,GAAgB,aAAA;AAAA;;;;;;;;ADqB/D;;;;;;;;;;;;;;;;uBELsB,uBAAA;EAAA,SACS,OAAA,EAAS,YAAA;AAAA,uBAE3B,cAAA,CAAe,SAAA,EAAW,OAAA;EAErC,YAAA,CAAa,OAAA,EAAS,mBAAA,CAAoB,SAAA,EAAW,OAAA,IAAW,kBAAA;EAAA,UAOtD,uBAAA,CACR,OAAA,EAAS,mBAAA,CAAoB,SAAA,EAAW,OAAA,aAC9B,WAAA;EFRD;;;;;;;;EAAA,mBEmCQ,eAAA,CAAgB,OAAA;IAAA,SACxB,QAAA,EAAU,SAAA;IAAA,SACV,MAAA,EAAQ,OAAA;IAAA,SACR,WAAA;IAAA,SACA,SAAA,EAAW,SAAA;EAAA,aACT,WAAA;EFrBe;;;;;EAAA,mBE4BT,sBAAA,CACjB,OAAA,EAAS,mBAAA,CAAoB,SAAA,EAAW,OAAA,aAC9B,WAAA;AAAA"}
1
+ {"version":3,"file":"ir.d.mts","names":[],"sources":["../src/core/ir/mongo-contract-serializer-base.ts","../src/core/ir/mongo-contract-serializer.ts","../src/core/ir/mongo-schema-verifier-base.ts"],"mappings":";;;;;;;;;;;;;;AAmCA;;;;;;;;;;;;;;;;uBAAsB,2BAAA,uBACT,kBAAA,CAAmB,SAAA;EAAA,iBAEb,cAAA;cAEL,kBAAA,GAAqB,WAAA,SAAoB,IAAA;EAUrD,mBAAA,WAA8B,SAAA,GAAY,SAAA,CAAA,CAAW,IAAA,YAAgB,CAAA;EAKrE,iBAAA,CAAkB,QAAA,EAAU,SAAA,GAAY,UAAA;EAnB7B;;;;;;EAgCX,mBAAA,EAbkD,gCAAA,CAa/B,sBAAA;EAlBnB;;;;;;;;;;;;;;;;EAAA,UAoCU,2BAAA,CAA4B,IAAA,YAAgB,aAAA;EAmCvB;;;;;;EAAA,UAArB,oBAAA,CAAqB,QAAA,EAAU,aAAA,GAAgB,aAAA;EAsCsB;;;;AClJjF;;;;EDkJiF,mBAA5D,uBAAA,CAAwB,SAAA,EAAW,aAAA,GAAgB,SAAA;AAAA;;;;;;;;;;AA5HxE;;;cCtBa,uBAAA,SAAgC,2BAAA,CAA4B,aAAA;EAAA,UAC7D,uBAAA,CAAwB,SAAA,EAAW,aAAA,GAAgB,aAAA;AAAA;;;;;;;;ADqB/D;;;;;;;;;;;;;;;;uBEFsB,uBAAA;EAAA,SAET,OAAA,EAAS,YAAA;EAAA,SACT,oBAAA,GAAuB,aAAA;AAAA,uBAGvB,cAAA,CAAe,SAAA,EAAW,OAAA;EAErC,YAAA,CAAa,OAAA,EAAS,mBAAA,CAAoB,SAAA,EAAW,OAAA,IAAW,kBAAA;EAAA,UAOtD,gCAAA,CACR,QAAA,EAAU,SAAA,EACV,UAAA,EAAY,eAAA,eACX,aAAA;EAAA,UAIO,8BAAA,CACR,QAAA,EAAU,SAAA,EACV,cAAA,WACC,aAAA;EAAA,UAMO,uBAAA,CACR,OAAA,EAAS,mBAAA,CAAoB,SAAA,EAAW,OAAA,aAC9B,WAAA;;;;;;;;;qBA2BO,eAAA,CAAgB,OAAA;IAAA,SACxB,QAAA,EAAU,SAAA;IAAA,SACV,MAAA,EAAQ,OAAA;IAAA,SACR,WAAA;IAAA,SACA,SAAA,EAAW,SAAA;EAAA,aACT,WAAA;EF9Bb;;;;;EAAA,mBEqCmB,sBAAA,CACjB,OAAA,EAAS,mBAAA,CAAoB,SAAA,EAAW,OAAA,aAC9B,WAAA;AAAA"}
package/dist/ir.mjs CHANGED
@@ -1,4 +1,6 @@
1
1
  import { n as MongoContractSerializerBase, t as MongoContractSerializer } from "./mongo-contract-serializer-DAoKJxiP.mjs";
2
+ import { effectiveControlPolicy } from "@prisma-next/contract/types";
3
+ import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
2
4
  //#region src/core/ir/mongo-schema-verifier-base.ts
3
5
  /**
4
6
  * Mongo family `SchemaVerifier` abstract base. Commits the Mongo family
@@ -31,6 +33,13 @@ var MongoSchemaVerifierBase = class {
31
33
  issues
32
34
  };
33
35
  }
36
+ effectiveCollectionControlPolicy(contract, collection) {
37
+ return effectiveControlPolicy(collection?.control, contract.defaultControlPolicy);
38
+ }
39
+ collectionControlPolicyForName(contract, collectionName) {
40
+ const collection = contract.storage.namespaces[UNBOUND_NAMESPACE_ID]?.collections[collectionName];
41
+ return this.effectiveCollectionControlPolicy(contract, collection);
42
+ }
34
43
  verifyCommonMongoSchema(options) {
35
44
  const issues = [];
36
45
  const { namespaces } = options.contract.storage;
package/dist/ir.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ir.mjs","names":[],"sources":["../src/core/ir/mongo-schema-verifier-base.ts"],"sourcesContent":["import type {\n SchemaIssue,\n SchemaVerifier,\n SchemaVerifyOptions,\n SchemaVerifyResult,\n} from '@prisma-next/framework-components/control';\nimport type { Namespace } from '@prisma-next/framework-components/ir';\nimport type { MongoStorage } from '@prisma-next/mongo-contract';\n\n/**\n * Mongo family `SchemaVerifier` abstract base. Commits the Mongo family\n * to namespace-keyed verification: the family-shared walk iterates\n * `storage.namespaces` in sorted order and dispatches per-namespace\n * through the protected `verifyNamespace` hook, then aggregates\n * target-extension issues from `verifyTargetExtensions`.\n *\n * Per-element diff work (collection / index / validator comparisons)\n * lives on the target inside `verifyNamespace`. The family's structural\n * commitment is \"verification is namespaced\"; the target's commitment is\n * \"verification of a given namespace's collections is the existing\n * diff/canonicalize pipeline\". The split keeps target-mongo's\n * introspection-side helpers (`contractToMongoSchemaIR`,\n * `canonicalizeSchemasForVerification`, `diffMongoSchemas`) in the target\n * layer where they belong, while the family base owns the iteration\n * scaffolding that makes namespaces a first-class verifier concept.\n *\n * Target-specific issue kinds (Atlas-only, future RLS-equivalents)\n * surface through `verifyTargetExtensions`; that hook returns the empty\n * list when no extensions exist over the Mongo family alphabet.\n */\nexport abstract class MongoSchemaVerifierBase<\n TContract extends { readonly storage: MongoStorage },\n TSchema,\n> implements SchemaVerifier<TContract, TSchema>\n{\n verifySchema(options: SchemaVerifyOptions<TContract, TSchema>): SchemaVerifyResult {\n const issues: SchemaIssue[] = [];\n issues.push(...this.verifyCommonMongoSchema(options));\n issues.push(...this.verifyTargetExtensions(options));\n return { ok: issues.length === 0, issues };\n }\n\n protected verifyCommonMongoSchema(\n options: SchemaVerifyOptions<TContract, TSchema>,\n ): readonly SchemaIssue[] {\n const issues: SchemaIssue[] = [];\n const { namespaces } = options.contract.storage;\n const namespaceIds = Object.keys(namespaces).sort();\n for (const namespaceId of namespaceIds) {\n const namespace = namespaces[namespaceId];\n if (!namespace) continue;\n issues.push(\n ...this.verifyNamespace({\n contract: options.contract,\n schema: options.schema,\n namespaceId,\n namespace,\n }),\n );\n }\n return issues;\n }\n\n /**\n * Per-namespace verification hook. Receives the namespace metadata plus\n * the full contract + schema pair; the target's implementation owns the\n * per-collection diff using its existing introspection-side helpers.\n * Slice the schema by namespace at the call site (or compute the full\n * diff once and dispatch per namespace) — the family base does not\n * prescribe the per-namespace shape.\n */\n protected abstract verifyNamespace(options: {\n readonly contract: TContract;\n readonly schema: TSchema;\n readonly namespaceId: string;\n readonly namespace: Namespace;\n }): readonly SchemaIssue[];\n\n /**\n * Target-specific extensions — Atlas-only kinds, target-only\n * namespace-mismatch issues that don't fit the family-shared walk.\n * Returns the empty list when the target ships no extensions.\n */\n protected abstract verifyTargetExtensions(\n options: SchemaVerifyOptions<TContract, TSchema>,\n ): readonly SchemaIssue[];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA8BA,IAAsB,0BAAtB,MAIA;CACE,aAAa,SAAsE;EACjF,MAAM,SAAwB,CAAC;EAC/B,OAAO,KAAK,GAAG,KAAK,wBAAwB,OAAO,CAAC;EACpD,OAAO,KAAK,GAAG,KAAK,uBAAuB,OAAO,CAAC;EACnD,OAAO;GAAE,IAAI,OAAO,WAAW;GAAG;EAAO;CAC3C;CAEA,wBACE,SACwB;EACxB,MAAM,SAAwB,CAAC;EAC/B,MAAM,EAAE,eAAe,QAAQ,SAAS;EACxC,MAAM,eAAe,OAAO,KAAK,UAAU,EAAE,KAAK;EAClD,KAAK,MAAM,eAAe,cAAc;GACtC,MAAM,YAAY,WAAW;GAC7B,IAAI,CAAC,WAAW;GAChB,OAAO,KACL,GAAG,KAAK,gBAAgB;IACtB,UAAU,QAAQ;IAClB,QAAQ,QAAQ;IAChB;IACA;GACF,CAAC,CACH;EACF;EACA,OAAO;CACT;AAyBF"}
1
+ {"version":3,"file":"ir.mjs","names":[],"sources":["../src/core/ir/mongo-schema-verifier-base.ts"],"sourcesContent":["import type { ControlPolicy } from '@prisma-next/contract/types';\nimport { effectiveControlPolicy } from '@prisma-next/contract/types';\nimport type {\n SchemaIssue,\n SchemaVerifier,\n SchemaVerifyOptions,\n SchemaVerifyResult,\n} from '@prisma-next/framework-components/control';\nimport type { Namespace } from '@prisma-next/framework-components/ir';\nimport { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';\nimport type { MongoCollection, MongoStorage } from '@prisma-next/mongo-contract';\n\n/**\n * Mongo family `SchemaVerifier` abstract base. Commits the Mongo family\n * to namespace-keyed verification: the family-shared walk iterates\n * `storage.namespaces` in sorted order and dispatches per-namespace\n * through the protected `verifyNamespace` hook, then aggregates\n * target-extension issues from `verifyTargetExtensions`.\n *\n * Per-element diff work (collection / index / validator comparisons)\n * lives on the target inside `verifyNamespace`. The family's structural\n * commitment is \"verification is namespaced\"; the target's commitment is\n * \"verification of a given namespace's collections is the existing\n * diff/canonicalize pipeline\". The split keeps target-mongo's\n * introspection-side helpers (`contractToMongoSchemaIR`,\n * `canonicalizeSchemasForVerification`, `diffMongoSchemas`) in the target\n * layer where they belong, while the family base owns the iteration\n * scaffolding that makes namespaces a first-class verifier concept.\n *\n * Target-specific issue kinds (Atlas-only, future RLS-equivalents)\n * surface through `verifyTargetExtensions`; that hook returns the empty\n * list when no extensions exist over the Mongo family alphabet.\n */\nexport abstract class MongoSchemaVerifierBase<\n TContract extends {\n readonly storage: MongoStorage;\n readonly defaultControlPolicy?: ControlPolicy;\n },\n TSchema,\n> implements SchemaVerifier<TContract, TSchema>\n{\n verifySchema(options: SchemaVerifyOptions<TContract, TSchema>): SchemaVerifyResult {\n const issues: SchemaIssue[] = [];\n issues.push(...this.verifyCommonMongoSchema(options));\n issues.push(...this.verifyTargetExtensions(options));\n return { ok: issues.length === 0, issues };\n }\n\n protected effectiveCollectionControlPolicy(\n contract: TContract,\n collection: MongoCollection | undefined,\n ): ControlPolicy {\n return effectiveControlPolicy(collection?.control, contract.defaultControlPolicy);\n }\n\n protected collectionControlPolicyForName(\n contract: TContract,\n collectionName: string,\n ): ControlPolicy {\n const namespace = contract.storage.namespaces[UNBOUND_NAMESPACE_ID];\n const collection = namespace?.collections[collectionName];\n return this.effectiveCollectionControlPolicy(contract, collection);\n }\n\n protected verifyCommonMongoSchema(\n options: SchemaVerifyOptions<TContract, TSchema>,\n ): readonly SchemaIssue[] {\n const issues: SchemaIssue[] = [];\n const { namespaces } = options.contract.storage;\n const namespaceIds = Object.keys(namespaces).sort();\n for (const namespaceId of namespaceIds) {\n const namespace = namespaces[namespaceId];\n if (!namespace) continue;\n issues.push(\n ...this.verifyNamespace({\n contract: options.contract,\n schema: options.schema,\n namespaceId,\n namespace,\n }),\n );\n }\n return issues;\n }\n\n /**\n * Per-namespace verification hook. Receives the namespace metadata plus\n * the full contract + schema pair; the target's implementation owns the\n * per-collection diff using its existing introspection-side helpers.\n * Slice the schema by namespace at the call site (or compute the full\n * diff once and dispatch per namespace) — the family base does not\n * prescribe the per-namespace shape.\n */\n protected abstract verifyNamespace(options: {\n readonly contract: TContract;\n readonly schema: TSchema;\n readonly namespaceId: string;\n readonly namespace: Namespace;\n }): readonly SchemaIssue[];\n\n /**\n * Target-specific extensions — Atlas-only kinds, target-only\n * namespace-mismatch issues that don't fit the family-shared walk.\n * Returns the empty list when the target ships no extensions.\n */\n protected abstract verifyTargetExtensions(\n options: SchemaVerifyOptions<TContract, TSchema>,\n ): readonly SchemaIssue[];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAsB,0BAAtB,MAOA;CACE,aAAa,SAAsE;EACjF,MAAM,SAAwB,CAAC;EAC/B,OAAO,KAAK,GAAG,KAAK,wBAAwB,OAAO,CAAC;EACpD,OAAO,KAAK,GAAG,KAAK,uBAAuB,OAAO,CAAC;EACnD,OAAO;GAAE,IAAI,OAAO,WAAW;GAAG;EAAO;CAC3C;CAEA,iCACE,UACA,YACe;EACf,OAAO,uBAAuB,YAAY,SAAS,SAAS,oBAAoB;CAClF;CAEA,+BACE,UACA,gBACe;EAEf,MAAM,aADY,SAAS,QAAQ,WAAW,uBAChB,YAAY;EAC1C,OAAO,KAAK,iCAAiC,UAAU,UAAU;CACnE;CAEA,wBACE,SACwB;EACxB,MAAM,SAAwB,CAAC;EAC/B,MAAM,EAAE,eAAe,QAAQ,SAAS;EACxC,MAAM,eAAe,OAAO,KAAK,UAAU,EAAE,KAAK;EAClD,KAAK,MAAM,eAAe,cAAc;GACtC,MAAM,YAAY,WAAW;GAC7B,IAAI,CAAC,WAAW;GAChB,OAAO,KACL,GAAG,KAAK,gBAAgB;IACtB,UAAU,QAAQ;IAClB,QAAQ,QAAQ;IAChB;IACA;GACF,CAAC,CACH;EACF;EACA,OAAO;CACT;AAyBF"}
@@ -0,0 +1,2 @@
1
+ import { defaultMongoDomainNamespaceId, defaultMongoStorageNamespaceId } from "@prisma-next/mongo-contract";
2
+ export { defaultMongoDomainNamespaceId, defaultMongoStorageNamespaceId };
@@ -0,0 +1,2 @@
1
+ import { defaultMongoDomainNamespaceId, defaultMongoStorageNamespaceId } from "@prisma-next/mongo-contract";
2
+ export { defaultMongoDomainNamespaceId, defaultMongoStorageNamespaceId };
@@ -1 +1 @@
1
- {"version":3,"file":"schema-verify.d.mts","names":[],"sources":["../src/core/schema-verify/verify-mongo-schema.ts"],"mappings":";;;;;;UAaiB,wBAAA;EAAA,SACN,QAAA,EAAU,aAAA;EAAA,SACV,MAAA,EAAQ,aAAA;EAAA,SACR,MAAA;EAAA,SACA,OAAA,GAAU,gBAAA;EAHA;;;;;EAAA,SASV,mBAAA,EAAqB,aAAA,CAAc,8BAAA;AAAA;AAAA,iBAG9B,iBAAA,CAAkB,OAAA,EAAS,wBAAA,GAA2B,0BAA0B"}
1
+ {"version":3,"file":"schema-verify.d.mts","names":[],"sources":["../src/core/schema-verify/verify-mongo-schema.ts"],"mappings":";;;;;;UAeiB,wBAAA;EAAA,SACN,QAAA,EAAU,aAAA;EAAA,SACV,MAAA,EAAQ,aAAA;EAAA,SACR,MAAA;EAAA,SACA,OAAA,GAAU,gBAAA;EAHA;;;;;EAAA,SASV,mBAAA,EAAqB,aAAA,CAAc,8BAAA;AAAA;AAAA,iBAG9B,iBAAA,CAAkB,OAAA,EAAS,wBAAA,GAA2B,0BAA0B"}
@@ -1,2 +1,2 @@
1
- import { t as verifyMongoSchema } from "./verify-mongo-schema-Bhxvdah3.mjs";
1
+ import { t as verifyMongoSchema } from "./verify-mongo-schema-CFRMURgz.mjs";
2
2
  export { verifyMongoSchema };