@prisma-next/target-mongo 0.4.1 → 0.4.2

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/README.md CHANGED
@@ -14,6 +14,8 @@ MongoDB target pack for Prisma Next.
14
14
  - `./pack`: pure target pack ref used by `@prisma-next/family-mongo` and `@prisma-next/mongo-contract-ts`
15
15
  - `./codec-types`: base Mongo codec type map
16
16
  - `./migration`: factory functions (the `Migration` base class is in `@prisma-next/family-mongo/migration`)
17
+ - `./control`: `MongoMigrationRunner` and `createMongoRunnerDeps` for runtime migration execution
18
+ - `./schema-verify`: pure `verifyMongoSchema(...)` (no DB I/O); composes `contractToMongoSchemaIR` and `diffMongoSchemas` so the runner's post-apply verify step and `MongoFamilyInstance.schemaVerify` agree on "matches the contract" by construction
17
19
 
18
20
  ## Usage
19
21
 
@@ -33,6 +35,7 @@ const contract = defineContract({
33
35
  ### Migration authoring
34
36
 
35
37
  ```typescript
38
+ import { MigrationCLI } from '@prisma-next/cli/migration-cli';
36
39
  import { Migration } from '@prisma-next/family-mongo/migration';
37
40
  import { createIndex, createCollection } from '@prisma-next/target-mongo/migration';
38
41
 
@@ -49,7 +52,7 @@ class UsersMigration extends Migration {
49
52
  }
50
53
 
51
54
  export default UsersMigration;
52
- Migration.run(import.meta.url, UsersMigration)
55
+ MigrationCLI.run(import.meta.url, UsersMigration);
53
56
  ```
54
57
 
55
58
  Run `tsx migration.ts` to produce `ops.json` and `migration.json` (when `describe()` is implemented). Use `--dry-run` to preview without writing.
@@ -1,10 +1,10 @@
1
- import { a as DropCollectionCall, c as schemaCollectionToCreateCollectionOptions, i as CreateIndexCall, l as schemaIndexToCreateIndexOptions, n as CollModMeta, o as DropIndexCall, r as CreateCollectionCall, s as OpFactoryCall, t as CollModCall } from "./op-factory-call-BjNAcPSF.mjs";
1
+ import { a as DropCollectionCall, c as schemaCollectionToCreateCollectionOptions, i as CreateIndexCall, l as schemaIndexToCreateIndexOptions, n as CollModMeta, o as DropIndexCall, r as CreateCollectionCall, s as OpFactoryCall, t as CollModCall } from "./op-factory-call-CVgzmLJh.mjs";
2
2
  import { MongoSchemaIR } from "@prisma-next/mongo-schema-ir";
3
3
  import { MongoQueryPlan } from "@prisma-next/mongo-query-ast/execution";
4
4
  import { AnyMongoMigrationOperation, MongoAndExpr, MongoDdlCommandVisitor, MongoExistsExpr, MongoExprFilter, MongoFieldFilter, MongoFilterExpr, MongoFilterVisitor, MongoInspectionCommandVisitor, MongoMigrationPlanOperation, MongoNotExpr, MongoOrExpr } from "@prisma-next/mongo-query-ast/control";
5
5
  import { Migration, MigrationMeta } from "@prisma-next/migration-tools/migration";
6
+ import { MigrationOperationPolicy, MigrationPlan, MigrationPlanOperation, MigrationPlanWithAuthoringSurface, MigrationPlanner, MigrationPlannerConflict, MigrationPlannerResult, MigrationRunnerExecutionChecks, MigrationRunnerResult, MigrationScaffoldContext, OperationContext } from "@prisma-next/framework-components/control";
6
7
  import { MongoContract } from "@prisma-next/mongo-contract";
7
- import { MigrationOperationPolicy, MigrationPlan, MigrationPlanOperation, MigrationPlanWithAuthoringSurface, MigrationPlanner, MigrationPlannerConflict, MigrationPlannerResult, MigrationRunnerExecutionChecks, MigrationRunnerResult, MigrationScaffoldContext } from "@prisma-next/framework-components/control";
8
8
  import { ContractMarkerRecord } from "@prisma-next/contract/types";
9
9
  import { Db } from "mongodb";
10
10
  import { TargetBoundComponentDescriptor } from "@prisma-next/framework-components/components";
@@ -106,21 +106,25 @@ interface MongoRunnerDependencies {
106
106
  readonly adapter: MongoAdapter;
107
107
  readonly driver: MongoDriver;
108
108
  readonly markerOps: MarkerOperations;
109
+ readonly introspectSchema: () => Promise<MongoSchemaIR>;
110
+ }
111
+ interface MongoMigrationRunnerExecuteOptions {
112
+ readonly plan: MigrationPlan;
113
+ readonly destinationContract: MongoContract;
114
+ readonly policy: MigrationOperationPolicy;
115
+ readonly callbacks?: {
116
+ onOperationStart?(op: MigrationPlanOperation): void;
117
+ onOperationComplete?(op: MigrationPlanOperation): void;
118
+ };
119
+ readonly executionChecks?: MigrationRunnerExecutionChecks;
120
+ readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'mongo', 'mongo'>>;
121
+ readonly strictVerification?: boolean;
122
+ readonly context?: OperationContext;
109
123
  }
110
124
  declare class MongoMigrationRunner {
111
125
  private readonly deps;
112
126
  constructor(deps: MongoRunnerDependencies);
113
- execute(options: {
114
- readonly plan: MigrationPlan;
115
- readonly destinationContract: unknown;
116
- readonly policy: MigrationOperationPolicy;
117
- readonly callbacks?: {
118
- onOperationStart?(op: MigrationPlanOperation): void;
119
- onOperationComplete?(op: MigrationPlanOperation): void;
120
- };
121
- readonly executionChecks?: MigrationRunnerExecutionChecks;
122
- readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'mongo', 'mongo'>>;
123
- }): Promise<MigrationRunnerResult>;
127
+ execute(options: MongoMigrationRunnerExecuteOptions): Promise<MigrationRunnerResult>;
124
128
  private executeDataTransform;
125
129
  private evaluateDataTransformChecks;
126
130
  private evaluateChecks;
@@ -179,9 +183,9 @@ interface RenderMigrationMeta {
179
183
  * `renderTypeScript()` expression and declares its own
180
184
  * `importRequirements()`. The top-level renderer aggregates imports
181
185
  * across all nodes and emits one `import { … } from "…"` line per module.
182
- * The `Migration` import from `@prisma-next/family-mongo/migration` is
183
- * always emitted it's driven by `meta` (the rendered scaffold always
184
- * extends `Migration`), not by any node.
186
+ * The `Migration` and `MigrationCLI` imports are always emitted — they're
187
+ * structural to the rendered scaffold (extends `Migration`, calls
188
+ * `MigrationCLI.run`), not driven by any node.
185
189
  */
186
190
  declare function renderCallsToTypeScript(calls: ReadonlyArray<OpFactoryCall>, meta: RenderMigrationMeta): string;
187
191
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/contract-to-schema.ts","../src/core/ddl-formatter.ts","../src/core/filter-evaluator.ts","../src/core/marker-ledger.ts","../src/core/mongo-ops-serializer.ts","../src/core/mongo-planner.ts","../src/core/mongo-runner.ts","../src/core/planner-produced-migration.ts","../src/core/render-ops.ts","../src/core/render-typescript.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;iBAoDgB,uBAAA,WAAkC,uBAAuB;;;iBC6CzD,qBAAA,sBAA2C;;;cC/C9C,eAAA,YAA2B;;mBAGrB,sBAAsB;cAK3B;YAKF;WAID;YAIC;eAIG;cAKD;;;;iBCjDQ,UAAA,KAAe,KAAK,QAAQ;iBAgB5B,UAAA,KAChB;;;IAEH;iBAcmB,YAAA,KAChB;;;IAGH;iBAiBmB,gBAAA,KAChB;;EHlCU,SAAA,IAAA,EAAA,MAAA;;IGoCb;;;iBC8ea,kBAAA,iBAAmC;iBAOnC,mBAAA,4BAA+C;iBAI/C,iBAAA,eAAgC;;;KC7epC,eAAA;;kBACoC;;;sBACI;;cAEvC,qBAAA,YAAiC;;;ILpD9B,SAAA,MAAA,EAAA,OAAuB;qBKwDlB;kCACa,cAAc;MAC1C;EJbU,IAAA,CAAA,OAAA,EAAA;;;qBIiIK;IHhLR,SAAA,QAAgB,EAAA,MAAA;IAGV,SAAA,mBAAA,EG+Ke,aH/Kf,CG+K6B,8BH/K7B,CAAA,OAAA,EAAA,OAAA,CAAA,CAAA;EAAsB,CAAA,CAAA,EGgLnC,sBHhLmC;EAK3B;;;;;;;;;0BGiMY,2BAA2B;;;;UCtNpC,gBAAA;gBACD,QAAQ;;;;MAIlB;;;INUU,SAAA,WAAA,EAAuB,MAAA;MMNlC;;;ILmDW,SAAA,IAAA,EAAA,MAAqB;;MK9C/B;;AJDO,UIII,uBAAA,CJJY;EAGV,SAAA,eAAA,EIES,sBJFT,CIEgC,OJFhC,CAAA,IAAA,CAAA,CAAA;EAAsB,SAAA,kBAAA,EIGV,6BJHU,CIGoB,OJHpB,CIG4B,MJH5B,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,CAAA,CAAA;EAK3B,SAAA,OAAA,EIDM,YJCN;EAKF,SAAA,MAAA,EILO,WJKP;EAID,SAAA,SAAA,EIRW,gBJQX;;AAQI,cIDF,oBAAA,CJCE;EAKD,iBAAA,IAAA;EA9B0B,WAAA,CAAA,IAAA,EIyBH,uBJzBG;EAAkB,OAAA,CAAA,OAAA,EAAA;mBI4BvC;;qBAEE;IHjDC,SAAU,SAAA,CAAA,EAAA;MAAK,gBAAA,EAAA,EAAA,EGmDT,sBHnDS,CAAA,EAAA,IAAA;MAAa,mBAAA,EAAA,EAAA,EGoDnB,sBHpDmB,CAAA,EAAA,IAAA;IAAR,CAAA;IAAO,SAAA,eAAA,CAAA,EGsDlB,8BHtDkB;IAgB3B,SAAU,mBAG7B,EGoC+B,aHpCxB,CGoCsC,8BHpCtC,CAAA,OAAA,EAAA,OAAA,CAAA,CAAA;EAcY,CAAA,CAAA,EGuBhB,OHvBgB,CGuBR,qBHnBX,CAAA;EAiBmB,QAAA,oBAAgB;;;;ECiftB,QAAA,0BAAmC;EAOnC,QAAA,yBAAmB;AAInC;;;;;;;;;;;;AJ7hBA;;;;AC6CA;;;cMzEa,6BAAA,SACH,UAAU,uCACP;ELwBA,iBAAA,KAAgB;EAGV,iBAAA,IAAA;EAAsB,SAAA,QAAA,EAAA,OAAA;EAK3B,WAAA,CAAA,KAAA,EAAA,SK3BuB,aL2BvB,EAAA,EAAA,IAAA,EK1Ba,aL0Bb;EAKF,IAAA,UAAA,CAAA,CAAA,EAAA,SK1B0B,0BL0B1B,EAAA;EAID,QAAA,CAAA,CAAA,EK1BY,aL0BZ;EAIC,gBAAA,CAAA,CAAA,EAAA,MAAA;;;;iBMpEI,SAAA,QAAiB,cAAc,iBAAiB;;;UCC/C,mBAAA;;;;;;;;;;;;ATgDjB;;;;AC6CA;;;;AC/CA;;;AAQc,iBOzBE,uBAAA,CPyBF,KAAA,EOxBL,aPwBK,COxBS,aPwBT,CAAA,EAAA,IAAA,EOvBN,mBPuBM,CAAA,EAAA,MAAA"}
1
+ {"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/contract-to-schema.ts","../src/core/ddl-formatter.ts","../src/core/filter-evaluator.ts","../src/core/marker-ledger.ts","../src/core/mongo-ops-serializer.ts","../src/core/mongo-planner.ts","../src/core/mongo-runner.ts","../src/core/planner-produced-migration.ts","../src/core/render-ops.ts","../src/core/render-typescript.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/control.mjs CHANGED
@@ -1,5 +1,6 @@
1
- import { a as dropCollection, n as createCollection, o as dropIndex, r as createIndex, t as collMod } from "./migration-factories-gwi81C8u.mjs";
2
- import { MongoSchemaCollection, MongoSchemaCollectionOptions, MongoSchemaIR, MongoSchemaIndex, MongoSchemaValidator, canonicalize, deepEqual } from "@prisma-next/mongo-schema-ir";
1
+ import { n as contractToMongoSchemaIR, t as verifyMongoSchema } from "./verify-mongo-schema-P0TRBJNs.mjs";
2
+ import { a as dropCollection, n as createCollection, o as dropIndex, r as createIndex, t as collMod } from "./migration-factories-Dbk5afMU.mjs";
3
+ import { canonicalize, deepEqual } from "@prisma-next/mongo-schema-ir";
3
4
  import { AggregateCommand, MongoAddFieldsStage, MongoLimitStage, MongoLookupStage, MongoMatchStage, MongoMergeStage, MongoProjectStage, MongoSortStage, RawAggregateCommand, RawDeleteManyCommand, RawDeleteOneCommand, RawFindOneAndDeleteCommand, RawFindOneAndUpdateCommand, RawInsertManyCommand, RawInsertOneCommand, RawUpdateManyCommand, RawUpdateOneCommand } from "@prisma-next/mongo-query-ast/execution";
4
5
  import { CollModCommand, CreateCollectionCommand, CreateIndexCommand, DropCollectionCommand, DropIndexCommand, ListCollectionsCommand, ListIndexesCommand, MongoAndExpr, MongoExistsExpr, MongoFieldFilter, MongoNotExpr, MongoOrExpr } from "@prisma-next/mongo-query-ast/control";
5
6
  import { ifDefined } from "@prisma-next/utils/defined";
@@ -10,45 +11,6 @@ import { detectScaffoldRuntime, shebangLineFor } from "@prisma-next/migration-to
10
11
  import { errorRunnerFailed } from "@prisma-next/errors/execution";
11
12
  import { notOk, ok } from "@prisma-next/utils/result";
12
13
 
13
- //#region src/core/contract-to-schema.ts
14
- function convertIndex(index) {
15
- return new MongoSchemaIndex({
16
- keys: index.keys,
17
- unique: index.unique,
18
- sparse: index.sparse,
19
- expireAfterSeconds: index.expireAfterSeconds,
20
- partialFilterExpression: index.partialFilterExpression,
21
- wildcardProjection: index.wildcardProjection,
22
- collation: index.collation,
23
- weights: index.weights,
24
- default_language: index.default_language,
25
- language_override: index.language_override
26
- });
27
- }
28
- function convertValidator(v) {
29
- return new MongoSchemaValidator({
30
- jsonSchema: v.jsonSchema,
31
- validationLevel: v.validationLevel,
32
- validationAction: v.validationAction
33
- });
34
- }
35
- function convertOptions(o) {
36
- return new MongoSchemaCollectionOptions(o);
37
- }
38
- function convertCollection(name, def) {
39
- return new MongoSchemaCollection({
40
- name,
41
- indexes: (def.indexes ?? []).map(convertIndex),
42
- ...def.validator != null && { validator: convertValidator(def.validator) },
43
- ...def.options != null && { options: convertOptions(def.options) }
44
- });
45
- }
46
- function contractToMongoSchemaIR(contract) {
47
- if (!contract) return new MongoSchemaIR([]);
48
- return new MongoSchemaIR(Object.entries(contract.storage.collections).map(([name, def]) => convertCollection(name, def)));
49
- }
50
-
51
- //#endregion
52
14
  //#region src/core/ddl-formatter.ts
53
15
  function formatKeySpec(keys) {
54
16
  return `{ ${keys.map((k) => `${JSON.stringify(k.field)}: ${JSON.stringify(k.direction)}`).join(", ")} }`;
@@ -827,10 +789,29 @@ function renderOps(calls) {
827
789
 
828
790
  //#endregion
829
791
  //#region src/core/render-typescript.ts
830
- const BASE_IMPORT = {
792
+ /**
793
+ * Always-present base imports for the rendered scaffold:
794
+ *
795
+ * - `Migration` from `@prisma-next/family-mongo/migration` — the
796
+ * user-facing Mongo `Migration` base; subclasses don't need to
797
+ * redeclare `targetId` or thread family/target generics.
798
+ * - `MigrationCLI` from `@prisma-next/cli/migration-cli` — the
799
+ * migration-file CLI entrypoint that loads `prisma-next.config.ts`,
800
+ * assembles a `ControlStack`, and instantiates the migration class.
801
+ * The migration file owns this dependency directly: pulling CLI
802
+ * machinery in at script run time is acceptable because the script's
803
+ * whole purpose is to be invoked from the project that owns the
804
+ * config. (Mirrors the postgres facade pattern; pulling `MigrationCLI`
805
+ * into `@prisma-next/family-mongo/migration` so a Mongo migration only
806
+ * needs one import is tracked separately as a follow-up.)
807
+ */
808
+ const BASE_IMPORTS = [{
831
809
  moduleSpecifier: "@prisma-next/family-mongo/migration",
832
810
  symbol: "Migration"
833
- };
811
+ }, {
812
+ moduleSpecifier: "@prisma-next/cli/migration-cli",
813
+ symbol: "MigrationCLI"
814
+ }];
834
815
  /**
835
816
  * Render a list of Mongo `OpFactoryCall`s as a `migration.ts`
836
817
  * source string. The result is shebanged, extends the user-facing
@@ -844,9 +825,9 @@ const BASE_IMPORT = {
844
825
  * `renderTypeScript()` expression and declares its own
845
826
  * `importRequirements()`. The top-level renderer aggregates imports
846
827
  * across all nodes and emits one `import { … } from "…"` line per module.
847
- * The `Migration` import from `@prisma-next/family-mongo/migration` is
848
- * always emitted it's driven by `meta` (the rendered scaffold always
849
- * extends `Migration`), not by any node.
828
+ * The `Migration` and `MigrationCLI` imports are always emitted — they're
829
+ * structural to the rendered scaffold (extends `Migration`, calls
830
+ * `MigrationCLI.run`), not driven by any node.
850
831
  */
851
832
  function renderCallsToTypeScript(calls, meta) {
852
833
  const imports = buildImports(calls);
@@ -865,12 +846,12 @@ function renderCallsToTypeScript(calls, meta) {
865
846
  "}",
866
847
  "",
867
848
  "export default M;",
868
- "Migration.run(import.meta.url, M);",
849
+ "MigrationCLI.run(import.meta.url, M);",
869
850
  ""
870
851
  ].join("\n");
871
852
  }
872
853
  function buildImports(calls) {
873
- const requirements = [BASE_IMPORT];
854
+ const requirements = [...BASE_IMPORTS];
874
855
  for (const call of calls) for (const req of call.importRequirements()) requirements.push(req);
875
856
  return renderImports(requirements);
876
857
  }
@@ -1109,9 +1090,6 @@ function planMutableOptionsDiffCall(collName, origin, dest) {
1109
1090
  //#endregion
1110
1091
  //#region src/core/mongo-runner.ts
1111
1092
  const READ_ONLY_CHECK_COMMAND_KINDS = new Set(["aggregate", "rawAggregate"]);
1112
- function hasProfileHash(value) {
1113
- return typeof value === "object" && value !== null && Object.hasOwn(value, "profileHash") && typeof value.profileHash === "string";
1114
- }
1115
1093
  function runnerFailure(code, summary, opts) {
1116
1094
  return notOk({
1117
1095
  code,
@@ -1163,11 +1141,23 @@ var MongoMigrationRunner = class {
1163
1141
  }
1164
1142
  }
1165
1143
  const destination = options.plan.destination;
1166
- const profileHash = hasProfileHash(options.destinationContract) ? options.destinationContract.profileHash : destination.storageHash;
1144
+ const profileHash = options.destinationContract.profileHash ?? destination.storageHash;
1167
1145
  if (operationsExecuted === 0 && existingMarker?.storageHash === destination.storageHash && existingMarker.profileHash === profileHash) return ok({
1168
1146
  operationsPlanned: operations.length,
1169
1147
  operationsExecuted
1170
1148
  });
1149
+ const liveSchema = await this.deps.introspectSchema();
1150
+ const verifyResult = verifyMongoSchema({
1151
+ contract: options.destinationContract,
1152
+ schema: liveSchema,
1153
+ strict: options.strictVerification ?? true,
1154
+ frameworkComponents: options.frameworkComponents,
1155
+ ...options.context ? { context: options.context } : {}
1156
+ });
1157
+ if (!verifyResult.ok) return runnerFailure("SCHEMA_VERIFY_FAILED", verifyResult.summary, {
1158
+ why: "The resulting database schema does not satisfy the destination contract.",
1159
+ meta: { issues: verifyResult.schema.issues }
1160
+ });
1171
1161
  if (existingMarker) {
1172
1162
  if (!await markerOps.updateMarker(existingMarker.storageHash, {
1173
1163
  storageHash: destination.storageHash,