@prisma-next/target-mongo 0.7.0 → 0.8.0-dev.1

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.
Files changed (31) hide show
  1. package/dist/control.d.mts +168 -101
  2. package/dist/control.d.mts.map +1 -1
  3. package/dist/control.mjs +1194 -1138
  4. package/dist/control.mjs.map +1 -1
  5. package/dist/{migration-factories-ZBsWqXt-.mjs → migration-factories-BRBKKZia.mjs} +1 -1
  6. package/dist/{migration-factories-ZBsWqXt-.mjs.map → migration-factories-BRBKKZia.mjs.map} +1 -1
  7. package/dist/migration.d.mts +2 -2
  8. package/dist/migration.mjs +1 -1
  9. package/dist/{op-factory-call-9z5D19cP.d.mts → op-factory-call-BC-llGKt.d.mts} +2 -2
  10. package/dist/{op-factory-call-9z5D19cP.d.mts.map → op-factory-call-BC-llGKt.d.mts.map} +1 -1
  11. package/package.json +23 -21
  12. package/src/core/control-target.ts +185 -0
  13. package/src/core/mongo-planner.ts +1 -1
  14. package/src/core/mongo-runner.ts +3 -45
  15. package/src/core/mongo-target-contract-serializer.ts +73 -0
  16. package/src/core/mongo-target-contract.ts +15 -0
  17. package/src/core/mongo-target-database.ts +82 -0
  18. package/src/core/mongo-target-schema-verifier.ts +54 -0
  19. package/src/exports/control.ts +8 -9
  20. package/dist/schema-verify.d.mts +0 -22
  21. package/dist/schema-verify.d.mts.map +0 -1
  22. package/dist/schema-verify.mjs +0 -2
  23. package/dist/verify-mongo-schema-DlPXaotB.mjs +0 -578
  24. package/dist/verify-mongo-schema-DlPXaotB.mjs.map +0 -1
  25. package/src/core/contract-to-schema.ts +0 -63
  26. package/src/core/ddl-formatter.ts +0 -112
  27. package/src/core/marker-ledger.ts +0 -232
  28. package/src/core/schema-diff.ts +0 -402
  29. package/src/core/schema-verify/canonicalize-introspection.ts +0 -389
  30. package/src/core/schema-verify/verify-mongo-schema.ts +0 -60
  31. package/src/exports/schema-verify.ts +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"migration-factories-ZBsWqXt-.mjs","names":[],"sources":["../src/core/migration-factories.ts"],"sourcesContent":["import type {\n MongoDataTransformCheck,\n MongoDataTransformOperation,\n MongoFilterExpr,\n MongoIndexKey,\n} from '@prisma-next/mongo-query-ast/control';\nimport {\n buildIndexOpId,\n CollModCommand,\n type CollModOptions,\n CreateCollectionCommand,\n type CreateCollectionOptions,\n CreateIndexCommand,\n type CreateIndexOptions,\n DropCollectionCommand,\n DropIndexCommand,\n defaultMongoIndexName,\n keysToKeySpec,\n ListCollectionsCommand,\n ListIndexesCommand,\n MongoAndExpr,\n MongoExistsExpr,\n MongoFieldFilter,\n type MongoMigrationPlanOperation,\n} from '@prisma-next/mongo-query-ast/control';\nimport type { MongoQueryPlan } from '@prisma-next/mongo-query-ast/execution';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { CollModMeta } from './op-factory-call';\n\ninterface Buildable {\n build(): MongoQueryPlan;\n}\n\nfunction isBuildable(value: unknown): value is Buildable {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'build' in value &&\n typeof (value as { build: unknown }).build === 'function'\n );\n}\n\nfunction resolveQuery(value: MongoQueryPlan | Buildable): MongoQueryPlan {\n return isBuildable(value) ? value.build() : value;\n}\n\n// Every MongoDB document carries `_id`, so `exists('_id')` is equivalent to\n// \"match all\". The filter AST has no identity/always-true expression.\nconst MATCH_ALL_FILTER: MongoFilterExpr = MongoExistsExpr.exists('_id');\n\nexport function dataTransform(\n name: string,\n options: {\n /**\n * Optional opt-in routing identity. Presence opts the transform into\n * invariant-aware routing; absence means it is path-dependent and\n * not referenceable from refs.\n */\n invariantId?: string;\n check?: {\n source: () => MongoQueryPlan | Buildable;\n filter?: MongoFilterExpr;\n expect?: 'exists' | 'notExists';\n description?: string;\n };\n run: () => MongoQueryPlan | Buildable;\n },\n): MongoDataTransformOperation {\n let precheck: readonly MongoDataTransformCheck[] = [];\n let postcheck: readonly MongoDataTransformCheck[] = [];\n\n if (options.check) {\n const source = resolveQuery(options.check.source());\n const filter = options.check.filter ?? MATCH_ALL_FILTER;\n const description = options.check.description ?? `Check for data transform: ${name}`;\n const precheckExpect = options.check.expect ?? 'exists';\n const postcheckExpect: 'exists' | 'notExists' =\n precheckExpect === 'exists' ? 'notExists' : 'exists';\n\n precheck = [{ description, source, filter, expect: precheckExpect }];\n postcheck = [{ description, source, filter, expect: postcheckExpect }];\n }\n\n const run: MongoQueryPlan[] = [resolveQuery(options.run())];\n\n return {\n id: `data_transform.${name}`,\n label: `Data transform: ${name}`,\n operationClass: 'data',\n name,\n ...ifDefined('invariantId', options.invariantId),\n precheck,\n run,\n postcheck,\n };\n}\n\nfunction formatKeys(keys: ReadonlyArray<MongoIndexKey>): string {\n return keys.map((k) => `${k.field}:${k.direction}`).join(', ');\n}\n\nfunction isTextIndex(keys: ReadonlyArray<MongoIndexKey>): boolean {\n return keys.some((k) => k.direction === 'text');\n}\n\nfunction keyFilter(keys: ReadonlyArray<MongoIndexKey>) {\n return isTextIndex(keys)\n ? MongoFieldFilter.eq('key._fts', 'text')\n : MongoFieldFilter.eq('key', keysToKeySpec(keys));\n}\n\nexport function createIndex(\n collection: string,\n keys: ReadonlyArray<MongoIndexKey>,\n options?: CreateIndexOptions,\n): MongoMigrationPlanOperation {\n const name = defaultMongoIndexName(keys);\n const filter = keyFilter(keys);\n const fullFilter = options?.unique\n ? MongoAndExpr.of([filter, MongoFieldFilter.eq('unique', true)])\n : filter;\n\n return {\n id: buildIndexOpId('create', collection, keys),\n label: `Create index on ${collection} (${formatKeys(keys)})`,\n operationClass: 'additive',\n precheck: [\n {\n description: `index does not already exist on ${collection}`,\n source: new ListIndexesCommand(collection),\n filter,\n expect: 'notExists',\n },\n ],\n execute: [\n {\n description: `create index on ${collection}`,\n command: new CreateIndexCommand(collection, keys, {\n ...options,\n unique: options?.unique ?? undefined,\n name,\n }),\n },\n ],\n postcheck: [\n {\n description: `index exists on ${collection}`,\n source: new ListIndexesCommand(collection),\n filter: fullFilter,\n expect: 'exists',\n },\n ],\n };\n}\n\nexport function dropIndex(\n collection: string,\n keys: ReadonlyArray<MongoIndexKey>,\n): MongoMigrationPlanOperation {\n const indexName = defaultMongoIndexName(keys);\n const filter = keyFilter(keys);\n\n return {\n id: buildIndexOpId('drop', collection, keys),\n label: `Drop index on ${collection} (${formatKeys(keys)})`,\n operationClass: 'destructive',\n precheck: [\n {\n description: `index exists on ${collection}`,\n source: new ListIndexesCommand(collection),\n filter,\n expect: 'exists',\n },\n ],\n execute: [\n {\n description: `drop index on ${collection}`,\n command: new DropIndexCommand(collection, indexName),\n },\n ],\n postcheck: [\n {\n description: `index no longer exists on ${collection}`,\n source: new ListIndexesCommand(collection),\n filter,\n expect: 'notExists',\n },\n ],\n };\n}\n\nexport function createCollection(\n collection: string,\n options?: CreateCollectionOptions,\n): MongoMigrationPlanOperation {\n return {\n id: `collection.${collection}.create`,\n label: `Create collection ${collection}`,\n operationClass: 'additive',\n precheck: [\n {\n description: `collection ${collection} does not exist`,\n source: new ListCollectionsCommand(),\n filter: MongoFieldFilter.eq('name', collection),\n expect: 'notExists',\n },\n ],\n execute: [\n {\n description: `create collection ${collection}`,\n command: new CreateCollectionCommand(collection, options),\n },\n ],\n postcheck: [],\n };\n}\n\nexport function dropCollection(collection: string): MongoMigrationPlanOperation {\n return {\n id: `collection.${collection}.drop`,\n label: `Drop collection ${collection}`,\n operationClass: 'destructive',\n precheck: [],\n execute: [\n {\n description: `drop collection ${collection}`,\n command: new DropCollectionCommand(collection),\n },\n ],\n postcheck: [],\n };\n}\n\nexport function setValidation(\n collection: string,\n schema: Record<string, unknown>,\n options?: { validationLevel?: 'strict' | 'moderate'; validationAction?: 'error' | 'warn' },\n): MongoMigrationPlanOperation {\n return {\n id: `collection.${collection}.setValidation`,\n label: `Set validation on ${collection}`,\n operationClass: 'destructive',\n precheck: [],\n execute: [\n {\n description: `set validation on ${collection}`,\n command: new CollModCommand(collection, {\n validator: { $jsonSchema: schema },\n validationLevel: options?.validationLevel,\n validationAction: options?.validationAction,\n }),\n },\n ],\n postcheck: [],\n };\n}\n\nexport function collMod(\n collection: string,\n options: CollModOptions,\n meta?: CollModMeta,\n): MongoMigrationPlanOperation {\n const hasValidator = options.validator != null && Object.keys(options.validator).length > 0;\n\n return {\n id: meta?.id ?? `collection.${collection}.collMod`,\n label: meta?.label ?? `Modify collection ${collection}`,\n operationClass: meta?.operationClass ?? 'destructive',\n precheck:\n options.validator != null\n ? [\n {\n description: `collection ${collection} exists`,\n source: new ListCollectionsCommand(),\n filter: MongoFieldFilter.eq('name', collection),\n expect: 'exists' as const,\n },\n ]\n : [],\n execute: [\n {\n description: `modify ${collection}`,\n command: new CollModCommand(collection, options),\n },\n ],\n postcheck: hasValidator\n ? [\n {\n description: `validator applied on ${collection}`,\n source: new ListCollectionsCommand(),\n filter: MongoAndExpr.of([\n MongoFieldFilter.eq('name', collection),\n ...(options.validationLevel\n ? [MongoFieldFilter.eq('options.validationLevel', options.validationLevel)]\n : []),\n ...(options.validationAction\n ? [MongoFieldFilter.eq('options.validationAction', options.validationAction)]\n : []),\n ]),\n expect: 'exists' as const,\n },\n ]\n : [],\n };\n}\n\nexport function validatedCollection(\n name: string,\n schema: Record<string, unknown>,\n indexes: ReadonlyArray<{ keys: MongoIndexKey[]; unique?: boolean }>,\n): MongoMigrationPlanOperation[] {\n return [\n createCollection(name, {\n validator: { $jsonSchema: schema },\n validationLevel: 'strict',\n validationAction: 'error',\n }),\n ...indexes.map((idx) => createIndex(name, idx.keys, { unique: idx.unique })),\n ];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"migration-factories-BRBKKZia.mjs","names":[],"sources":["../src/core/migration-factories.ts"],"sourcesContent":["import type {\n MongoDataTransformCheck,\n MongoDataTransformOperation,\n MongoFilterExpr,\n MongoIndexKey,\n} from '@prisma-next/mongo-query-ast/control';\nimport {\n buildIndexOpId,\n CollModCommand,\n type CollModOptions,\n CreateCollectionCommand,\n type CreateCollectionOptions,\n CreateIndexCommand,\n type CreateIndexOptions,\n DropCollectionCommand,\n DropIndexCommand,\n defaultMongoIndexName,\n keysToKeySpec,\n ListCollectionsCommand,\n ListIndexesCommand,\n MongoAndExpr,\n MongoExistsExpr,\n MongoFieldFilter,\n type MongoMigrationPlanOperation,\n} from '@prisma-next/mongo-query-ast/control';\nimport type { MongoQueryPlan } from '@prisma-next/mongo-query-ast/execution';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { CollModMeta } from './op-factory-call';\n\ninterface Buildable {\n build(): MongoQueryPlan;\n}\n\nfunction isBuildable(value: unknown): value is Buildable {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'build' in value &&\n typeof (value as { build: unknown }).build === 'function'\n );\n}\n\nfunction resolveQuery(value: MongoQueryPlan | Buildable): MongoQueryPlan {\n return isBuildable(value) ? value.build() : value;\n}\n\n// Every MongoDB document carries `_id`, so `exists('_id')` is equivalent to\n// \"match all\". The filter AST has no identity/always-true expression.\nconst MATCH_ALL_FILTER: MongoFilterExpr = MongoExistsExpr.exists('_id');\n\nexport function dataTransform(\n name: string,\n options: {\n /**\n * Optional opt-in routing identity. Presence opts the transform into\n * invariant-aware routing; absence means it is path-dependent and\n * not referenceable from refs.\n */\n invariantId?: string;\n check?: {\n source: () => MongoQueryPlan | Buildable;\n filter?: MongoFilterExpr;\n expect?: 'exists' | 'notExists';\n description?: string;\n };\n run: () => MongoQueryPlan | Buildable;\n },\n): MongoDataTransformOperation {\n let precheck: readonly MongoDataTransformCheck[] = [];\n let postcheck: readonly MongoDataTransformCheck[] = [];\n\n if (options.check) {\n const source = resolveQuery(options.check.source());\n const filter = options.check.filter ?? MATCH_ALL_FILTER;\n const description = options.check.description ?? `Check for data transform: ${name}`;\n const precheckExpect = options.check.expect ?? 'exists';\n const postcheckExpect: 'exists' | 'notExists' =\n precheckExpect === 'exists' ? 'notExists' : 'exists';\n\n precheck = [{ description, source, filter, expect: precheckExpect }];\n postcheck = [{ description, source, filter, expect: postcheckExpect }];\n }\n\n const run: MongoQueryPlan[] = [resolveQuery(options.run())];\n\n return {\n id: `data_transform.${name}`,\n label: `Data transform: ${name}`,\n operationClass: 'data',\n name,\n ...ifDefined('invariantId', options.invariantId),\n precheck,\n run,\n postcheck,\n };\n}\n\nfunction formatKeys(keys: ReadonlyArray<MongoIndexKey>): string {\n return keys.map((k) => `${k.field}:${k.direction}`).join(', ');\n}\n\nfunction isTextIndex(keys: ReadonlyArray<MongoIndexKey>): boolean {\n return keys.some((k) => k.direction === 'text');\n}\n\nfunction keyFilter(keys: ReadonlyArray<MongoIndexKey>) {\n return isTextIndex(keys)\n ? MongoFieldFilter.eq('key._fts', 'text')\n : MongoFieldFilter.eq('key', keysToKeySpec(keys));\n}\n\nexport function createIndex(\n collection: string,\n keys: ReadonlyArray<MongoIndexKey>,\n options?: CreateIndexOptions,\n): MongoMigrationPlanOperation {\n const name = defaultMongoIndexName(keys);\n const filter = keyFilter(keys);\n const fullFilter = options?.unique\n ? MongoAndExpr.of([filter, MongoFieldFilter.eq('unique', true)])\n : filter;\n\n return {\n id: buildIndexOpId('create', collection, keys),\n label: `Create index on ${collection} (${formatKeys(keys)})`,\n operationClass: 'additive',\n precheck: [\n {\n description: `index does not already exist on ${collection}`,\n source: new ListIndexesCommand(collection),\n filter,\n expect: 'notExists',\n },\n ],\n execute: [\n {\n description: `create index on ${collection}`,\n command: new CreateIndexCommand(collection, keys, {\n ...options,\n unique: options?.unique ?? undefined,\n name,\n }),\n },\n ],\n postcheck: [\n {\n description: `index exists on ${collection}`,\n source: new ListIndexesCommand(collection),\n filter: fullFilter,\n expect: 'exists',\n },\n ],\n };\n}\n\nexport function dropIndex(\n collection: string,\n keys: ReadonlyArray<MongoIndexKey>,\n): MongoMigrationPlanOperation {\n const indexName = defaultMongoIndexName(keys);\n const filter = keyFilter(keys);\n\n return {\n id: buildIndexOpId('drop', collection, keys),\n label: `Drop index on ${collection} (${formatKeys(keys)})`,\n operationClass: 'destructive',\n precheck: [\n {\n description: `index exists on ${collection}`,\n source: new ListIndexesCommand(collection),\n filter,\n expect: 'exists',\n },\n ],\n execute: [\n {\n description: `drop index on ${collection}`,\n command: new DropIndexCommand(collection, indexName),\n },\n ],\n postcheck: [\n {\n description: `index no longer exists on ${collection}`,\n source: new ListIndexesCommand(collection),\n filter,\n expect: 'notExists',\n },\n ],\n };\n}\n\nexport function createCollection(\n collection: string,\n options?: CreateCollectionOptions,\n): MongoMigrationPlanOperation {\n return {\n id: `collection.${collection}.create`,\n label: `Create collection ${collection}`,\n operationClass: 'additive',\n precheck: [\n {\n description: `collection ${collection} does not exist`,\n source: new ListCollectionsCommand(),\n filter: MongoFieldFilter.eq('name', collection),\n expect: 'notExists',\n },\n ],\n execute: [\n {\n description: `create collection ${collection}`,\n command: new CreateCollectionCommand(collection, options),\n },\n ],\n postcheck: [],\n };\n}\n\nexport function dropCollection(collection: string): MongoMigrationPlanOperation {\n return {\n id: `collection.${collection}.drop`,\n label: `Drop collection ${collection}`,\n operationClass: 'destructive',\n precheck: [],\n execute: [\n {\n description: `drop collection ${collection}`,\n command: new DropCollectionCommand(collection),\n },\n ],\n postcheck: [],\n };\n}\n\nexport function setValidation(\n collection: string,\n schema: Record<string, unknown>,\n options?: { validationLevel?: 'strict' | 'moderate'; validationAction?: 'error' | 'warn' },\n): MongoMigrationPlanOperation {\n return {\n id: `collection.${collection}.setValidation`,\n label: `Set validation on ${collection}`,\n operationClass: 'destructive',\n precheck: [],\n execute: [\n {\n description: `set validation on ${collection}`,\n command: new CollModCommand(collection, {\n validator: { $jsonSchema: schema },\n validationLevel: options?.validationLevel,\n validationAction: options?.validationAction,\n }),\n },\n ],\n postcheck: [],\n };\n}\n\nexport function collMod(\n collection: string,\n options: CollModOptions,\n meta?: CollModMeta,\n): MongoMigrationPlanOperation {\n const hasValidator = options.validator != null && Object.keys(options.validator).length > 0;\n\n return {\n id: meta?.id ?? `collection.${collection}.collMod`,\n label: meta?.label ?? `Modify collection ${collection}`,\n operationClass: meta?.operationClass ?? 'destructive',\n precheck:\n options.validator != null\n ? [\n {\n description: `collection ${collection} exists`,\n source: new ListCollectionsCommand(),\n filter: MongoFieldFilter.eq('name', collection),\n expect: 'exists' as const,\n },\n ]\n : [],\n execute: [\n {\n description: `modify ${collection}`,\n command: new CollModCommand(collection, options),\n },\n ],\n postcheck: hasValidator\n ? [\n {\n description: `validator applied on ${collection}`,\n source: new ListCollectionsCommand(),\n filter: MongoAndExpr.of([\n MongoFieldFilter.eq('name', collection),\n ...(options.validationLevel\n ? [MongoFieldFilter.eq('options.validationLevel', options.validationLevel)]\n : []),\n ...(options.validationAction\n ? [MongoFieldFilter.eq('options.validationAction', options.validationAction)]\n : []),\n ]),\n expect: 'exists' as const,\n },\n ]\n : [],\n };\n}\n\nexport function validatedCollection(\n name: string,\n schema: Record<string, unknown>,\n indexes: ReadonlyArray<{ keys: MongoIndexKey[]; unique?: boolean }>,\n): MongoMigrationPlanOperation[] {\n return [\n createCollection(name, {\n validator: { $jsonSchema: schema },\n validationLevel: 'strict',\n validationAction: 'error',\n }),\n ...indexes.map((idx) => createIndex(name, idx.keys, { unique: idx.unique })),\n ];\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { n as CollModMeta } from "./op-factory-call-9z5D19cP.mjs";
2
- import { MongoQueryPlan } from "@prisma-next/mongo-query-ast/execution";
1
+ import { n as CollModMeta } from "./op-factory-call-BC-llGKt.mjs";
3
2
  import { CollModOptions, CreateCollectionOptions, CreateIndexOptions, MongoDataTransformOperation, MongoFilterExpr, MongoIndexKey, MongoMigrationPlanOperation } from "@prisma-next/mongo-query-ast/control";
3
+ import { MongoQueryPlan } from "@prisma-next/mongo-query-ast/execution";
4
4
  import { placeholder } from "@prisma-next/errors/migration";
5
5
 
6
6
  //#region src/core/migration-factories.d.ts
@@ -1,3 +1,3 @@
1
- import { a as dropCollection, c as validatedCollection, i as dataTransform, n as createCollection, o as dropIndex, r as createIndex, s as setValidation, t as collMod } from "./migration-factories-ZBsWqXt-.mjs";
1
+ import { a as dropCollection, c as validatedCollection, i as dataTransform, n as createCollection, o as dropIndex, r as createIndex, s as setValidation, t as collMod } from "./migration-factories-BRBKKZia.mjs";
2
2
  import { placeholder } from "@prisma-next/errors/migration";
3
3
  export { collMod, createCollection, createIndex, dataTransform, dropCollection, dropIndex, placeholder, setValidation, validatedCollection };
@@ -1,6 +1,6 @@
1
1
  import { MongoSchemaCollection, MongoSchemaIndex } from "@prisma-next/mongo-schema-ir";
2
- import { CollModOptions, CreateCollectionOptions, CreateIndexOptions, MongoIndexKey, MongoMigrationPlanOperation } from "@prisma-next/mongo-query-ast/control";
3
2
  import { ImportRequirement, TsExpression } from "@prisma-next/ts-render";
3
+ import { CollModOptions, CreateCollectionOptions, CreateIndexOptions, MongoIndexKey, MongoMigrationPlanOperation } from "@prisma-next/mongo-query-ast/control";
4
4
  import { MigrationOperationClass, OpFactoryCall } from "@prisma-next/framework-components/control";
5
5
 
6
6
  //#region src/core/op-factory-call.d.ts
@@ -73,4 +73,4 @@ declare function schemaIndexToCreateIndexOptions(index: MongoSchemaIndex): Creat
73
73
  declare function schemaCollectionToCreateCollectionOptions(coll: MongoSchemaCollection): CreateCollectionOptions | undefined;
74
74
  //#endregion
75
75
  export { DropCollectionCall as a, schemaCollectionToCreateCollectionOptions as c, CreateIndexCall as i, schemaIndexToCreateIndexOptions as l, CollModMeta as n, DropIndexCall as o, CreateCollectionCall as r, OpFactoryCall$1 as s, CollModCall as t };
76
- //# sourceMappingURL=op-factory-call-9z5D19cP.d.mts.map
76
+ //# sourceMappingURL=op-factory-call-BC-llGKt.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"op-factory-call-9z5D19cP.d.mts","names":[],"sources":["../src/core/op-factory-call.ts"],"mappings":";;;;;;UA6CiB,WAAA;EAAA,SACN,EAAA;EAAA,SACA,KAAA;EAAA,SACA,cAAA,GAAiB,uBAAA;AAAA;AAAA,uBAKb,iBAAA,SAA0B,YAAA,YAAwB,aAAA;EAAA,kBAC7C,WAAA;EAAA,kBACA,cAAA,EAAgB,uBAAA;EAAA,kBAChB,KAAA;EAAA,SACT,IAAA,CAAA,GAAQ,2BAAA;EAEjB,kBAAA,CAAA,YAA+B,iBAAA;EAAA,UAIrB,MAAA,CAAA;AAAA;AAAA,cASC,eAAA,SAAwB,iBAAA;EAAA,SAC1B,WAAA;EAAA,SACA,cAAA;EAAA,SACA,UAAA;EAAA,SACA,IAAA,EAAM,aAAA,CAAc,aAAA;EAAA,SACpB,OAAA,EAAS,kBAAA;EAAA,SACT,KAAA;cAGP,UAAA,UACA,IAAA,EAAM,aAAA,CAAc,aAAA,GACpB,OAAA,GAAU,kBAAA;EAUZ,IAAA,CAAA,GAAQ,2BAAA;EAIR,gBAAA,CAAA;AAAA;AAAA,cAOW,aAAA,SAAsB,iBAAA;EAAA,SACxB,WAAA;EAAA,SACA,cAAA;EAAA,SACA,UAAA;EAAA,SACA,IAAA,EAAM,aAAA,CAAc,aAAA;EAAA,SACpB,KAAA;cAEG,UAAA,UAAoB,IAAA,EAAM,aAAA,CAAc,aAAA;EAQpD,IAAA,CAAA,GAAQ,2BAAA;EAIR,gBAAA,CAAA;AAAA;AAAA,cAKW,oBAAA,SAA6B,iBAAA;EAAA,SAC/B,WAAA;EAAA,SACA,cAAA;EAAA,SACA,UAAA;EAAA,SACA,OAAA,EAAS,uBAAA;EAAA,SACT,KAAA;cAEG,UAAA,UAAoB,OAAA,GAAU,uBAAA;EAQ1C,IAAA,CAAA,GAAQ,2BAAA;EAIR,gBAAA,CAAA;AAAA;AAAA,cAOW,kBAAA,SAA2B,iBAAA;EAAA,SAC7B,WAAA;EAAA,SACA,cAAA;EAAA,SACA,UAAA;EAAA,SACA,KAAA;cAEG,UAAA;EAOZ,IAAA,CAAA,GAAQ,2BAAA;EAIR,gBAAA,CAAA;AAAA;AAAA,cAKW,WAAA,SAAoB,iBAAA;EAAA,SACtB,WAAA;EAAA,SACA,UAAA;EAAA,SACA,OAAA,EAAS,cAAA;EAAA,SACT,IAAA,EAAM,WAAA;EAAA,SACN,cAAA,EAAgB,uBAAA;EAAA,SAChB,KAAA;cAEG,UAAA,UAAoB,OAAA,EAAS,cAAA,EAAgB,IAAA,GAAO,WAAA;EAUhE,IAAA,CAAA,GAAQ,2BAAA;EAIR,gBAAA,CAAA;AAAA;AAAA,KAOU,eAAA,GACR,eAAA,GACA,aAAA,GACA,oBAAA,GACA,kBAAA,GACA,WAAA;AAAA,iBAEY,+BAAA,CAAgC,KAAA,EAAO,gBAAA,GAAmB,kBAAA;AAAA,iBAc1D,yCAAA,CACd,IAAA,EAAM,qBAAA,GACL,uBAAA"}
1
+ {"version":3,"file":"op-factory-call-BC-llGKt.d.mts","names":[],"sources":["../src/core/op-factory-call.ts"],"mappings":";;;;;;UA6CiB,WAAA;EAAA,SACN,EAAA;EAAA,SACA,KAAA;EAAA,SACA,cAAA,GAAiB,uBAAA;AAAA;AAAA,uBAKb,iBAAA,SAA0B,YAAA,YAAwB,aAAA;EAAA,kBAC7C,WAAA;EAAA,kBACA,cAAA,EAAgB,uBAAA;EAAA,kBAChB,KAAA;EAAA,SACT,IAAA,CAAA,GAAQ,2BAAA;EAEjB,kBAAA,CAAA,YAA+B,iBAAA;EAAA,UAIrB,MAAA,CAAA;AAAA;AAAA,cASC,eAAA,SAAwB,iBAAA;EAAA,SAC1B,WAAA;EAAA,SACA,cAAA;EAAA,SACA,UAAA;EAAA,SACA,IAAA,EAAM,aAAA,CAAc,aAAA;EAAA,SACpB,OAAA,EAAS,kBAAA;EAAA,SACT,KAAA;cAGP,UAAA,UACA,IAAA,EAAM,aAAA,CAAc,aAAA,GACpB,OAAA,GAAU,kBAAA;EAUZ,IAAA,CAAA,GAAQ,2BAAA;EAIR,gBAAA,CAAA;AAAA;AAAA,cAOW,aAAA,SAAsB,iBAAA;EAAA,SACxB,WAAA;EAAA,SACA,cAAA;EAAA,SACA,UAAA;EAAA,SACA,IAAA,EAAM,aAAA,CAAc,aAAA;EAAA,SACpB,KAAA;cAEG,UAAA,UAAoB,IAAA,EAAM,aAAA,CAAc,aAAA;EAQpD,IAAA,CAAA,GAAQ,2BAAA;EAIR,gBAAA,CAAA;AAAA;AAAA,cAKW,oBAAA,SAA6B,iBAAA;EAAA,SAC/B,WAAA;EAAA,SACA,cAAA;EAAA,SACA,UAAA;EAAA,SACA,OAAA,EAAS,uBAAA;EAAA,SACT,KAAA;cAEG,UAAA,UAAoB,OAAA,GAAU,uBAAA;EAQ1C,IAAA,CAAA,GAAQ,2BAAA;EAIR,gBAAA,CAAA;AAAA;AAAA,cAOW,kBAAA,SAA2B,iBAAA;EAAA,SAC7B,WAAA;EAAA,SACA,cAAA;EAAA,SACA,UAAA;EAAA,SACA,KAAA;cAEG,UAAA;EAOZ,IAAA,CAAA,GAAQ,2BAAA;EAIR,gBAAA,CAAA;AAAA;AAAA,cAKW,WAAA,SAAoB,iBAAA;EAAA,SACtB,WAAA;EAAA,SACA,UAAA;EAAA,SACA,OAAA,EAAS,cAAA;EAAA,SACT,IAAA,EAAM,WAAA;EAAA,SACN,cAAA,EAAgB,uBAAA;EAAA,SAChB,KAAA;cAEG,UAAA,UAAoB,OAAA,EAAS,cAAA,EAAgB,IAAA,GAAO,WAAA;EAUhE,IAAA,CAAA,GAAQ,2BAAA;EAIR,gBAAA,CAAA;AAAA;AAAA,KAOU,eAAA,GACR,eAAA,GACA,aAAA,GACA,oBAAA,GACA,kBAAA,GACA,WAAA;AAAA,iBAEY,+BAAA,CAAgC,KAAA,EAAO,gBAAA,GAAmB,kBAAA;AAAA,iBAc1D,yCAAA,CACd,IAAA,EAAM,qBAAA,GACL,uBAAA"}
package/package.json CHANGED
@@ -1,35 +1,40 @@
1
1
  {
2
2
  "name": "@prisma-next/target-mongo",
3
- "version": "0.7.0",
3
+ "version": "0.8.0-dev.1",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "description": "MongoDB target pack for Prisma Next",
8
8
  "dependencies": {
9
+ "@prisma-next/adapter-mongo": "0.8.0-dev.1",
10
+ "@prisma-next/contract": "0.8.0-dev.1",
11
+ "@prisma-next/driver-mongo": "0.8.0-dev.1",
12
+ "@prisma-next/errors": "0.8.0-dev.1",
13
+ "@prisma-next/family-mongo": "0.8.0-dev.1",
14
+ "@prisma-next/framework-components": "0.8.0-dev.1",
15
+ "@prisma-next/migration-tools": "0.8.0-dev.1",
16
+ "@prisma-next/ts-render": "0.8.0-dev.1",
17
+ "@prisma-next/mongo-codec": "0.8.0-dev.1",
18
+ "@prisma-next/mongo-contract": "0.8.0-dev.1",
19
+ "@prisma-next/mongo-lowering": "0.8.0-dev.1",
20
+ "@prisma-next/mongo-query-ast": "0.8.0-dev.1",
21
+ "@prisma-next/mongo-schema-ir": "0.8.0-dev.1",
22
+ "@prisma-next/mongo-value": "0.8.0-dev.1",
23
+ "@prisma-next/utils": "0.8.0-dev.1",
9
24
  "arktype": "^2.1.29",
10
- "mongodb": "^6.16.0",
11
- "@prisma-next/contract": "0.7.0",
12
- "@prisma-next/framework-components": "0.7.0",
13
- "@prisma-next/errors": "0.7.0",
14
- "@prisma-next/migration-tools": "0.7.0",
15
- "@prisma-next/ts-render": "0.7.0",
16
- "@prisma-next/mongo-codec": "0.7.0",
17
- "@prisma-next/mongo-contract": "0.7.0",
18
- "@prisma-next/mongo-lowering": "0.7.0",
19
- "@prisma-next/mongo-query-ast": "0.7.0",
20
- "@prisma-next/mongo-schema-ir": "0.7.0",
21
- "@prisma-next/mongo-value": "0.7.0",
22
- "@prisma-next/utils": "0.7.0"
25
+ "mongodb": "^6.16.0"
23
26
  },
24
27
  "devDependencies": {
28
+ "@prisma-next/mongo-contract-psl": "0.8.0-dev.1",
29
+ "@prisma-next/psl-parser": "0.8.0-dev.1",
30
+ "@prisma-next/test-utils": "0.8.0-dev.1",
31
+ "@prisma-next/tsconfig": "0.8.0-dev.1",
32
+ "@prisma-next/tsdown": "0.8.0-dev.1",
25
33
  "mongodb-memory-server": "11.0.1",
26
34
  "pathe": "^2.0.3",
27
35
  "tsdown": "0.22.0",
28
36
  "typescript": "5.9.3",
29
- "vitest": "4.1.5",
30
- "@prisma-next/test-utils": "0.7.0",
31
- "@prisma-next/tsconfig": "0.7.0",
32
- "@prisma-next/tsdown": "0.7.0"
37
+ "vitest": "4.1.5"
33
38
  },
34
39
  "files": [
35
40
  "dist",
@@ -41,7 +46,6 @@
41
46
  "./migration": "./dist/migration.mjs",
42
47
  "./pack": "./dist/pack.mjs",
43
48
  "./runtime": "./dist/runtime.mjs",
44
- "./schema-verify": "./dist/schema-verify.mjs",
45
49
  "./package.json": "./package.json"
46
50
  },
47
51
  "repository": {
@@ -49,8 +53,6 @@
49
53
  "url": "https://github.com/prisma/prisma-next.git",
50
54
  "directory": "packages/3-mongo-target/1-mongo-target"
51
55
  },
52
- "main": "./dist/pack.mjs",
53
- "module": "./dist/pack.mjs",
54
56
  "types": "./dist/pack.d.mts",
55
57
  "prismaNext": {
56
58
  "minServerVersion": "6.0"
@@ -0,0 +1,185 @@
1
+ import {
2
+ createMongoRunnerDeps,
3
+ extractDb,
4
+ type MongoRunnerDependencies,
5
+ } from '@prisma-next/adapter-mongo/control';
6
+ import type { Contract } from '@prisma-next/contract/types';
7
+ import { MongoDriverImpl } from '@prisma-next/driver-mongo';
8
+ import type {
9
+ MongoControlFamilyInstance,
10
+ MongoControlTargetDescriptor,
11
+ } from '@prisma-next/family-mongo/control';
12
+ import { contractToMongoSchemaIR } from '@prisma-next/family-mongo/control';
13
+ import type {
14
+ MigrationRunner,
15
+ MigrationRunnerResult,
16
+ MigrationRunnerSuccessValue,
17
+ MultiSpaceCapableRunner,
18
+ MultiSpaceRunnerFailure,
19
+ MultiSpaceRunnerPerSpaceOptions,
20
+ MultiSpaceRunnerResult,
21
+ } from '@prisma-next/framework-components/control';
22
+ import {
23
+ type ContractSpaceMember,
24
+ projectSchemaToSpace,
25
+ } from '@prisma-next/migration-tools/aggregate';
26
+ import type { MongoContract } from '@prisma-next/mongo-contract';
27
+ import type { MongoSchemaCollection } from '@prisma-next/mongo-schema-ir';
28
+ import { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';
29
+ import { notOk, ok } from '@prisma-next/utils/result';
30
+ import { mongoTargetDescriptorMeta } from './descriptor-meta';
31
+ import { MongoMigrationPlanner } from './mongo-planner';
32
+ import { MongoMigrationRunner, type MongoMigrationRunnerExecuteOptions } from './mongo-runner';
33
+ import type { MongoTargetContract } from './mongo-target-contract';
34
+ import { MongoTargetContractSerializer } from './mongo-target-contract-serializer';
35
+ import { MongoTargetSchemaVerifier } from './mongo-target-schema-verifier';
36
+
37
+ export type { MongoControlTargetDescriptor };
38
+
39
+ /**
40
+ * `migration.ts` default-exports a `Migration` subclass whose `operations`
41
+ * getter returns the ordered list of operations and whose `describe()`
42
+ * returns the manifest identity metadata. `MongoMigrationPlanner.plan()`
43
+ * returns a `MigrationPlanWithAuthoringSurface` that knows how to render
44
+ * itself back to such a file; `MongoMigrationPlanner.emptyMigration()`
45
+ * returns the same shape for `migration new`. Users run the scaffolded
46
+ * `migration.ts` directly (via `node migration.ts`) to self-emit
47
+ * `ops.json` and attest the `migrationHash`.
48
+ */
49
+ export const mongoTargetDescriptor: MongoControlTargetDescriptor<MongoTargetContract> = {
50
+ ...mongoTargetDescriptorMeta,
51
+ contractSerializer: new MongoTargetContractSerializer(),
52
+ schemaVerifier: new MongoTargetSchemaVerifier(),
53
+ migrations: {
54
+ createPlanner(_family: MongoControlFamilyInstance) {
55
+ return new MongoMigrationPlanner();
56
+ },
57
+ createRunner(family: MongoControlFamilyInstance) {
58
+ // Deps are bound to the first driver passed to execute() and cached for
59
+ // subsequent calls. Callers must not change the driver between calls.
60
+ let cachedDeps: MongoRunnerDependencies | undefined;
61
+
62
+ const runMongo = async (
63
+ driver: Parameters<MigrationRunner<'mongo', 'mongo'>['execute']>[0]['driver'],
64
+ runnerOptions: Omit<MongoMigrationRunnerExecuteOptions, 'destinationContract'> & {
65
+ readonly destinationContract: unknown;
66
+ },
67
+ ): Promise<MigrationRunnerResult> => {
68
+ cachedDeps ??= createMongoRunnerDeps(
69
+ driver,
70
+ MongoDriverImpl.fromDb(extractDb(driver)),
71
+ family,
72
+ );
73
+ // The framework `MigrationRunner` interface types `destinationContract`
74
+ // as `unknown`; the Mongo runner narrows to `MongoContract`. Validation
75
+ // happens upstream — `migration apply` calls
76
+ // `familyInstance.validateContract(migration.toContract)` before
77
+ // routing the contract here, so this cast preserves the framework
78
+ // signature without weakening the runner's typed surface.
79
+ return new MongoMigrationRunner(cachedDeps).execute({
80
+ ...runnerOptions,
81
+ destinationContract: runnerOptions.destinationContract as MongoContract,
82
+ });
83
+ };
84
+
85
+ const runner: MigrationRunner<'mongo', 'mongo'> & MultiSpaceCapableRunner<'mongo', 'mongo'> =
86
+ {
87
+ async execute(options) {
88
+ const { driver, ...runnerOptions } = options;
89
+ return runMongo(driver, runnerOptions);
90
+ },
91
+ // Mongo cannot wrap DDL ops in a session transaction (createCollection,
92
+ // createIndex, collMod, setValidation all bypass transactions even on
93
+ // replica sets), so the cross-space envelope is *resumable* rather than
94
+ // transactional. Per-space-internal verify-gated marker atomicity
95
+ // already lives in `runner.execute`: ops apply, schema is introspected
96
+ // and verified, and the marker advances only on verify-pass. This loop
97
+ // composes that guarantee across spaces — earlier-advanced markers are
98
+ // not rolled back when a later space fails. Re-running reads each
99
+ // marker, finds spaces 1..N−1 at-head (no-op skip), retries N onward.
100
+ //
101
+ // Per-space verify is sliced via `projectSchemaToSpace`: the live DB
102
+ // holds collections owned by sibling spaces, but each space's verify
103
+ // only sees the slice that space's contract actually claims. Without
104
+ // the projection an aggregate of two spaces could not pass strict
105
+ // verify (every other-space collection would look like an extra).
106
+ //
107
+ // See `docs/architecture docs/subsystems/10. MongoDB Family.md` §
108
+ // Contract spaces and ADR 212 — Contract spaces.
109
+ async executeAcrossSpaces({ driver, perSpaceOptions }): Promise<MultiSpaceRunnerResult> {
110
+ const members = perSpaceOptions.map(toSpaceMember);
111
+ const perSpaceResults: Array<{
112
+ space: string;
113
+ value: MigrationRunnerSuccessValue;
114
+ }> = [];
115
+ for (let i = 0; i < perSpaceOptions.length; i++) {
116
+ const spaceOptions = perSpaceOptions[i];
117
+ if (!spaceOptions) continue;
118
+ const member = members[i];
119
+ if (!member) continue;
120
+ const others = members.filter((_, j) => j !== i);
121
+ const projectSchema = (schema: MongoSchemaIR): MongoSchemaIR => {
122
+ // `projectSchemaToSpace` returns a plain object
123
+ // `{...schemaIR, collections: prunedArray}` (not a
124
+ // `MongoSchemaIR` instance), so the descriptor rewraps
125
+ // the pruned collections into a fresh `MongoSchemaIR`
126
+ // before handing it to `verifyMongoSchema` (which
127
+ // depends on the class's `collectionNames` /
128
+ // `collection(name)` accessors).
129
+ const projected = projectSchemaToSpace(schema, member, others) as {
130
+ readonly collections: ReadonlyArray<MongoSchemaCollection>;
131
+ };
132
+ return new MongoSchemaIR(projected.collections);
133
+ };
134
+ const result = await runMongo(driver, { ...spaceOptions, projectSchema });
135
+ if (!result.ok) {
136
+ return notOk<MultiSpaceRunnerFailure>({
137
+ ...result.failure,
138
+ failingSpace: spaceOptions.space,
139
+ });
140
+ }
141
+ perSpaceResults.push({ space: spaceOptions.space, value: result.value });
142
+ }
143
+ return ok({ perSpaceResults });
144
+ },
145
+ };
146
+ return runner;
147
+ },
148
+ contractToSchema(contract: Contract | null) {
149
+ return contractToMongoSchemaIR(contract as MongoContract | null);
150
+ },
151
+ },
152
+ create() {
153
+ return { familyId: 'mongo' as const, targetId: 'mongo' as const };
154
+ },
155
+ };
156
+
157
+ /**
158
+ * Synthesise the minimum {@link projectSchemaToSpace}-compatible
159
+ * `ContractSpaceMember` shape from a per-space option entry. The
160
+ * projector only reads `spaceId` and `contract.storage`; the rest of
161
+ * `ContractSpaceMember` (head ref invariants, hydrated migration
162
+ * graph) is irrelevant at runner time and stubbed with sentinels.
163
+ *
164
+ * The `as unknown as ContractSpaceMember` cast is the load-bearing bit
165
+ * — the projector duck-types its members so a sentinel-shaped graph
166
+ * never gets read, but the framework type carries a richer shape.
167
+ */
168
+ function toSpaceMember(
169
+ opts: MultiSpaceRunnerPerSpaceOptions<'mongo', 'mongo'>,
170
+ ): ContractSpaceMember {
171
+ return {
172
+ spaceId: opts.space,
173
+ contract: opts.destinationContract as Contract,
174
+ headRef: { hash: '', invariants: [] },
175
+ migrations: {
176
+ graph: {
177
+ nodes: new Set<string>(),
178
+ forwardChain: new Map(),
179
+ reverseChain: new Map(),
180
+ migrationByHash: new Map(),
181
+ },
182
+ packagesByMigrationHash: new Map(),
183
+ },
184
+ } as unknown as ContractSpaceMember;
185
+ }
@@ -1,4 +1,5 @@
1
1
  import type { Contract } from '@prisma-next/contract/types';
2
+ import { contractToMongoSchemaIR } from '@prisma-next/family-mongo/control';
2
3
  import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
3
4
  import type {
4
5
  MigrationOperationClass,
@@ -18,7 +19,6 @@ import type {
18
19
  MongoSchemaValidator,
19
20
  } from '@prisma-next/mongo-schema-ir';
20
21
  import { canonicalize, deepEqual } from '@prisma-next/mongo-schema-ir';
21
- import { contractToMongoSchemaIR } from './contract-to-schema';
22
22
  import type { OpFactoryCall } from './op-factory-call';
23
23
  import {
24
24
  CollModCall,
@@ -1,5 +1,7 @@
1
+ import type { MarkerOperations, MongoRunnerDependencies } from '@prisma-next/adapter-mongo/control';
1
2
  import type { ContractMarkerRecord } from '@prisma-next/contract/types';
2
3
  import { errorRunnerFailed } from '@prisma-next/errors/execution';
4
+ import { verifyMongoSchema } from '@prisma-next/family-mongo/schema-verify';
3
5
  import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
4
6
  import {
5
7
  APP_SPACE_ID,
@@ -17,7 +19,6 @@ import type {
17
19
  AnyMongoMigrationOperation,
18
20
  MongoDataTransformCheck,
19
21
  MongoDataTransformOperation,
20
- MongoDdlCommandVisitor,
21
22
  MongoInspectionCommandVisitor,
22
23
  MongoMigrationCheck,
23
24
  MongoMigrationPlanOperation,
@@ -26,53 +27,10 @@ import type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';
26
27
  import { notOk, ok } from '@prisma-next/utils/result';
27
28
  import { FilterEvaluator } from './filter-evaluator';
28
29
  import { deserializeMongoOps } from './mongo-ops-serializer';
29
- import { verifyMongoSchema } from './schema-verify/verify-mongo-schema';
30
30
 
31
31
  const READ_ONLY_CHECK_COMMAND_KINDS: ReadonlySet<string> = new Set(['aggregate', 'rawAggregate']);
32
32
 
33
- /**
34
- * Marker / ledger operations the Mongo runner depends on. Every method
35
- * takes a `space` parameter so each loaded contract space addresses its
36
- * own marker row independently — see ADR 212 for the per-space
37
- * mechanism.
38
- */
39
- export interface MarkerOperations {
40
- readMarker(space: string): Promise<ContractMarkerRecord | null>;
41
- initMarker(
42
- space: string,
43
- destination: {
44
- readonly storageHash: string;
45
- readonly profileHash: string;
46
- readonly invariants?: readonly string[];
47
- },
48
- ): Promise<void>;
49
- updateMarker(
50
- space: string,
51
- expectedFrom: string,
52
- destination: {
53
- readonly storageHash: string;
54
- readonly profileHash: string;
55
- readonly invariants?: readonly string[];
56
- },
57
- ): Promise<boolean>;
58
- writeLedgerEntry(
59
- space: string,
60
- entry: {
61
- readonly edgeId: string;
62
- readonly from: string;
63
- readonly to: string;
64
- },
65
- ): Promise<void>;
66
- }
67
-
68
- export interface MongoRunnerDependencies {
69
- readonly commandExecutor: MongoDdlCommandVisitor<Promise<void>>;
70
- readonly inspectionExecutor: MongoInspectionCommandVisitor<Promise<Record<string, unknown>[]>>;
71
- readonly adapter: MongoAdapter;
72
- readonly driver: MongoDriver;
73
- readonly markerOps: MarkerOperations;
74
- readonly introspectSchema: () => Promise<MongoSchemaIR>;
75
- }
33
+ export type { MarkerOperations, MongoRunnerDependencies };
76
34
 
77
35
  export interface MongoMigrationRunnerExecuteOptions {
78
36
  readonly plan: MigrationPlan;
@@ -0,0 +1,73 @@
1
+ import { MongoContractSerializerBase } from '@prisma-next/family-mongo/ir';
2
+ import { UNSPECIFIED_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
3
+ import { type MongoContract, MongoStorage } from '@prisma-next/mongo-contract';
4
+ import type { JsonObject } from '@prisma-next/utils/json';
5
+ import type { MongoTargetContract } from './mongo-target-contract';
6
+ import { MongoTargetUnspecifiedDatabase } from './mongo-target-database';
7
+
8
+ /**
9
+ * Mongo target `ContractSerializer` concretion. Plugs into the
10
+ * family-shared deserialization pipeline at `constructTargetContract`,
11
+ * wrapping the validated flat-data shape in a `MongoStorage` class
12
+ * instance and providing the target's default namespace map.
13
+ *
14
+ * Default namespaces is
15
+ * `{ [UNSPECIFIED_NAMESPACE_ID]: MongoTargetUnspecifiedDatabase.instance }`
16
+ * — supplied at this target-layer call site because the family-layer
17
+ * `MongoStorage` class is target-agnostic (it cannot import the
18
+ * Mongo-target's namespace concretion). Contracts authored before
19
+ * multi-namespace support bind to the unspecified singleton without the
20
+ * call site declaring anything.
21
+ *
22
+ * `validated.storage.collections` already carries `MongoCollection` IR
23
+ * class instances by the time this method runs — the family-base
24
+ * `hydrateMongoContract` walks the arktype-validated tree and
25
+ * constructs class instances before validation. The target serializer
26
+ * just wraps the envelope.
27
+ */
28
+ export class MongoTargetContractSerializer extends MongoContractSerializerBase<MongoTargetContract> {
29
+ protected constructTargetContract(validated: MongoContract): MongoTargetContract {
30
+ const { storage, ...rest } = validated;
31
+ const targetStorage = new MongoStorage({
32
+ storageHash: storage.storageHash,
33
+ collections: storage.collections,
34
+ namespaces: {
35
+ [UNSPECIFIED_NAMESPACE_ID]: MongoTargetUnspecifiedDatabase.instance,
36
+ },
37
+ });
38
+ return { ...rest, storage: targetStorage };
39
+ }
40
+
41
+ /**
42
+ * Produce the canonical on-disk JSON shape from an in-memory Mongo
43
+ * contract. Strips runtime-only fields the storage class carries
44
+ * for its live-instance API but that don't belong in the persisted
45
+ * envelope: `MongoStorage.namespaces` is a Namespace-class map the
46
+ * verifier and runtime walk; the persisted shape omits it (today's
47
+ * contracts have a single implicit unspecified namespace; future
48
+ * explicit per-collection assignment will surface in JSON via a
49
+ * different field).
50
+ *
51
+ * Constructing the JsonObject here — rather than relying on
52
+ * non-enumerable property tricks at the storage class — keeps the
53
+ * "what's on disk" decision in the SPI implementer, where it
54
+ * belongs.
55
+ */
56
+ override serializeContract(contract: MongoTargetContract): JsonObject {
57
+ const { storage, ...rest } = contract;
58
+ // `as unknown as JsonObject` because the returned literal mixes
59
+ // `MongoCollection` class instances under `storage.collections` with
60
+ // the JSON-clean remainder of the contract envelope. The class
61
+ // instances are JSON-clean by construction (their `kind` literal is
62
+ // enumerable; nested IR shapes are normalised by the constructor),
63
+ // so the canonical-stringify pass produces correct output, but the
64
+ // structural type system doesn't know `MongoCollection` is JSON-safe.
65
+ return {
66
+ ...rest,
67
+ storage: {
68
+ storageHash: storage.storageHash,
69
+ collections: storage.collections,
70
+ },
71
+ } as unknown as JsonObject;
72
+ }
73
+ }
@@ -0,0 +1,15 @@
1
+ import type { MongoContract, MongoStorage } from '@prisma-next/mongo-contract';
2
+
3
+ /**
4
+ * Mongo target contract envelope: the result of
5
+ * `descriptor.contractSerializer.deserializeContract(json)`.
6
+ *
7
+ * Structurally `MongoContract` with the storage envelope promoted to
8
+ * the family-layer `MongoStorage` class instance — the class carries
9
+ * `namespaces` and gives the rest of the framework a stable surface to
10
+ * reach for. The leaf collection / index shapes inside
11
+ * `storage.collections` are family-layer `MongoCollection` instances.
12
+ */
13
+ export type MongoTargetContract = Omit<MongoContract, 'storage'> & {
14
+ readonly storage: MongoStorage;
15
+ };
@@ -0,0 +1,82 @@
1
+ import {
2
+ freezeNode,
3
+ NamespaceBase,
4
+ UNSPECIFIED_NAMESPACE_ID,
5
+ } from '@prisma-next/framework-components/ir';
6
+
7
+ /**
8
+ * Mongo target `Namespace` concretion. In Mongo the "namespace" concept
9
+ * binds to the connection's `db` field — a `MongoTargetDatabase` instance
10
+ * names the database the collections live under.
11
+ *
12
+ * Qualifier emission is the rendering seam: query / DDL emission asks the
13
+ * namespace for its qualifier (e.g. `"<db>.<collection>"`) and consumes
14
+ * the result polymorphically. The unspecified singleton overrides these
15
+ * methods to elide the prefix entirely — call sites stay polymorphic and
16
+ * never branch on `id === UNSPECIFIED_NAMESPACE_ID`.
17
+ *
18
+ * **Freeze-trap warning.** The constructor calls `freezeNode(this)` at
19
+ * the end. Direct subclasses MUST NOT add instance fields — the freeze
20
+ * runs in this base constructor and any subclass field assignment will
21
+ * silently fail in non-strict mode or throw in strict mode. The
22
+ * `MongoTargetUnspecifiedDatabase` singleton below is intentionally
23
+ * field-free for this reason; if a future subclass needs to carry
24
+ * additional fields, lift this `freezeNode` to the leaf-class
25
+ * constructors (or to a `seal()` hook each leaf calls explicitly).
26
+ */
27
+ export class MongoTargetDatabase extends NamespaceBase {
28
+ readonly kind = 'database' as const;
29
+ readonly id: string;
30
+
31
+ constructor(id: string) {
32
+ super();
33
+ this.id = id;
34
+ freezeNode(this);
35
+ }
36
+
37
+ /**
38
+ * The bare qualifier as it would appear in a rendered string. The
39
+ * unspecified-database singleton overrides this to return `''`.
40
+ */
41
+ qualifier(): string {
42
+ return this.id;
43
+ }
44
+
45
+ /**
46
+ * Qualify a collection name with the database prefix. The
47
+ * unspecified-database singleton overrides this to emit just the
48
+ * collection name. Used by emission/introspection paths that need a
49
+ * fully-qualified reference.
50
+ */
51
+ qualifyCollection(collectionName: string): string {
52
+ return `${this.id}.${collectionName}`;
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Singleton subclass for the reserved sentinel namespace id
58
+ * (`UNSPECIFIED_NAMESPACE_ID`). Overrides qualifier emission to elide
59
+ * the database prefix — call sites that consume `qualifier()` /
60
+ * `qualifyCollection()` get unqualified output without branching on the
61
+ * namespace id.
62
+ *
63
+ * This is the target-side materialization of "the framework provides
64
+ * affordances; targets implement specifics": the framework names the
65
+ * sentinel; Mongo decides what no-database-bound means here (the
66
+ * collection name, naked).
67
+ */
68
+ export class MongoTargetUnspecifiedDatabase extends MongoTargetDatabase {
69
+ static readonly instance: MongoTargetUnspecifiedDatabase = new MongoTargetUnspecifiedDatabase();
70
+
71
+ private constructor() {
72
+ super(UNSPECIFIED_NAMESPACE_ID);
73
+ }
74
+
75
+ override qualifier(): string {
76
+ return '';
77
+ }
78
+
79
+ override qualifyCollection(collectionName: string): string {
80
+ return collectionName;
81
+ }
82
+ }