@prisma-next/target-mongo 0.11.0-dev.5 → 0.11.0-dev.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codec-types.d.mts.map +1 -1
- package/dist/control.d.mts +0 -1
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +52 -47
- package/dist/control.mjs.map +1 -1
- package/dist/descriptor-meta-DdXFJeK1.mjs.map +1 -1
- package/dist/{migration-factories-BRBKKZia.mjs → migration-factories-BX6N1O0e.mjs} +4 -2
- package/dist/migration-factories-BX6N1O0e.mjs.map +1 -0
- package/dist/migration.d.mts.map +1 -1
- package/dist/migration.mjs +1 -1
- package/dist/op-factory-call-BC-llGKt.d.mts.map +1 -1
- package/dist/pack.d.mts.map +1 -1
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs.map +1 -1
- package/package.json +23 -23
- package/src/core/control-target.ts +16 -32
- package/src/core/migration-factories.ts +24 -0
- package/src/core/mongo-ops-serializer.ts +13 -10
- package/src/core/mongo-planner.ts +53 -8
- package/src/core/planner-produced-migration.ts +0 -2
- package/src/core/render-typescript.ts +1 -5
- package/dist/migration-factories-BRBKKZia.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-factories-BX6N1O0e.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 type { MongoValue } from '@prisma-next/mongo-value';\nimport { blindCast } from '@prisma-next/utils/casts';\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 // Include the $jsonSchema body so the idempotency probe only skips when the\n // live validator body genuinely already equals the target — not merely when\n // level/action happen to be unchanged (which was the silent-skip bug for widen ops).\n // MongoFieldFilter.eq compares with order-sensitive deepEqual, not canonicalize.\n // That is safe here because MongoDB preserves BSON key order when round-tripping\n // the $jsonSchema through listCollections (confirmed by the MMS integration test),\n // so a matching live validator compares equal. The only consequence of skipping\n // canonicalization is a safe false-negative on the skip: a validator installed\n // out-of-band with a different key order simply re-runs the collMod harmlessly.\n // The cast is safe: CollModOptions.validator is Record<string,unknown>, and its\n // $jsonSchema value is always a plain BSON object (MongoDocument at runtime).\n ...(options.validator?.['$jsonSchema'] !== undefined\n ? [\n MongoFieldFilter.eq(\n 'options.validator.$jsonSchema',\n blindCast<\n MongoValue,\n 'options.validator.$jsonSchema is a plain BSON object — the factory only populates this from a MongoSchemaValidator.jsonSchema record, which is a MongoDocument at runtime'\n >(options.validator?.['$jsonSchema']),\n ),\n ]\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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"}
|
package/dist/migration.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration.d.mts","names":[],"sources":["../src/core/migration-factories.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"migration.d.mts","names":[],"sources":["../src/core/migration-factories.ts"],"mappings":";;;;;;UA+BU,SAAA;EACR,KAAA,IAAS,cAAc;AAAA;AAAA,iBAoBT,aAAA,CACd,IAAA,UACA,OAAA;;;AAtBuB;AAoBzB;;EAQI,WAAA;EACA,KAAA;IACE,MAAA,QAAc,cAAA,GAAiB,SAAA;IAC/B,MAAA,GAAS,eAAA;IACT,MAAA;IACA,WAAA;EAAA;EAEF,GAAA,QAAW,cAAA,GAAiB,SAAA;AAAA,IAE7B,2BAAA;AAAA,iBA4Ca,WAAA,CACd,UAAA,UACA,IAAA,EAAM,aAAA,CAAc,aAAA,GACpB,OAAA,GAAU,kBAAA,GACT,2BAAA;AAAA,iBAwCa,SAAA,CACd,UAAA,UACA,IAAA,EAAM,aAAA,CAAc,aAAA,IACnB,2BAAA;AAAA,iBAiCa,gBAAA,CACd,UAAA,UACA,OAAA,GAAU,uBAAA,GACT,2BAA2B;AAAA,iBAuBd,cAAA,CAAe,UAAA,WAAqB,2BAA2B;AAAA,iBAgB/D,aAAA,CACd,UAAA,UACA,MAAA,EAAQ,MAAA,mBACR,OAAA;EAAY,eAAA;EAAyC,gBAAA;AAAA,IACpD,2BAA2B;AAAA,iBAoBd,OAAA,CACd,UAAA,UACA,OAAA,EAAS,cAAA,EACT,IAAA,GAAO,WAAA,GACN,2BAAA;AAAA,iBAmEa,mBAAA,CACd,IAAA,UACA,MAAA,EAAQ,MAAA,mBACR,OAAA,EAAS,aAAA;EAAgB,IAAA,EAAM,aAAA;EAAiB,MAAA;AAAA,KAC/C,2BAAA"}
|
package/dist/migration.mjs
CHANGED
|
@@ -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-
|
|
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-BX6N1O0e.mjs";
|
|
2
2
|
import { placeholder } from "@prisma-next/errors/migration";
|
|
3
3
|
export { collMod, createCollection, createIndex, dataTransform, dropCollection, dropIndex, placeholder, setValidation, validatedCollection };
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,uBAAuB;AAAA;AAAA,uBAKpC,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,iBAAiB;EAAA,SAC9C,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,kBAAkB;AAAA,iBAc5E,yCAAA,CACd,IAAA,EAAM,qBAAA,GACL,uBAAuB"}
|
package/dist/pack.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pack.d.mts","names":[],"sources":["../src/exports/pack.ts"],"mappings":";;;cAGM,eAAA;EAAA,SACK,IAAA;EAAA,SACA,QAAA;EAAA,SACA,QAAA;EAAA,SACA,EAAA;EAAA,SACA,OAAA;EAAA,SACA,YAAA,EAAc,MAAA;EAAA,SACd,YAAA,GAAe,
|
|
1
|
+
{"version":3,"file":"pack.d.mts","names":[],"sources":["../src/exports/pack.ts"],"mappings":";;;cAGM,eAAA;EAAA,SACK,IAAA;EAAA,SACA,QAAA;EAAA,SACA,QAAA;EAAA,SACA,EAAA;EAAA,SACA,OAAA;EAAA,SACA,YAAA,EAAc,MAAA;EAAA,SACd,YAAA,GAAe,UAAU;AAAA"}
|
package/dist/runtime.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/exports/runtime.ts"],"mappings":";;;;UAOiB,0BAAA,SAAmC,
|
|
1
|
+
{"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/exports/runtime.ts"],"mappings":";;;;UAOiB,0BAAA,SAAmC,qBAAqB;AAAzE;;;;AAAA,cAMM,4BAAA,EAA8B,uBAAA,mBAGlC,0BAAA;EAAA,SAES,MAAA,QAAc,kBAAA;AAAA"}
|
package/dist/runtime.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.mjs","names":[],"sources":["../src/exports/runtime.ts"],"sourcesContent":["import type {\n RuntimeTargetDescriptor,\n RuntimeTargetInstance,\n} from '@prisma-next/framework-components/execution';\nimport { type MongoCodecRegistry, newMongoCodecRegistry } from '@prisma-next/mongo-codec';\nimport { mongoTargetDescriptorMeta } from '../core/descriptor-meta';\n\nexport interface MongoRuntimeTargetInstance extends RuntimeTargetInstance<'mongo', 'mongo'> {}\n\n/**\n * Target-mongo deliberately does NOT import `MongoRuntimeTargetDescriptor` from `@prisma-next/mongo-runtime`. The target package is a control-plane residence and must not pull the Mongo execution-plane package into its dependency closure. The runtime descriptor here is shaped to satisfy the framework's `RuntimeTargetDescriptor` plus the structural `MongoStaticContributions` (`codecs`) that `@prisma-next/mongo-runtime`\n * consumers narrow to at composition time.\n */\nconst mongoRuntimeTargetDescriptor: RuntimeTargetDescriptor<\n 'mongo',\n 'mongo',\n MongoRuntimeTargetInstance\n> & {\n readonly codecs: () => MongoCodecRegistry;\n} = {\n ...mongoTargetDescriptorMeta,\n // The target descriptor itself contributes no codecs — the standard set lives on the adapter descriptor (see `@prisma-next/adapter-mongo/runtime`).\n codecs: () => newMongoCodecRegistry(),\n create(): MongoRuntimeTargetInstance {\n return {\n familyId: 'mongo',\n targetId: 'mongo',\n };\n },\n};\n\nexport default mongoRuntimeTargetDescriptor;\n"],"mappings":";;;;;;;AAaA,MAAM,+BAMF;CACF,GAAG;CAEH,cAAc,
|
|
1
|
+
{"version":3,"file":"runtime.mjs","names":[],"sources":["../src/exports/runtime.ts"],"sourcesContent":["import type {\n RuntimeTargetDescriptor,\n RuntimeTargetInstance,\n} from '@prisma-next/framework-components/execution';\nimport { type MongoCodecRegistry, newMongoCodecRegistry } from '@prisma-next/mongo-codec';\nimport { mongoTargetDescriptorMeta } from '../core/descriptor-meta';\n\nexport interface MongoRuntimeTargetInstance extends RuntimeTargetInstance<'mongo', 'mongo'> {}\n\n/**\n * Target-mongo deliberately does NOT import `MongoRuntimeTargetDescriptor` from `@prisma-next/mongo-runtime`. The target package is a control-plane residence and must not pull the Mongo execution-plane package into its dependency closure. The runtime descriptor here is shaped to satisfy the framework's `RuntimeTargetDescriptor` plus the structural `MongoStaticContributions` (`codecs`) that `@prisma-next/mongo-runtime`\n * consumers narrow to at composition time.\n */\nconst mongoRuntimeTargetDescriptor: RuntimeTargetDescriptor<\n 'mongo',\n 'mongo',\n MongoRuntimeTargetInstance\n> & {\n readonly codecs: () => MongoCodecRegistry;\n} = {\n ...mongoTargetDescriptorMeta,\n // The target descriptor itself contributes no codecs — the standard set lives on the adapter descriptor (see `@prisma-next/adapter-mongo/runtime`).\n codecs: () => newMongoCodecRegistry(),\n create(): MongoRuntimeTargetInstance {\n return {\n familyId: 'mongo',\n targetId: 'mongo',\n };\n },\n};\n\nexport default mongoRuntimeTargetDescriptor;\n"],"mappings":";;;;;;;AAaA,MAAM,+BAMF;CACF,GAAG;CAEH,cAAc,sBAAsB;CACpC,SAAqC;EACnC,OAAO;GACL,UAAU;GACV,UAAU;EACZ;CACF;AACF"}
|
package/package.json
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/target-mongo",
|
|
3
|
-
"version": "0.11.0-dev.
|
|
3
|
+
"version": "0.11.0-dev.51",
|
|
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.11.0-dev.
|
|
10
|
-
"@prisma-next/contract": "0.11.0-dev.
|
|
11
|
-
"@prisma-next/driver-mongo": "0.11.0-dev.
|
|
12
|
-
"@prisma-next/errors": "0.11.0-dev.
|
|
13
|
-
"@prisma-next/family-mongo": "0.11.0-dev.
|
|
14
|
-
"@prisma-next/framework-components": "0.11.0-dev.
|
|
15
|
-
"@prisma-next/migration-tools": "0.11.0-dev.
|
|
16
|
-
"@prisma-next/ts-render": "0.11.0-dev.
|
|
17
|
-
"@prisma-next/mongo-codec": "0.11.0-dev.
|
|
18
|
-
"@prisma-next/mongo-contract": "0.11.0-dev.
|
|
19
|
-
"@prisma-next/mongo-lowering": "0.11.0-dev.
|
|
20
|
-
"@prisma-next/mongo-query-ast": "0.11.0-dev.
|
|
21
|
-
"@prisma-next/mongo-schema-ir": "0.11.0-dev.
|
|
22
|
-
"@prisma-next/mongo-value": "0.11.0-dev.
|
|
23
|
-
"@prisma-next/utils": "0.11.0-dev.
|
|
24
|
-
"arktype": "^2.2.0"
|
|
25
|
-
"mongodb": "^6.16.0"
|
|
9
|
+
"@prisma-next/adapter-mongo": "0.11.0-dev.51",
|
|
10
|
+
"@prisma-next/contract": "0.11.0-dev.51",
|
|
11
|
+
"@prisma-next/driver-mongo": "0.11.0-dev.51",
|
|
12
|
+
"@prisma-next/errors": "0.11.0-dev.51",
|
|
13
|
+
"@prisma-next/family-mongo": "0.11.0-dev.51",
|
|
14
|
+
"@prisma-next/framework-components": "0.11.0-dev.51",
|
|
15
|
+
"@prisma-next/migration-tools": "0.11.0-dev.51",
|
|
16
|
+
"@prisma-next/ts-render": "0.11.0-dev.51",
|
|
17
|
+
"@prisma-next/mongo-codec": "0.11.0-dev.51",
|
|
18
|
+
"@prisma-next/mongo-contract": "0.11.0-dev.51",
|
|
19
|
+
"@prisma-next/mongo-lowering": "0.11.0-dev.51",
|
|
20
|
+
"@prisma-next/mongo-query-ast": "0.11.0-dev.51",
|
|
21
|
+
"@prisma-next/mongo-schema-ir": "0.11.0-dev.51",
|
|
22
|
+
"@prisma-next/mongo-value": "0.11.0-dev.51",
|
|
23
|
+
"@prisma-next/utils": "0.11.0-dev.51",
|
|
24
|
+
"arktype": "^2.2.0"
|
|
26
25
|
},
|
|
27
26
|
"devDependencies": {
|
|
28
|
-
"
|
|
29
|
-
"@prisma-next/psl
|
|
30
|
-
"@prisma-next/
|
|
31
|
-
"@prisma-next/
|
|
32
|
-
"@prisma-next/
|
|
27
|
+
"mongodb": "^7.2.0",
|
|
28
|
+
"@prisma-next/mongo-contract-psl": "0.11.0-dev.51",
|
|
29
|
+
"@prisma-next/psl-parser": "0.11.0-dev.51",
|
|
30
|
+
"@prisma-next/test-utils": "0.11.0-dev.51",
|
|
31
|
+
"@prisma-next/tsconfig": "0.11.0-dev.51",
|
|
32
|
+
"@prisma-next/tsdown": "0.11.0-dev.51",
|
|
33
33
|
"mongodb-memory-server": "11.1.0",
|
|
34
34
|
"pathe": "^2.0.3",
|
|
35
35
|
"tsdown": "0.22.0",
|
|
@@ -20,12 +20,13 @@ import type {
|
|
|
20
20
|
MultiSpaceRunnerResult,
|
|
21
21
|
} from '@prisma-next/framework-components/control';
|
|
22
22
|
import {
|
|
23
|
-
|
|
23
|
+
createContractSpaceMember,
|
|
24
24
|
projectSchemaToSpace,
|
|
25
25
|
} from '@prisma-next/migration-tools/aggregate';
|
|
26
26
|
import type { MongoContract } from '@prisma-next/mongo-contract';
|
|
27
27
|
import type { MongoSchemaCollection } from '@prisma-next/mongo-schema-ir';
|
|
28
28
|
import { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';
|
|
29
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
29
30
|
import { notOk, ok } from '@prisma-next/utils/result';
|
|
30
31
|
import { mongoTargetDescriptorMeta } from './descriptor-meta';
|
|
31
32
|
import { MongoMigrationPlanner } from './mongo-planner';
|
|
@@ -156,37 +157,20 @@ export const mongoTargetDescriptor: MongoControlTargetDescriptor<MongoTargetCont
|
|
|
156
157
|
};
|
|
157
158
|
|
|
158
159
|
/**
|
|
159
|
-
* Synthesise
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
* graph) is irrelevant at runner time and stubbed with sentinels.
|
|
164
|
-
*
|
|
165
|
-
* The `as unknown as ContractSpaceMember` cast is the load-bearing bit
|
|
166
|
-
* — the projector duck-types its members so a sentinel-shaped graph
|
|
167
|
-
* never gets read, but the framework type carries a richer shape.
|
|
160
|
+
* Synthesise a {@link projectSchemaToSpace}-compatible member from a
|
|
161
|
+
* per-space option entry. The projector only reads `spaceId` and
|
|
162
|
+
* `contract()`; migration graph state is empty because the runner
|
|
163
|
+
* consumes the destination contract directly.
|
|
168
164
|
*/
|
|
169
|
-
function toSpaceMember(
|
|
170
|
-
|
|
171
|
-
): ContractSpaceMember {
|
|
172
|
-
return {
|
|
165
|
+
function toSpaceMember(opts: MultiSpaceRunnerPerSpaceOptions<'mongo', 'mongo'>) {
|
|
166
|
+
return createContractSpaceMember({
|
|
173
167
|
spaceId: opts.space,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
migrations: {
|
|
183
|
-
graph: {
|
|
184
|
-
nodes: new Set<string>(),
|
|
185
|
-
forwardChain: new Map(),
|
|
186
|
-
reverseChain: new Map(),
|
|
187
|
-
migrationByHash: new Map(),
|
|
188
|
-
},
|
|
189
|
-
packagesByMigrationHash: new Map(),
|
|
190
|
-
},
|
|
191
|
-
} as unknown as ContractSpaceMember;
|
|
168
|
+
packages: [],
|
|
169
|
+
refs: {},
|
|
170
|
+
headRef: null,
|
|
171
|
+
resolveContract: () =>
|
|
172
|
+
blindCast<Contract, 'destinationContract validated at aggregate boundary'>(
|
|
173
|
+
opts.destinationContract,
|
|
174
|
+
),
|
|
175
|
+
});
|
|
192
176
|
}
|
|
@@ -24,6 +24,8 @@ import {
|
|
|
24
24
|
type MongoMigrationPlanOperation,
|
|
25
25
|
} from '@prisma-next/mongo-query-ast/control';
|
|
26
26
|
import type { MongoQueryPlan } from '@prisma-next/mongo-query-ast/execution';
|
|
27
|
+
import type { MongoValue } from '@prisma-next/mongo-value';
|
|
28
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
27
29
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
28
30
|
import type { CollModMeta } from './op-factory-call';
|
|
29
31
|
|
|
@@ -296,6 +298,28 @@ export function collMod(
|
|
|
296
298
|
...(options.validationAction
|
|
297
299
|
? [MongoFieldFilter.eq('options.validationAction', options.validationAction)]
|
|
298
300
|
: []),
|
|
301
|
+
// Include the $jsonSchema body so the idempotency probe only skips when the
|
|
302
|
+
// live validator body genuinely already equals the target — not merely when
|
|
303
|
+
// level/action happen to be unchanged (which was the silent-skip bug for widen ops).
|
|
304
|
+
// MongoFieldFilter.eq compares with order-sensitive deepEqual, not canonicalize.
|
|
305
|
+
// That is safe here because MongoDB preserves BSON key order when round-tripping
|
|
306
|
+
// the $jsonSchema through listCollections (confirmed by the MMS integration test),
|
|
307
|
+
// so a matching live validator compares equal. The only consequence of skipping
|
|
308
|
+
// canonicalization is a safe false-negative on the skip: a validator installed
|
|
309
|
+
// out-of-band with a different key order simply re-runs the collMod harmlessly.
|
|
310
|
+
// The cast is safe: CollModOptions.validator is Record<string,unknown>, and its
|
|
311
|
+
// $jsonSchema value is always a plain BSON object (MongoDocument at runtime).
|
|
312
|
+
...(options.validator?.['$jsonSchema'] !== undefined
|
|
313
|
+
? [
|
|
314
|
+
MongoFieldFilter.eq(
|
|
315
|
+
'options.validator.$jsonSchema',
|
|
316
|
+
blindCast<
|
|
317
|
+
MongoValue,
|
|
318
|
+
'options.validator.$jsonSchema is a plain BSON object — the factory only populates this from a MongoSchemaValidator.jsonSchema record, which is a MongoDocument at runtime'
|
|
319
|
+
>(options.validator?.['$jsonSchema']),
|
|
320
|
+
),
|
|
321
|
+
]
|
|
322
|
+
: []),
|
|
299
323
|
]),
|
|
300
324
|
expect: 'exists' as const,
|
|
301
325
|
},
|
|
@@ -489,16 +489,19 @@ function deserializeDdlCommand(json: unknown): AnyMongoDdlCommand {
|
|
|
489
489
|
case 'createIndex': {
|
|
490
490
|
const data = validate(CreateIndexJson, json, 'createIndex command');
|
|
491
491
|
return new CreateIndexCommand(data.collection, data.keys, {
|
|
492
|
-
unique
|
|
493
|
-
sparse
|
|
494
|
-
expireAfterSeconds
|
|
495
|
-
partialFilterExpression
|
|
496
|
-
name
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
492
|
+
...ifDefined('unique', data.unique),
|
|
493
|
+
...ifDefined('sparse', data.sparse),
|
|
494
|
+
...ifDefined('expireAfterSeconds', data.expireAfterSeconds),
|
|
495
|
+
...ifDefined('partialFilterExpression', data.partialFilterExpression),
|
|
496
|
+
...ifDefined('name', data.name),
|
|
497
|
+
...ifDefined(
|
|
498
|
+
'wildcardProjection',
|
|
499
|
+
data.wildcardProjection as Record<string, 0 | 1> | undefined,
|
|
500
|
+
),
|
|
501
|
+
...ifDefined('collation', data.collation),
|
|
502
|
+
...ifDefined('weights', data.weights as Record<string, number> | undefined),
|
|
503
|
+
...ifDefined('default_language', data.default_language),
|
|
504
|
+
...ifDefined('language_override', data.language_override),
|
|
502
505
|
});
|
|
503
506
|
}
|
|
504
507
|
case 'dropIndex': {
|
|
@@ -66,21 +66,66 @@ function classifyValidatorUpdate(
|
|
|
66
66
|
origin: MongoSchemaValidator,
|
|
67
67
|
dest: MongoSchemaValidator,
|
|
68
68
|
): 'widening' | 'destructive' {
|
|
69
|
-
|
|
69
|
+
// Moving to a stricter action or level narrows the accepted value space.
|
|
70
|
+
if (origin.validationAction !== dest.validationAction && dest.validationAction === 'error') {
|
|
71
|
+
return 'destructive';
|
|
72
|
+
}
|
|
73
|
+
if (origin.validationLevel !== dest.validationLevel && dest.validationLevel === 'strict') {
|
|
74
|
+
return 'destructive';
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (canonicalize(origin.jsonSchema) === canonicalize(dest.jsonSchema)) {
|
|
78
|
+
return 'widening';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Check whether the schema change only adds non-required properties (widening).
|
|
82
|
+
return isWideningSchemaChange(origin.jsonSchema, dest.jsonSchema) ? 'widening' : 'destructive';
|
|
83
|
+
}
|
|
70
84
|
|
|
71
|
-
|
|
72
|
-
|
|
85
|
+
function isPlainObject(v: unknown): v is Record<string, unknown> {
|
|
86
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Returns true when `dest` is a structural superset of `origin` for the common
|
|
91
|
+
* additive case: adding non-required properties to a top-level object schema.
|
|
92
|
+
* Anything uncertain falls through to the safe `destructive` default.
|
|
93
|
+
*/
|
|
94
|
+
function isWideningSchemaChange(
|
|
95
|
+
origin: Record<string, unknown>,
|
|
96
|
+
dest: Record<string, unknown>,
|
|
97
|
+
): boolean {
|
|
98
|
+
// Only handle top-level object schemas.
|
|
99
|
+
if (origin['bsonType'] !== 'object' || dest['bsonType'] !== 'object') {
|
|
100
|
+
return false;
|
|
73
101
|
}
|
|
74
102
|
|
|
75
|
-
|
|
76
|
-
|
|
103
|
+
// Any change to keys besides 'required' and 'properties' is uncertain → destructive.
|
|
104
|
+
const allKeys = new Set([...Object.keys(origin), ...Object.keys(dest)]);
|
|
105
|
+
for (const key of allKeys) {
|
|
106
|
+
if (key === 'required' || key === 'properties') continue;
|
|
107
|
+
if (canonicalize(origin[key]) !== canonicalize(dest[key])) return false;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// dest.required must be a subset of origin.required — no new required fields.
|
|
111
|
+
const originRequired = new Set<unknown>(
|
|
112
|
+
Array.isArray(origin['required']) ? origin['required'] : [],
|
|
113
|
+
);
|
|
114
|
+
const destRequired = Array.isArray(dest['required']) ? dest['required'] : [];
|
|
115
|
+
for (const field of destRequired) {
|
|
116
|
+
if (!originRequired.has(field)) return false;
|
|
77
117
|
}
|
|
78
118
|
|
|
79
|
-
|
|
80
|
-
|
|
119
|
+
// All properties that existed in origin must still exist unchanged.
|
|
120
|
+
// New properties in dest (absent from origin) are allowed — widening.
|
|
121
|
+
const originProps = isPlainObject(origin['properties']) ? origin['properties'] : {};
|
|
122
|
+
const destProps = isPlainObject(dest['properties']) ? dest['properties'] : {};
|
|
123
|
+
for (const field of Object.keys(originProps)) {
|
|
124
|
+
if (!Object.hasOwn(destProps, field)) return false; // Property removed → destructive.
|
|
125
|
+
if (canonicalize(originProps[field]) !== canonicalize(destProps[field])) return false; // Property narrowed → destructive.
|
|
81
126
|
}
|
|
82
127
|
|
|
83
|
-
return
|
|
128
|
+
return true;
|
|
84
129
|
}
|
|
85
130
|
|
|
86
131
|
function hasImmutableOptionChange(
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { MigrationPlanWithAuthoringSurface } from '@prisma-next/framework-components/control';
|
|
2
2
|
import { Migration, type MigrationMeta } from '@prisma-next/migration-tools/migration';
|
|
3
3
|
import type { AnyMongoMigrationOperation } from '@prisma-next/mongo-query-ast/control';
|
|
4
|
-
import { ifDefined } from '@prisma-next/utils/defined';
|
|
5
4
|
import type { OpFactoryCall } from './op-factory-call';
|
|
6
5
|
import { renderOps } from './render-ops';
|
|
7
6
|
import { renderCallsToTypeScript } from './render-typescript';
|
|
@@ -47,7 +46,6 @@ export class PlannerProducedMongoMigration
|
|
|
47
46
|
return renderCallsToTypeScript(this.calls, {
|
|
48
47
|
from: this.meta.from,
|
|
49
48
|
to: this.meta.to,
|
|
50
|
-
...ifDefined('labels', this.meta.labels),
|
|
51
49
|
});
|
|
52
50
|
}
|
|
53
51
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { detectScaffoldRuntime, shebangLineFor } from '@prisma-next/migration-tools/migration-ts';
|
|
2
|
-
import { type ImportRequirement,
|
|
2
|
+
import { type ImportRequirement, renderImports } from '@prisma-next/ts-render';
|
|
3
3
|
import type { OpFactoryCall } from './op-factory-call';
|
|
4
4
|
|
|
5
5
|
export interface RenderMigrationMeta {
|
|
6
6
|
readonly from: string | null;
|
|
7
7
|
readonly to: string;
|
|
8
|
-
readonly labels?: readonly string[];
|
|
9
8
|
}
|
|
10
9
|
|
|
11
10
|
/**
|
|
@@ -88,9 +87,6 @@ function buildDescribeMethod(meta: RenderMigrationMeta): string {
|
|
|
88
87
|
lines.push(' return {');
|
|
89
88
|
lines.push(` from: ${JSON.stringify(meta.from)},`);
|
|
90
89
|
lines.push(` to: ${JSON.stringify(meta.to)},`);
|
|
91
|
-
if (meta.labels && meta.labels.length > 0) {
|
|
92
|
-
lines.push(` labels: ${jsonToTsSource(meta.labels)},`);
|
|
93
|
-
}
|
|
94
90
|
lines.push(' };');
|
|
95
91
|
lines.push(' }');
|
|
96
92
|
lines.push('');
|
|
@@ -1 +0,0 @@
|
|
|
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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"}
|