@prisma-next/family-mongo 0.4.0-dev.5 → 0.4.0-dev.6

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 +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":";;;;;UAgCiB,0BAAA,SACP,+BAA+B,gBACrC,kBAAkB;2CACqB;AAH3C;AACyC,iBAkSzB,yBAAA,CAlSyB,aAAA,EAkSgB,YAlShB,CAAA,EAkS+B,0BAlS/B;;;cCV5B,uBAAuB,iCAAiC;;;cCVxD,uBAAuB,6CAGlC"}
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":";;;;;UAgCiB,0BAAA,SACP,+BAA+B,gBACrC,kBAAkB;2CACqB;AAH3C;AACyC,iBAkSzB,yBAAA,CAlSyB,aAAA,EAkSgB,YAlShB,CAAA,EAkS+B,0BAlS/B;;;cCV5B,uBAAuB,iCAAiC;;;cCTxD,uBAAuB,6CAGlC"}
package/dist/control.mjs CHANGED
@@ -6,6 +6,12 @@ import { MongoMigrationPlanner, MongoMigrationRunner, contractToMongoSchemaIR, i
6
6
  import { ifDefined } from "@prisma-next/utils/defined";
7
7
  import { canonicalize, deepEqual } from "@prisma-next/mongo-schema-ir";
8
8
  import mongoTargetDescriptorMeta from "@prisma-next/target-mongo/pack";
9
+ import { stat } from "node:fs/promises";
10
+ import { pathToFileURL } from "node:url";
11
+ import { errorMigrationFileMissing, errorMigrationInvalidDefaultExport, errorMigrationPlanNotArray } from "@prisma-next/errors/migration";
12
+ import { writeMigrationOps } from "@prisma-next/migration-tools/io";
13
+ import { Migration } from "@prisma-next/migration-tools/migration";
14
+ import { join } from "pathe";
9
15
 
10
16
  //#region src/core/schema-diff.ts
11
17
  function diffMongoSchemas(live, expected, strict) {
@@ -620,6 +626,79 @@ var MongoFamilyDescriptor = class {
620
626
  };
621
627
  const mongoFamilyDescriptor = new MongoFamilyDescriptor();
622
628
 
629
+ //#endregion
630
+ //#region src/core/mongo-emit.ts
631
+ /**
632
+ * Mongo's in-process implementation of the `emit` capability on
633
+ * `TargetMigrationsCapability`.
634
+ *
635
+ * The CLI's `migration emit` (and `migration plan`'s inline emit) dispatches
636
+ * here for any target that does not implement `resolveDescriptors`. Two
637
+ * authoring shapes are accepted:
638
+ *
639
+ * 1. Class subclass (canonical):
640
+ * class M extends Migration { override plan() { return [...] } }
641
+ * export default M;
642
+ * Migration.run(import.meta.url, M);
643
+ *
644
+ * 2. Factory function returning a Migration-satisfying object:
645
+ * export default () => ({ plan() { return [createCollection("users")] } });
646
+ *
647
+ * We dynamic-import the file (so that any structured errors thrown by
648
+ * `placeholder(...)` propagate as real exceptions to the CLI), dispatch on
649
+ * the export's shape (class subclass vs. callable function), and persist
650
+ * `ops.json` via the framework I/O helper. `Migration.run` already guards
651
+ * itself against firing when the file is imported rather than run as the
652
+ * main module, so this is safe to call from inside the CLI process.
653
+ *
654
+ * Attestation (computing and writing `migrationId` to `manifest.json`) is
655
+ * owned by the framework's `emitMigration` helper, not this capability.
656
+ */
657
+ const MIGRATION_TS_FILE = "migration.ts";
658
+ /**
659
+ * Implementation of `TargetMigrationsCapability.emit` for Mongo.
660
+ *
661
+ * Loads `<dir>/migration.ts` and dispatches on the default export's shape:
662
+ * if it is a `Migration` subclass, instantiates it and calls `plan()`;
663
+ * otherwise invokes it as a factory function, validates the returned value
664
+ * has a `plan()` method, and calls it.
665
+ * Writes `ops.json` and returns the operations for the framework helper to
666
+ * render. Attestation (`migrationId` in `manifest.json`) is the framework
667
+ * helper's responsibility; this capability MUST NOT call `attestMigration`
668
+ * itself.
669
+ */
670
+ async function mongoEmit(options) {
671
+ const filePath = join(options.dir, MIGRATION_TS_FILE);
672
+ try {
673
+ await stat(filePath);
674
+ } catch {
675
+ throw errorMigrationFileMissing(options.dir);
676
+ }
677
+ const MigrationExport = (await import(pathToFileURL(filePath).href)).default;
678
+ if (typeof MigrationExport !== "function") throw errorMigrationInvalidDefaultExport(options.dir, `default export of type ${typeof MigrationExport}`);
679
+ let migration;
680
+ if (MigrationExport.prototype instanceof Migration) migration = new MigrationExport();
681
+ else {
682
+ let factoryResult;
683
+ try {
684
+ factoryResult = await MigrationExport();
685
+ } catch (error) {
686
+ if (error instanceof TypeError && /cannot be invoked without 'new'/i.test(error.message)) throw errorMigrationInvalidDefaultExport(options.dir, "a default export that does not extend Migration (from @prisma-next/migration-tools/migration)");
687
+ throw error;
688
+ }
689
+ if (typeof factoryResult !== "object" || factoryResult === null || typeof factoryResult.plan !== "function") throw errorMigrationInvalidDefaultExport(options.dir, `factory must return an object with a plan() method; got ${describeValue(factoryResult)}`);
690
+ migration = factoryResult;
691
+ }
692
+ const operations = migration.plan();
693
+ if (!Array.isArray(operations)) throw errorMigrationPlanNotArray(options.dir, describeValue(operations));
694
+ await writeMigrationOps(options.dir, operations);
695
+ return operations;
696
+ }
697
+ function describeValue(value) {
698
+ if (value === null) return "null";
699
+ return `a value of type ${typeof value}`;
700
+ }
701
+
623
702
  //#endregion
624
703
  //#region src/core/mongo-target-descriptor.ts
625
704
  const mongoTargetDescriptor = {
@@ -638,7 +717,8 @@ const mongoTargetDescriptor = {
638
717
  },
639
718
  contractToSchema(contract) {
640
719
  return contractToMongoSchemaIR(contract);
641
- }
720
+ },
721
+ emit: mongoEmit
642
722
  },
643
723
  create() {
644
724
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"control.mjs","names":["issues: SchemaIssue[]","collectionChildren: SchemaVerificationNode[]","nodes: SchemaVerificationNode[]","children: SchemaTreeNode[]","options: string[]","validatorChildren: SchemaTreeNode[]","optLabels: string[]","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-diff.ts","../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 {\n SchemaIssue,\n SchemaVerificationNode,\n} from '@prisma-next/framework-components/control';\nimport type {\n MongoSchemaCollection,\n MongoSchemaIndex,\n MongoSchemaIR,\n} from '@prisma-next/mongo-schema-ir';\nimport { canonicalize, deepEqual } from '@prisma-next/mongo-schema-ir';\n\nexport function diffMongoSchemas(\n live: MongoSchemaIR,\n expected: MongoSchemaIR,\n strict: boolean,\n): {\n root: SchemaVerificationNode;\n issues: SchemaIssue[];\n counts: { pass: number; warn: number; fail: number; totalNodes: number };\n} {\n const issues: SchemaIssue[] = [];\n const collectionChildren: SchemaVerificationNode[] = [];\n let pass = 0;\n let warn = 0;\n let fail = 0;\n\n const allNames = new Set([...live.collectionNames, ...expected.collectionNames]);\n\n for (const name of [...allNames].sort()) {\n const liveColl = live.collection(name);\n const expectedColl = expected.collection(name);\n\n if (!liveColl && expectedColl) {\n issues.push({\n kind: 'missing_table',\n table: name,\n message: `Collection \"${name}\" is missing from the database`,\n });\n collectionChildren.push({\n status: 'fail',\n kind: 'collection',\n name,\n contractPath: `storage.collections.${name}`,\n code: 'MISSING_COLLECTION',\n message: `Collection \"${name}\" is missing`,\n expected: name,\n actual: null,\n children: [],\n });\n fail++;\n continue;\n }\n\n if (liveColl && !expectedColl) {\n const status = strict ? 'fail' : 'warn';\n issues.push({\n kind: 'extra_table',\n table: name,\n message: `Extra collection \"${name}\" exists in the database but not in the contract`,\n });\n collectionChildren.push({\n status,\n kind: 'collection',\n name,\n contractPath: `storage.collections.${name}`,\n code: 'EXTRA_COLLECTION',\n message: `Extra collection \"${name}\" found`,\n expected: null,\n actual: name,\n children: [],\n });\n if (status === 'fail') fail++;\n else warn++;\n continue;\n }\n\n const lc = liveColl as MongoSchemaCollection;\n const ec = expectedColl as MongoSchemaCollection;\n const indexChildren = diffIndexes(name, lc, ec, strict, issues);\n const validatorChildren = diffValidator(name, lc, ec, strict, issues);\n const optionsChildren = diffOptions(name, lc, ec, strict, issues);\n const children = [...indexChildren, ...validatorChildren, ...optionsChildren];\n\n const worstStatus = children.reduce<'pass' | 'warn' | 'fail'>(\n (s, c) => (c.status === 'fail' ? 'fail' : c.status === 'warn' && s !== 'fail' ? 'warn' : s),\n 'pass',\n );\n\n for (const c of children) {\n if (c.status === 'pass') pass++;\n else if (c.status === 'warn') warn++;\n else fail++;\n }\n\n if (children.length === 0) {\n pass++;\n }\n\n collectionChildren.push({\n status: worstStatus,\n kind: 'collection',\n name,\n contractPath: `storage.collections.${name}`,\n code: worstStatus === 'pass' ? 'MATCH' : 'DRIFT',\n message:\n worstStatus === 'pass' ? `Collection \"${name}\" matches` : `Collection \"${name}\" has drift`,\n expected: name,\n actual: name,\n children,\n });\n }\n\n const rootStatus = fail > 0 ? 'fail' : warn > 0 ? 'warn' : 'pass';\n const totalNodes = pass + warn + fail + collectionChildren.length;\n\n const root: SchemaVerificationNode = {\n status: rootStatus,\n kind: 'root',\n name: 'mongo-schema',\n contractPath: 'storage',\n code: rootStatus === 'pass' ? 'MATCH' : 'DRIFT',\n message: rootStatus === 'pass' ? 'Schema matches' : 'Schema has drift',\n expected: null,\n actual: null,\n children: collectionChildren,\n };\n\n return { root, issues, counts: { pass, warn, fail, totalNodes } };\n}\n\nfunction buildIndexLookupKey(index: MongoSchemaIndex): string {\n const keys = index.keys.map((k) => `${k.field}:${k.direction}`).join(',');\n const opts = [\n index.unique ? 'unique' : '',\n index.sparse ? 'sparse' : '',\n index.expireAfterSeconds != null ? `ttl:${index.expireAfterSeconds}` : '',\n index.partialFilterExpression ? `pfe:${canonicalize(index.partialFilterExpression)}` : '',\n index.wildcardProjection ? `wp:${canonicalize(index.wildcardProjection)}` : '',\n index.collation ? `col:${canonicalize(index.collation)}` : '',\n index.weights ? `wt:${canonicalize(index.weights)}` : '',\n index.default_language ? `dl:${index.default_language}` : '',\n index.language_override ? `lo:${index.language_override}` : '',\n ]\n .filter(Boolean)\n .join(';');\n return opts ? `${keys}|${opts}` : keys;\n}\n\nfunction formatIndexName(index: MongoSchemaIndex): string {\n return index.keys.map((k) => `${k.field}:${k.direction}`).join(', ');\n}\n\nfunction diffIndexes(\n collName: string,\n live: MongoSchemaCollection,\n expected: MongoSchemaCollection,\n strict: boolean,\n issues: SchemaIssue[],\n): SchemaVerificationNode[] {\n const nodes: SchemaVerificationNode[] = [];\n const liveLookup = new Map<string, MongoSchemaIndex>();\n for (const idx of live.indexes) liveLookup.set(buildIndexLookupKey(idx), idx);\n\n const expectedLookup = new Map<string, MongoSchemaIndex>();\n for (const idx of expected.indexes) expectedLookup.set(buildIndexLookupKey(idx), idx);\n\n for (const [key, idx] of expectedLookup) {\n if (liveLookup.has(key)) {\n nodes.push({\n status: 'pass',\n kind: 'index',\n name: formatIndexName(idx),\n contractPath: `storage.collections.${collName}.indexes`,\n code: 'MATCH',\n message: `Index ${formatIndexName(idx)} matches`,\n expected: key,\n actual: key,\n children: [],\n });\n } else {\n issues.push({\n kind: 'index_mismatch',\n table: collName,\n indexOrConstraint: formatIndexName(idx),\n message: `Index ${formatIndexName(idx)} missing on collection \"${collName}\"`,\n });\n nodes.push({\n status: 'fail',\n kind: 'index',\n name: formatIndexName(idx),\n contractPath: `storage.collections.${collName}.indexes`,\n code: 'MISSING_INDEX',\n message: `Index ${formatIndexName(idx)} missing`,\n expected: key,\n actual: null,\n children: [],\n });\n }\n }\n\n for (const [key, idx] of liveLookup) {\n if (!expectedLookup.has(key)) {\n const status = strict ? 'fail' : 'warn';\n issues.push({\n kind: 'extra_index',\n table: collName,\n indexOrConstraint: formatIndexName(idx),\n message: `Extra index ${formatIndexName(idx)} on collection \"${collName}\"`,\n });\n nodes.push({\n status,\n kind: 'index',\n name: formatIndexName(idx),\n contractPath: `storage.collections.${collName}.indexes`,\n code: 'EXTRA_INDEX',\n message: `Extra index ${formatIndexName(idx)}`,\n expected: null,\n actual: key,\n children: [],\n });\n }\n }\n\n return nodes;\n}\n\nfunction diffValidator(\n collName: string,\n live: MongoSchemaCollection,\n expected: MongoSchemaCollection,\n strict: boolean,\n issues: SchemaIssue[],\n): SchemaVerificationNode[] {\n if (!live.validator && !expected.validator) return [];\n\n if (expected.validator && !live.validator) {\n issues.push({\n kind: 'type_missing',\n table: collName,\n message: `Validator missing on collection \"${collName}\"`,\n });\n return [\n {\n status: 'fail',\n kind: 'validator',\n name: 'validator',\n contractPath: `storage.collections.${collName}.validator`,\n code: 'MISSING_VALIDATOR',\n message: 'Validator missing',\n expected: canonicalize(expected.validator.jsonSchema),\n actual: null,\n children: [],\n },\n ];\n }\n\n if (!expected.validator && live.validator) {\n const status = strict ? 'fail' : 'warn';\n issues.push({\n kind: 'extra_validator',\n table: collName,\n message: `Extra validator on collection \"${collName}\"`,\n });\n return [\n {\n status,\n kind: 'validator',\n name: 'validator',\n contractPath: `storage.collections.${collName}.validator`,\n code: 'EXTRA_VALIDATOR',\n message: 'Extra validator found',\n expected: null,\n actual: canonicalize(live.validator.jsonSchema),\n children: [],\n },\n ];\n }\n\n const liveVal = live.validator as NonNullable<typeof live.validator>;\n const expectedVal = expected.validator as NonNullable<typeof expected.validator>;\n const liveSchema = canonicalize(liveVal.jsonSchema);\n const expectedSchema = canonicalize(expectedVal.jsonSchema);\n\n if (\n liveSchema !== expectedSchema ||\n liveVal.validationLevel !== expectedVal.validationLevel ||\n liveVal.validationAction !== expectedVal.validationAction\n ) {\n issues.push({\n kind: 'type_mismatch',\n table: collName,\n expected: expectedSchema,\n actual: liveSchema,\n message: `Validator mismatch on collection \"${collName}\"`,\n });\n return [\n {\n status: 'fail',\n kind: 'validator',\n name: 'validator',\n contractPath: `storage.collections.${collName}.validator`,\n code: 'VALIDATOR_MISMATCH',\n message: 'Validator mismatch',\n expected: {\n jsonSchema: expectedVal.jsonSchema,\n validationLevel: expectedVal.validationLevel,\n validationAction: expectedVal.validationAction,\n },\n actual: {\n jsonSchema: liveVal.jsonSchema,\n validationLevel: liveVal.validationLevel,\n validationAction: liveVal.validationAction,\n },\n children: [],\n },\n ];\n }\n\n return [\n {\n status: 'pass',\n kind: 'validator',\n name: 'validator',\n contractPath: `storage.collections.${collName}.validator`,\n code: 'MATCH',\n message: 'Validator matches',\n expected: expectedSchema,\n actual: liveSchema,\n children: [],\n },\n ];\n}\n\nfunction diffOptions(\n collName: string,\n live: MongoSchemaCollection,\n expected: MongoSchemaCollection,\n strict: boolean,\n issues: SchemaIssue[],\n): SchemaVerificationNode[] {\n if (!live.options && !expected.options) return [];\n\n if (!expected.options && live.options) {\n const status = strict ? 'fail' : 'warn';\n issues.push({\n kind: 'type_mismatch',\n table: collName,\n actual: canonicalize(live.options),\n message: `Extra collection options on \"${collName}\"`,\n });\n return [\n {\n status,\n kind: 'options',\n name: 'options',\n contractPath: `storage.collections.${collName}.options`,\n code: 'EXTRA_OPTIONS',\n message: 'Extra collection options found',\n expected: null,\n actual: live.options,\n children: [],\n },\n ];\n }\n\n if (deepEqual(live.options, expected.options)) {\n return [\n {\n status: 'pass',\n kind: 'options',\n name: 'options',\n contractPath: `storage.collections.${collName}.options`,\n code: 'MATCH',\n message: 'Collection options match',\n expected: canonicalize(expected.options),\n actual: canonicalize(live.options),\n children: [],\n },\n ];\n }\n\n issues.push({\n kind: 'type_mismatch',\n table: collName,\n expected: canonicalize(expected.options),\n actual: canonicalize(live.options),\n message: `Collection options mismatch on \"${collName}\"`,\n });\n return [\n {\n status: 'fail',\n kind: 'options',\n name: 'options',\n contractPath: `storage.collections.${collName}.options`,\n code: 'OPTIONS_MISMATCH',\n message: 'Collection options mismatch',\n expected: expected.options,\n actual: live.options,\n children: [],\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 { introspectSchema } from '@prisma-next/adapter-mongo/control';\nimport type { Contract, ContractMarkerRecord } from '@prisma-next/contract/types';\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_SCHEMA_FAILURE,\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 contractToMongoSchemaIR,\n initMarker,\n readMarker,\n updateMarker,\n} from '@prisma-next/target-mongo/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { Db } from 'mongodb';\nimport { diffMongoSchemas } from './schema-diff';\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<unknown>;\n }): Promise<VerifyDatabaseSchemaResult> {\n const { driver, contract: rawContract, strict, contractPath, configPath } = options;\n const startTime = Date.now();\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 const expectedIR = contractToMongoSchemaIR(contract);\n\n const { root, issues, counts } = diffMongoSchemas(liveIR, expectedIR, strict);\n\n const ok = counts.fail === 0;\n\n return {\n ok,\n ...ifDefined('code', ok ? undefined : VERIFY_CODE_SCHEMA_FAILURE),\n summary: ok ? 'Schema matches contract' : `Schema verification found ${counts.fail} issue(s)`,\n contract: {\n storageHash: contract.storage.storageHash,\n ...ifDefined('profileHash', contract.profileHash),\n },\n target: { expected: contract.target },\n schema: { issues, root, counts },\n meta: {\n ...ifDefined('contractPath', contractPath),\n ...ifDefined('configPath', configPath),\n strict,\n },\n timings: { total: Date.now() - startTime },\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 } from '@prisma-next/adapter-mongo/control';\nimport type { Contract } from '@prisma-next/contract/types';\nimport type { MigratableTargetDescriptor } 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\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 return {\n async execute(options) {\n cachedDeps ??= createMongoRunnerDeps(options.driver);\n const { driver: _, ...runnerOptions } = options;\n const runner = new MongoMigrationRunner(cachedDeps);\n return runner.execute(runnerOptions);\n },\n };\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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"}
1
+ {"version":3,"file":"control.mjs","names":["issues: SchemaIssue[]","collectionChildren: SchemaVerificationNode[]","nodes: SchemaVerificationNode[]","children: SchemaTreeNode[]","options: string[]","validatorChildren: SchemaTreeNode[]","optLabels: string[]","previousHashes: { storageHash?: string; profileHash?: string } | undefined","summary: string","mongoFamilyDescriptor: ControlFamilyDescriptor<'mongo', MongoControlFamilyInstance>","migration: { plan(): unknown }","factoryResult: unknown","operations: unknown","mongoTargetDescriptor: MigratableTargetDescriptor<\n 'mongo',\n 'mongo',\n MongoControlFamilyInstance\n>","cachedDeps: MongoRunnerDependencies | undefined"],"sources":["../src/core/schema-diff.ts","../src/core/schema-to-view.ts","../src/core/control-instance.ts","../src/core/control-descriptor.ts","../src/core/mongo-emit.ts","../src/core/mongo-target-descriptor.ts"],"sourcesContent":["import type {\n SchemaIssue,\n SchemaVerificationNode,\n} from '@prisma-next/framework-components/control';\nimport type {\n MongoSchemaCollection,\n MongoSchemaIndex,\n MongoSchemaIR,\n} from '@prisma-next/mongo-schema-ir';\nimport { canonicalize, deepEqual } from '@prisma-next/mongo-schema-ir';\n\nexport function diffMongoSchemas(\n live: MongoSchemaIR,\n expected: MongoSchemaIR,\n strict: boolean,\n): {\n root: SchemaVerificationNode;\n issues: SchemaIssue[];\n counts: { pass: number; warn: number; fail: number; totalNodes: number };\n} {\n const issues: SchemaIssue[] = [];\n const collectionChildren: SchemaVerificationNode[] = [];\n let pass = 0;\n let warn = 0;\n let fail = 0;\n\n const allNames = new Set([...live.collectionNames, ...expected.collectionNames]);\n\n for (const name of [...allNames].sort()) {\n const liveColl = live.collection(name);\n const expectedColl = expected.collection(name);\n\n if (!liveColl && expectedColl) {\n issues.push({\n kind: 'missing_table',\n table: name,\n message: `Collection \"${name}\" is missing from the database`,\n });\n collectionChildren.push({\n status: 'fail',\n kind: 'collection',\n name,\n contractPath: `storage.collections.${name}`,\n code: 'MISSING_COLLECTION',\n message: `Collection \"${name}\" is missing`,\n expected: name,\n actual: null,\n children: [],\n });\n fail++;\n continue;\n }\n\n if (liveColl && !expectedColl) {\n const status = strict ? 'fail' : 'warn';\n issues.push({\n kind: 'extra_table',\n table: name,\n message: `Extra collection \"${name}\" exists in the database but not in the contract`,\n });\n collectionChildren.push({\n status,\n kind: 'collection',\n name,\n contractPath: `storage.collections.${name}`,\n code: 'EXTRA_COLLECTION',\n message: `Extra collection \"${name}\" found`,\n expected: null,\n actual: name,\n children: [],\n });\n if (status === 'fail') fail++;\n else warn++;\n continue;\n }\n\n const lc = liveColl as MongoSchemaCollection;\n const ec = expectedColl as MongoSchemaCollection;\n const indexChildren = diffIndexes(name, lc, ec, strict, issues);\n const validatorChildren = diffValidator(name, lc, ec, strict, issues);\n const optionsChildren = diffOptions(name, lc, ec, strict, issues);\n const children = [...indexChildren, ...validatorChildren, ...optionsChildren];\n\n const worstStatus = children.reduce<'pass' | 'warn' | 'fail'>(\n (s, c) => (c.status === 'fail' ? 'fail' : c.status === 'warn' && s !== 'fail' ? 'warn' : s),\n 'pass',\n );\n\n for (const c of children) {\n if (c.status === 'pass') pass++;\n else if (c.status === 'warn') warn++;\n else fail++;\n }\n\n if (children.length === 0) {\n pass++;\n }\n\n collectionChildren.push({\n status: worstStatus,\n kind: 'collection',\n name,\n contractPath: `storage.collections.${name}`,\n code: worstStatus === 'pass' ? 'MATCH' : 'DRIFT',\n message:\n worstStatus === 'pass' ? `Collection \"${name}\" matches` : `Collection \"${name}\" has drift`,\n expected: name,\n actual: name,\n children,\n });\n }\n\n const rootStatus = fail > 0 ? 'fail' : warn > 0 ? 'warn' : 'pass';\n const totalNodes = pass + warn + fail + collectionChildren.length;\n\n const root: SchemaVerificationNode = {\n status: rootStatus,\n kind: 'root',\n name: 'mongo-schema',\n contractPath: 'storage',\n code: rootStatus === 'pass' ? 'MATCH' : 'DRIFT',\n message: rootStatus === 'pass' ? 'Schema matches' : 'Schema has drift',\n expected: null,\n actual: null,\n children: collectionChildren,\n };\n\n return { root, issues, counts: { pass, warn, fail, totalNodes } };\n}\n\nfunction buildIndexLookupKey(index: MongoSchemaIndex): string {\n const keys = index.keys.map((k) => `${k.field}:${k.direction}`).join(',');\n const opts = [\n index.unique ? 'unique' : '',\n index.sparse ? 'sparse' : '',\n index.expireAfterSeconds != null ? `ttl:${index.expireAfterSeconds}` : '',\n index.partialFilterExpression ? `pfe:${canonicalize(index.partialFilterExpression)}` : '',\n index.wildcardProjection ? `wp:${canonicalize(index.wildcardProjection)}` : '',\n index.collation ? `col:${canonicalize(index.collation)}` : '',\n index.weights ? `wt:${canonicalize(index.weights)}` : '',\n index.default_language ? `dl:${index.default_language}` : '',\n index.language_override ? `lo:${index.language_override}` : '',\n ]\n .filter(Boolean)\n .join(';');\n return opts ? `${keys}|${opts}` : keys;\n}\n\nfunction formatIndexName(index: MongoSchemaIndex): string {\n return index.keys.map((k) => `${k.field}:${k.direction}`).join(', ');\n}\n\nfunction diffIndexes(\n collName: string,\n live: MongoSchemaCollection,\n expected: MongoSchemaCollection,\n strict: boolean,\n issues: SchemaIssue[],\n): SchemaVerificationNode[] {\n const nodes: SchemaVerificationNode[] = [];\n const liveLookup = new Map<string, MongoSchemaIndex>();\n for (const idx of live.indexes) liveLookup.set(buildIndexLookupKey(idx), idx);\n\n const expectedLookup = new Map<string, MongoSchemaIndex>();\n for (const idx of expected.indexes) expectedLookup.set(buildIndexLookupKey(idx), idx);\n\n for (const [key, idx] of expectedLookup) {\n if (liveLookup.has(key)) {\n nodes.push({\n status: 'pass',\n kind: 'index',\n name: formatIndexName(idx),\n contractPath: `storage.collections.${collName}.indexes`,\n code: 'MATCH',\n message: `Index ${formatIndexName(idx)} matches`,\n expected: key,\n actual: key,\n children: [],\n });\n } else {\n issues.push({\n kind: 'index_mismatch',\n table: collName,\n indexOrConstraint: formatIndexName(idx),\n message: `Index ${formatIndexName(idx)} missing on collection \"${collName}\"`,\n });\n nodes.push({\n status: 'fail',\n kind: 'index',\n name: formatIndexName(idx),\n contractPath: `storage.collections.${collName}.indexes`,\n code: 'MISSING_INDEX',\n message: `Index ${formatIndexName(idx)} missing`,\n expected: key,\n actual: null,\n children: [],\n });\n }\n }\n\n for (const [key, idx] of liveLookup) {\n if (!expectedLookup.has(key)) {\n const status = strict ? 'fail' : 'warn';\n issues.push({\n kind: 'extra_index',\n table: collName,\n indexOrConstraint: formatIndexName(idx),\n message: `Extra index ${formatIndexName(idx)} on collection \"${collName}\"`,\n });\n nodes.push({\n status,\n kind: 'index',\n name: formatIndexName(idx),\n contractPath: `storage.collections.${collName}.indexes`,\n code: 'EXTRA_INDEX',\n message: `Extra index ${formatIndexName(idx)}`,\n expected: null,\n actual: key,\n children: [],\n });\n }\n }\n\n return nodes;\n}\n\nfunction diffValidator(\n collName: string,\n live: MongoSchemaCollection,\n expected: MongoSchemaCollection,\n strict: boolean,\n issues: SchemaIssue[],\n): SchemaVerificationNode[] {\n if (!live.validator && !expected.validator) return [];\n\n if (expected.validator && !live.validator) {\n issues.push({\n kind: 'type_missing',\n table: collName,\n message: `Validator missing on collection \"${collName}\"`,\n });\n return [\n {\n status: 'fail',\n kind: 'validator',\n name: 'validator',\n contractPath: `storage.collections.${collName}.validator`,\n code: 'MISSING_VALIDATOR',\n message: 'Validator missing',\n expected: canonicalize(expected.validator.jsonSchema),\n actual: null,\n children: [],\n },\n ];\n }\n\n if (!expected.validator && live.validator) {\n const status = strict ? 'fail' : 'warn';\n issues.push({\n kind: 'extra_validator',\n table: collName,\n message: `Extra validator on collection \"${collName}\"`,\n });\n return [\n {\n status,\n kind: 'validator',\n name: 'validator',\n contractPath: `storage.collections.${collName}.validator`,\n code: 'EXTRA_VALIDATOR',\n message: 'Extra validator found',\n expected: null,\n actual: canonicalize(live.validator.jsonSchema),\n children: [],\n },\n ];\n }\n\n const liveVal = live.validator as NonNullable<typeof live.validator>;\n const expectedVal = expected.validator as NonNullable<typeof expected.validator>;\n const liveSchema = canonicalize(liveVal.jsonSchema);\n const expectedSchema = canonicalize(expectedVal.jsonSchema);\n\n if (\n liveSchema !== expectedSchema ||\n liveVal.validationLevel !== expectedVal.validationLevel ||\n liveVal.validationAction !== expectedVal.validationAction\n ) {\n issues.push({\n kind: 'type_mismatch',\n table: collName,\n expected: expectedSchema,\n actual: liveSchema,\n message: `Validator mismatch on collection \"${collName}\"`,\n });\n return [\n {\n status: 'fail',\n kind: 'validator',\n name: 'validator',\n contractPath: `storage.collections.${collName}.validator`,\n code: 'VALIDATOR_MISMATCH',\n message: 'Validator mismatch',\n expected: {\n jsonSchema: expectedVal.jsonSchema,\n validationLevel: expectedVal.validationLevel,\n validationAction: expectedVal.validationAction,\n },\n actual: {\n jsonSchema: liveVal.jsonSchema,\n validationLevel: liveVal.validationLevel,\n validationAction: liveVal.validationAction,\n },\n children: [],\n },\n ];\n }\n\n return [\n {\n status: 'pass',\n kind: 'validator',\n name: 'validator',\n contractPath: `storage.collections.${collName}.validator`,\n code: 'MATCH',\n message: 'Validator matches',\n expected: expectedSchema,\n actual: liveSchema,\n children: [],\n },\n ];\n}\n\nfunction diffOptions(\n collName: string,\n live: MongoSchemaCollection,\n expected: MongoSchemaCollection,\n strict: boolean,\n issues: SchemaIssue[],\n): SchemaVerificationNode[] {\n if (!live.options && !expected.options) return [];\n\n if (!expected.options && live.options) {\n const status = strict ? 'fail' : 'warn';\n issues.push({\n kind: 'type_mismatch',\n table: collName,\n actual: canonicalize(live.options),\n message: `Extra collection options on \"${collName}\"`,\n });\n return [\n {\n status,\n kind: 'options',\n name: 'options',\n contractPath: `storage.collections.${collName}.options`,\n code: 'EXTRA_OPTIONS',\n message: 'Extra collection options found',\n expected: null,\n actual: live.options,\n children: [],\n },\n ];\n }\n\n if (deepEqual(live.options, expected.options)) {\n return [\n {\n status: 'pass',\n kind: 'options',\n name: 'options',\n contractPath: `storage.collections.${collName}.options`,\n code: 'MATCH',\n message: 'Collection options match',\n expected: canonicalize(expected.options),\n actual: canonicalize(live.options),\n children: [],\n },\n ];\n }\n\n issues.push({\n kind: 'type_mismatch',\n table: collName,\n expected: canonicalize(expected.options),\n actual: canonicalize(live.options),\n message: `Collection options mismatch on \"${collName}\"`,\n });\n return [\n {\n status: 'fail',\n kind: 'options',\n name: 'options',\n contractPath: `storage.collections.${collName}.options`,\n code: 'OPTIONS_MISMATCH',\n message: 'Collection options mismatch',\n expected: expected.options,\n actual: live.options,\n children: [],\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 { introspectSchema } from '@prisma-next/adapter-mongo/control';\nimport type { Contract, ContractMarkerRecord } from '@prisma-next/contract/types';\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_SCHEMA_FAILURE,\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 contractToMongoSchemaIR,\n initMarker,\n readMarker,\n updateMarker,\n} from '@prisma-next/target-mongo/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { Db } from 'mongodb';\nimport { diffMongoSchemas } from './schema-diff';\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<unknown>;\n }): Promise<VerifyDatabaseSchemaResult> {\n const { driver, contract: rawContract, strict, contractPath, configPath } = options;\n const startTime = Date.now();\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 const expectedIR = contractToMongoSchemaIR(contract);\n\n const { root, issues, counts } = diffMongoSchemas(liveIR, expectedIR, strict);\n\n const ok = counts.fail === 0;\n\n return {\n ok,\n ...ifDefined('code', ok ? undefined : VERIFY_CODE_SCHEMA_FAILURE),\n summary: ok ? 'Schema matches contract' : `Schema verification found ${counts.fail} issue(s)`,\n contract: {\n storageHash: contract.storage.storageHash,\n ...ifDefined('profileHash', contract.profileHash),\n },\n target: { expected: contract.target },\n schema: { issues, root, counts },\n meta: {\n ...ifDefined('contractPath', contractPath),\n ...ifDefined('configPath', configPath),\n strict,\n },\n timings: { total: Date.now() - startTime },\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","/**\n * Mongo's in-process implementation of the `emit` capability on\n * `TargetMigrationsCapability`.\n *\n * The CLI's `migration emit` (and `migration plan`'s inline emit) dispatches\n * here for any target that does not implement `resolveDescriptors`. Two\n * authoring shapes are accepted:\n *\n * 1. Class subclass (canonical):\n * class M extends Migration { override plan() { return [...] } }\n * export default M;\n * Migration.run(import.meta.url, M);\n *\n * 2. Factory function returning a Migration-satisfying object:\n * export default () => ({ plan() { return [createCollection(\"users\")] } });\n *\n * We dynamic-import the file (so that any structured errors thrown by\n * `placeholder(...)` propagate as real exceptions to the CLI), dispatch on\n * the export's shape (class subclass vs. callable function), and persist\n * `ops.json` via the framework I/O helper. `Migration.run` already guards\n * itself against firing when the file is imported rather than run as the\n * main module, so this is safe to call from inside the CLI process.\n *\n * Attestation (computing and writing `migrationId` to `manifest.json`) is\n * owned by the framework's `emitMigration` helper, not this capability.\n */\n\nimport { stat } from 'node:fs/promises';\nimport { pathToFileURL } from 'node:url';\nimport {\n errorMigrationFileMissing,\n errorMigrationInvalidDefaultExport,\n errorMigrationPlanNotArray,\n} from '@prisma-next/errors/migration';\nimport type {\n MigrationPlanOperation,\n TargetMigrationsCapability,\n} from '@prisma-next/framework-components/control';\nimport { writeMigrationOps } from '@prisma-next/migration-tools/io';\nimport { Migration } from '@prisma-next/migration-tools/migration';\nimport { join } from 'pathe';\n\nconst MIGRATION_TS_FILE = 'migration.ts';\n\ntype EmitOptions = Parameters<NonNullable<TargetMigrationsCapability['emit']>>[0];\n\n/**\n * Implementation of `TargetMigrationsCapability.emit` for Mongo.\n *\n * Loads `<dir>/migration.ts` and dispatches on the default export's shape:\n * if it is a `Migration` subclass, instantiates it and calls `plan()`;\n * otherwise invokes it as a factory function, validates the returned value\n * has a `plan()` method, and calls it.\n * Writes `ops.json` and returns the operations for the framework helper to\n * render. Attestation (`migrationId` in `manifest.json`) is the framework\n * helper's responsibility; this capability MUST NOT call `attestMigration`\n * itself.\n */\nexport async function mongoEmit(options: EmitOptions): Promise<readonly MigrationPlanOperation[]> {\n const filePath = join(options.dir, MIGRATION_TS_FILE);\n\n try {\n await stat(filePath);\n } catch {\n throw errorMigrationFileMissing(options.dir);\n }\n\n const fileUrl = pathToFileURL(filePath).href;\n const mod = (await import(fileUrl)) as { default?: unknown };\n\n const MigrationExport = mod.default;\n if (typeof MigrationExport !== 'function') {\n throw errorMigrationInvalidDefaultExport(\n options.dir,\n `default export of type ${typeof MigrationExport}`,\n );\n }\n\n let migration: { plan(): unknown };\n if (MigrationExport.prototype instanceof Migration) {\n migration = new (MigrationExport as new () => Migration)();\n } else {\n let factoryResult: unknown;\n try {\n factoryResult = await (MigrationExport as () => unknown | Promise<unknown>)();\n } catch (error) {\n if (error instanceof TypeError && /cannot be invoked without 'new'/i.test(error.message)) {\n throw errorMigrationInvalidDefaultExport(\n options.dir,\n 'a default export that does not extend Migration (from @prisma-next/migration-tools/migration)',\n );\n }\n throw error;\n }\n if (\n typeof factoryResult !== 'object' ||\n factoryResult === null ||\n typeof (factoryResult as { plan?: unknown }).plan !== 'function'\n ) {\n throw errorMigrationInvalidDefaultExport(\n options.dir,\n `factory must return an object with a plan() method; got ${describeValue(factoryResult)}`,\n );\n }\n migration = factoryResult as { plan(): unknown };\n }\n\n const operations: unknown = migration.plan();\n\n if (!Array.isArray(operations)) {\n throw errorMigrationPlanNotArray(options.dir, describeValue(operations));\n }\n\n await writeMigrationOps(options.dir, operations);\n\n return operations;\n}\n\nfunction describeValue(value: unknown): string {\n if (value === null) return 'null';\n return `a value of type ${typeof value}`;\n}\n","import { createMongoRunnerDeps } from '@prisma-next/adapter-mongo/control';\nimport type { Contract } from '@prisma-next/contract/types';\nimport type { MigratableTargetDescriptor } 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';\nimport { mongoEmit } from './mongo-emit';\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 return {\n async execute(options) {\n cachedDeps ??= createMongoRunnerDeps(options.driver);\n const { driver: _, ...runnerOptions } = options;\n const runner = new MongoMigrationRunner(cachedDeps);\n return runner.execute(runnerOptions);\n },\n };\n },\n contractToSchema(contract: Contract | null) {\n return contractToMongoSchemaIR(contract as MongoContract | null);\n },\n emit: mongoEmit,\n },\n create() {\n return { familyId: 'mongo' as const, targetId: 'mongo' as const };\n },\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,30 +1,32 @@
1
1
  {
2
2
  "name": "@prisma-next/family-mongo",
3
- "version": "0.4.0-dev.5",
3
+ "version": "0.4.0-dev.6",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "Mongo family descriptor for Prisma Next",
7
7
  "dependencies": {
8
8
  "mongodb": "^6.16.0",
9
- "@prisma-next/contract": "0.4.0-dev.5",
10
- "@prisma-next/framework-components": "0.4.0-dev.5",
11
- "@prisma-next/emitter": "0.4.0-dev.5",
12
- "@prisma-next/adapter-mongo": "0.4.0-dev.5",
13
- "@prisma-next/migration-tools": "0.4.0-dev.5",
14
- "@prisma-next/mongo-emitter": "0.4.0-dev.5",
15
- "@prisma-next/mongo-contract": "0.4.0-dev.5",
16
- "@prisma-next/mongo-query-ast": "0.4.0-dev.5",
17
- "@prisma-next/mongo-schema-ir": "0.4.0-dev.5",
18
- "@prisma-next/utils": "0.4.0-dev.5",
19
- "@prisma-next/target-mongo": "0.4.0-dev.5"
9
+ "pathe": "^2.0.3",
10
+ "@prisma-next/adapter-mongo": "0.4.0-dev.6",
11
+ "@prisma-next/errors": "0.4.0-dev.6",
12
+ "@prisma-next/emitter": "0.4.0-dev.6",
13
+ "@prisma-next/framework-components": "0.4.0-dev.6",
14
+ "@prisma-next/migration-tools": "0.4.0-dev.6",
15
+ "@prisma-next/mongo-contract": "0.4.0-dev.6",
16
+ "@prisma-next/mongo-emitter": "0.4.0-dev.6",
17
+ "@prisma-next/mongo-query-ast": "0.4.0-dev.6",
18
+ "@prisma-next/mongo-schema-ir": "0.4.0-dev.6",
19
+ "@prisma-next/target-mongo": "0.4.0-dev.6",
20
+ "@prisma-next/contract": "0.4.0-dev.6",
21
+ "@prisma-next/utils": "0.4.0-dev.6"
20
22
  },
21
23
  "devDependencies": {
22
24
  "tsdown": "0.18.4",
23
25
  "typescript": "5.9.3",
24
26
  "vitest": "4.0.17",
25
- "@prisma-next/mongo-contract-ts": "0.4.0-dev.5",
26
- "@prisma-next/tsdown": "0.0.0",
27
- "@prisma-next/tsconfig": "0.0.0"
27
+ "@prisma-next/mongo-contract-ts": "0.4.0-dev.6",
28
+ "@prisma-next/tsconfig": "0.0.0",
29
+ "@prisma-next/tsdown": "0.0.0"
28
30
  },
29
31
  "files": [
30
32
  "dist",
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Mongo's in-process implementation of the `emit` capability on
3
+ * `TargetMigrationsCapability`.
4
+ *
5
+ * The CLI's `migration emit` (and `migration plan`'s inline emit) dispatches
6
+ * here for any target that does not implement `resolveDescriptors`. Two
7
+ * authoring shapes are accepted:
8
+ *
9
+ * 1. Class subclass (canonical):
10
+ * class M extends Migration { override plan() { return [...] } }
11
+ * export default M;
12
+ * Migration.run(import.meta.url, M);
13
+ *
14
+ * 2. Factory function returning a Migration-satisfying object:
15
+ * export default () => ({ plan() { return [createCollection("users")] } });
16
+ *
17
+ * We dynamic-import the file (so that any structured errors thrown by
18
+ * `placeholder(...)` propagate as real exceptions to the CLI), dispatch on
19
+ * the export's shape (class subclass vs. callable function), and persist
20
+ * `ops.json` via the framework I/O helper. `Migration.run` already guards
21
+ * itself against firing when the file is imported rather than run as the
22
+ * main module, so this is safe to call from inside the CLI process.
23
+ *
24
+ * Attestation (computing and writing `migrationId` to `manifest.json`) is
25
+ * owned by the framework's `emitMigration` helper, not this capability.
26
+ */
27
+
28
+ import { stat } from 'node:fs/promises';
29
+ import { pathToFileURL } from 'node:url';
30
+ import {
31
+ errorMigrationFileMissing,
32
+ errorMigrationInvalidDefaultExport,
33
+ errorMigrationPlanNotArray,
34
+ } from '@prisma-next/errors/migration';
35
+ import type {
36
+ MigrationPlanOperation,
37
+ TargetMigrationsCapability,
38
+ } from '@prisma-next/framework-components/control';
39
+ import { writeMigrationOps } from '@prisma-next/migration-tools/io';
40
+ import { Migration } from '@prisma-next/migration-tools/migration';
41
+ import { join } from 'pathe';
42
+
43
+ const MIGRATION_TS_FILE = 'migration.ts';
44
+
45
+ type EmitOptions = Parameters<NonNullable<TargetMigrationsCapability['emit']>>[0];
46
+
47
+ /**
48
+ * Implementation of `TargetMigrationsCapability.emit` for Mongo.
49
+ *
50
+ * Loads `<dir>/migration.ts` and dispatches on the default export's shape:
51
+ * if it is a `Migration` subclass, instantiates it and calls `plan()`;
52
+ * otherwise invokes it as a factory function, validates the returned value
53
+ * has a `plan()` method, and calls it.
54
+ * Writes `ops.json` and returns the operations for the framework helper to
55
+ * render. Attestation (`migrationId` in `manifest.json`) is the framework
56
+ * helper's responsibility; this capability MUST NOT call `attestMigration`
57
+ * itself.
58
+ */
59
+ export async function mongoEmit(options: EmitOptions): Promise<readonly MigrationPlanOperation[]> {
60
+ const filePath = join(options.dir, MIGRATION_TS_FILE);
61
+
62
+ try {
63
+ await stat(filePath);
64
+ } catch {
65
+ throw errorMigrationFileMissing(options.dir);
66
+ }
67
+
68
+ const fileUrl = pathToFileURL(filePath).href;
69
+ const mod = (await import(fileUrl)) as { default?: unknown };
70
+
71
+ const MigrationExport = mod.default;
72
+ if (typeof MigrationExport !== 'function') {
73
+ throw errorMigrationInvalidDefaultExport(
74
+ options.dir,
75
+ `default export of type ${typeof MigrationExport}`,
76
+ );
77
+ }
78
+
79
+ let migration: { plan(): unknown };
80
+ if (MigrationExport.prototype instanceof Migration) {
81
+ migration = new (MigrationExport as new () => Migration)();
82
+ } else {
83
+ let factoryResult: unknown;
84
+ try {
85
+ factoryResult = await (MigrationExport as () => unknown | Promise<unknown>)();
86
+ } catch (error) {
87
+ if (error instanceof TypeError && /cannot be invoked without 'new'/i.test(error.message)) {
88
+ throw errorMigrationInvalidDefaultExport(
89
+ options.dir,
90
+ 'a default export that does not extend Migration (from @prisma-next/migration-tools/migration)',
91
+ );
92
+ }
93
+ throw error;
94
+ }
95
+ if (
96
+ typeof factoryResult !== 'object' ||
97
+ factoryResult === null ||
98
+ typeof (factoryResult as { plan?: unknown }).plan !== 'function'
99
+ ) {
100
+ throw errorMigrationInvalidDefaultExport(
101
+ options.dir,
102
+ `factory must return an object with a plan() method; got ${describeValue(factoryResult)}`,
103
+ );
104
+ }
105
+ migration = factoryResult as { plan(): unknown };
106
+ }
107
+
108
+ const operations: unknown = migration.plan();
109
+
110
+ if (!Array.isArray(operations)) {
111
+ throw errorMigrationPlanNotArray(options.dir, describeValue(operations));
112
+ }
113
+
114
+ await writeMigrationOps(options.dir, operations);
115
+
116
+ return operations;
117
+ }
118
+
119
+ function describeValue(value: unknown): string {
120
+ if (value === null) return 'null';
121
+ return `a value of type ${typeof value}`;
122
+ }
@@ -10,6 +10,7 @@ import {
10
10
  } from '@prisma-next/target-mongo/control';
11
11
  import mongoTargetDescriptorMeta from '@prisma-next/target-mongo/pack';
12
12
  import type { MongoControlFamilyInstance } from './control-instance';
13
+ import { mongoEmit } from './mongo-emit';
13
14
 
14
15
  export const mongoTargetDescriptor: MigratableTargetDescriptor<
15
16
  'mongo',
@@ -37,6 +38,7 @@ export const mongoTargetDescriptor: MigratableTargetDescriptor<
37
38
  contractToSchema(contract: Contract | null) {
38
39
  return contractToMongoSchemaIR(contract as MongoContract | null);
39
40
  },
41
+ emit: mongoEmit,
40
42
  },
41
43
  create() {
42
44
  return { familyId: 'mongo' as const, targetId: 'mongo' as const };