feat(mongo-migration): add hand-authored migration authoring#344
feat(mongo-migration): add hand-authored migration authoring#344
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a migration authoring framework and Mongo-targeted tooling: a generic Migration base with CLI/dry-run, MongoMigration subclass, migration factory functions (indexes, collections, validation), package exports, example migrations, and extensive tests (unit, integration, E2E) exercising serialization and execution against in-memory MongoDB. Changes
Sequence Diagram(s)sequenceDiagram
actor Dev as Developer
participant CLI as Migration.run()
participant Module as Migration Module
participant Schema as Metadata Validator
participant FS as Filesystem
Dev->>CLI: Run migration entrypoint (e.g., tsx migration.ts)
CLI->>CLI: Check module is entrypoint
alt not entrypoint
CLI-->>Dev: no-op (import)
else entrypoint
CLI->>Module: Instantiate Migration
Module-->>CLI: instance
CLI->>Module: call plan()
Module-->>CLI: operations[]
CLI->>Schema: validate describe() metadata (if present)
Schema-->>CLI: valid / error
alt --dry-run
CLI-->>Dev: print ops.json and migration.json to stdout
else normal run
CLI->>FS: write ops.json
CLI->>FS: write migration.json (if metadata)
FS-->>CLI: write confirmations
CLI-->>Dev: success message
end
end
sequenceDiagram
actor User as Runner Caller
participant Runner as MongoMigrationRunner
participant Driver as MongoControlDriver
participant Mongo as MongoDB
User->>Runner: execute(operations, policy)
loop per operation
Runner->>Driver: precheck (ListIndexes/ListCollections)
Driver->>Mongo: query state
Mongo-->>Driver: state
Driver-->>Runner: precheck result
alt precheck passes
Runner->>Driver: execute command (CreateIndex/CreateCollection/CollMod/DropIndex/DropCollection)
Driver->>Mongo: apply command
Mongo-->>Driver: result
Driver-->>Runner: execution result
Runner->>Driver: postcheck (verify)
Driver->>Mongo: verification
Mongo-->>Driver: verification result
Driver-->>Runner: postcheck result
end
end
Runner-->>User: { ok, operationsExecuted }
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (6)
packages/3-mongo-target/1-mongo-target/test/migration-e2e.test.ts (1)
1-6: Preferpatheovernode:pathfor path operations.Per coding guidelines, use
patheinstead ofnode:pathfor consistent cross-platform behavior.♻️ Suggested change
import { execFile } from 'node:child_process'; import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'; import { tmpdir } from 'node:os'; -import { join, resolve } from 'node:path'; +import { join, resolve } from 'pathe'; import { promisify } from 'node:util'; import { afterEach, beforeEach, describe, expect, it } from 'vitest';Based on learnings: "In the prisma/prisma-next repo, prefer using
patheover Node's built-innode:path."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/3-mongo-target/1-mongo-target/test/migration-e2e.test.ts` around lines 1 - 6, Replace imports from 'node:path' with 'pathe' and update any path function usage accordingly: change the import statement that currently brings in join and resolve from 'node:path' to import them from 'pathe' instead, and ensure any calls to join(...) and resolve(...) in this file (e.g., in migration-e2e.test.ts) remain the same but now reference the pathe implementations for consistent cross-platform behavior.examples/retail-store/test/manual-migration.test.ts (1)
1-2: Preferpatheovernode:pathfor path operations.Per coding guidelines, use
patheinstead ofnode:pathfor consistent cross-platform behavior.♻️ Suggested change
import { readFileSync } from 'node:fs'; -import { resolve } from 'node:path'; +import { resolve } from 'pathe';Based on learnings: "In the prisma/prisma-next repo, prefer using
patheover Node's built-innode:path."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/retail-store/test/manual-migration.test.ts` around lines 1 - 2, The import uses Node's built-in path module (import { resolve } from 'node:path') which violates the guideline to use pathe; replace the node:path usage by importing resolve from 'pathe' and update any references that call resolve accordingly (keep readFileSync from 'node:fs' as-is) so path operations use pathe's cross-platform implementation.packages/3-mongo-target/1-mongo-target/test/migration-strategies.test.ts (1)
22-27: Consider usingtoMatchObjectfor related property assertions.Multiple assertions on the same
cmdobject could be consolidated for cleaner test code.♻️ Suggested refactor
- expect(cmd).toBeInstanceOf(CreateCollectionCommand); - expect(cmd.validator).toEqual({ $jsonSchema: { required: ['email'] } }); - expect(cmd.validationLevel).toBe('strict'); - expect(cmd.validationAction).toBe('error'); + expect(cmd).toBeInstanceOf(CreateCollectionCommand); + expect(cmd).toMatchObject({ + validator: { $jsonSchema: { required: ['email'] } }, + validationLevel: 'strict', + validationAction: 'error', + });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/3-mongo-target/1-mongo-target/test/migration-strategies.test.ts` around lines 22 - 27, The test currently makes multiple assertions on the same CreateCollectionCommand instance (cmd)—replace the separate expect checks for validator, validationLevel, and validationAction with a single consolidated assertion using toMatchObject on cmd (or cmd as CreateCollectionCommand) to assert the related properties together (e.g., expect(cmd).toMatchObject({ validator: { $jsonSchema: { required: ['email'] } }, validationLevel: 'strict', validationAction: 'error' })), keeping the initial instance check expect(cmd).toBeInstanceOf(CreateCollectionCommand) intact.examples/mongo-demo/test/manual-migration.test.ts (2)
5-5: Unused import:Migration.The
Migrationimport is not used in this test file—the migration class is dynamically imported viaimport('../migrations/...')instead.Suggested fix
-import { Migration } from '@prisma-next/family-mongo/migration';🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/mongo-demo/test/manual-migration.test.ts` at line 5, The import Migration from '@prisma-next/family-mongo/migration' in manual-migration.test.ts is unused because the test loads migrations dynamically via import('../migrations/...'); remove the unused import statement (the `Migration` identifier) from that file to eliminate the dead import and ensure there are no remaining references to `Migration` in the test.
1-2: Usepatheinstead ofnode:pathfor cross-platform consistency.Per repository guidelines, prefer
patheovernode:pathfor path manipulation in TypeScript files.Suggested fix
import { readFileSync } from 'node:fs'; -import { resolve } from 'node:path'; +import { resolve } from 'pathe';🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/mongo-demo/test/manual-migration.test.ts` around lines 1 - 2, Replace the use of Node's path module with pathe for cross-platform consistency: change the import of resolve from "node:path" to import { resolve } from "pathe" (leave readFileSync from "node:fs" as-is) and update any uses of resolve in this file (e.g., in manual-migration.test.ts) to rely on pathe's resolve.packages/3-mongo-target/1-mongo-target/src/core/migration-factories.ts (1)
29-33: Remove unusedcollectionparameter fromkeyFilter.The
collectionparameter is declared but never used in the function body.Suggested fix
-function keyFilter(collection: string, keys: ReadonlyArray<MongoIndexKey>) { +function keyFilter(keys: ReadonlyArray<MongoIndexKey>) { return isTextIndex(keys) ? MongoFieldFilter.eq('key._fts', 'text') : MongoFieldFilter.eq('key', keysToKeySpec(keys)); }Then update the call sites at lines 41 and 84:
- const filter = keyFilter(collection, keys); + const filter = keyFilter(keys);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/3-mongo-target/1-mongo-target/src/core/migration-factories.ts` around lines 29 - 33, The function keyFilter declares an unused parameter "collection"; remove that parameter from the keyFilter signature and update its body to only accept (keys: ReadonlyArray<MongoIndexKey>) same as currently used logic, then update all call sites that pass a collection (the two places invoking keyFilter in the same file) to call keyFilter(keys) instead of keyFilter(collection, keys); ensure imports/types remain unchanged and run tests/typecheck to verify no remaining references to the removed parameter (function name: keyFilter; update the two call sites that currently pass collection).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/1-framework/3-tooling/migration/src/migration-base.ts`:
- Around line 59-69: The help text in printHelp wrongly suggests running a
TypeScript migration directly with Node; update the Usage line in the
printHelp() function to show the supported runner instead (e.g. "Usage:
<migration-runner> <migration-file> [options]" or the actual CLI name your
project exposes) so --help points to a working invocation; edit the string in
printHelp() and keep the rest of the options text unchanged.
- Around line 72-80: Before calling buildManifest(), validate the object
returned by describe() against the MigrationMeta shape (the same Arktype used
elsewhere for plan()) and reject/throw if validation fails; specifically, call
the MigrationMeta validator (or the existing arktype schema used for plan()) on
the describe() result, ensure from/to are strings, kind is a valid kind, and
labels is an array, and only pass the validated/parsed value into
buildManifest(); if validation fails, surface a clear error so malformed JS/TS
migrations cannot produce an invalid migration.json.
In `@packages/1-framework/3-tooling/migration/test/migration-base.test.ts`:
- Around line 67-80: The generated fixture uses raw absolute paths for ESM
imports (migrationBasePath and the import string inside migrationScript), which
are invalid; convert the path to a file:// URL using pathToFileURL(...).href and
use that href in the import specifier. Specifically, update migrationBasePath to
be pathToFileURL(join(packageRoot, 'src/migration-base.ts')).href (ensure
pathToFileURL is imported from 'url'), and change the import line inside
migrationScript to import { Migration } from '<migrationBasePathHref>'; so the
generated fixture emits a proper file:// URL instead of a raw absolute path.
---
Nitpick comments:
In `@examples/mongo-demo/test/manual-migration.test.ts`:
- Line 5: The import Migration from '@prisma-next/family-mongo/migration' in
manual-migration.test.ts is unused because the test loads migrations dynamically
via import('../migrations/...'); remove the unused import statement (the
`Migration` identifier) from that file to eliminate the dead import and ensure
there are no remaining references to `Migration` in the test.
- Around line 1-2: Replace the use of Node's path module with pathe for
cross-platform consistency: change the import of resolve from "node:path" to
import { resolve } from "pathe" (leave readFileSync from "node:fs" as-is) and
update any uses of resolve in this file (e.g., in manual-migration.test.ts) to
rely on pathe's resolve.
In `@examples/retail-store/test/manual-migration.test.ts`:
- Around line 1-2: The import uses Node's built-in path module (import { resolve
} from 'node:path') which violates the guideline to use pathe; replace the
node:path usage by importing resolve from 'pathe' and update any references that
call resolve accordingly (keep readFileSync from 'node:fs' as-is) so path
operations use pathe's cross-platform implementation.
In `@packages/3-mongo-target/1-mongo-target/src/core/migration-factories.ts`:
- Around line 29-33: The function keyFilter declares an unused parameter
"collection"; remove that parameter from the keyFilter signature and update its
body to only accept (keys: ReadonlyArray<MongoIndexKey>) same as currently used
logic, then update all call sites that pass a collection (the two places
invoking keyFilter in the same file) to call keyFilter(keys) instead of
keyFilter(collection, keys); ensure imports/types remain unchanged and run
tests/typecheck to verify no remaining references to the removed parameter
(function name: keyFilter; update the two call sites that currently pass
collection).
In `@packages/3-mongo-target/1-mongo-target/test/migration-e2e.test.ts`:
- Around line 1-6: Replace imports from 'node:path' with 'pathe' and update any
path function usage accordingly: change the import statement that currently
brings in join and resolve from 'node:path' to import them from 'pathe' instead,
and ensure any calls to join(...) and resolve(...) in this file (e.g., in
migration-e2e.test.ts) remain the same but now reference the pathe
implementations for consistent cross-platform behavior.
In `@packages/3-mongo-target/1-mongo-target/test/migration-strategies.test.ts`:
- Around line 22-27: The test currently makes multiple assertions on the same
CreateCollectionCommand instance (cmd)—replace the separate expect checks for
validator, validationLevel, and validationAction with a single consolidated
assertion using toMatchObject on cmd (or cmd as CreateCollectionCommand) to
assert the related properties together (e.g., expect(cmd).toMatchObject({
validator: { $jsonSchema: { required: ['email'] } }, validationLevel: 'strict',
validationAction: 'error' })), keeping the initial instance check
expect(cmd).toBeInstanceOf(CreateCollectionCommand) intact.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 1ddac469-852f-4497-b780-e6c2cc35bced
⛔ Files ignored due to path filters (3)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlprojects/mongo-migration-authoring/assets/migration-authoring-design.mdis excluded by!projects/**projects/mongo-migration-authoring/spec.mdis excluded by!projects/**
📒 Files selected for processing (28)
examples/mongo-demo/migrations/20260415_add-posts-author-index/migration.jsonexamples/mongo-demo/migrations/20260415_add-posts-author-index/migration.tsexamples/mongo-demo/migrations/20260415_add-posts-author-index/ops.jsonexamples/mongo-demo/test/manual-migration.test.tsexamples/retail-store/migrations/20260415_add-product-validation/migration.jsonexamples/retail-store/migrations/20260415_add-product-validation/migration.tsexamples/retail-store/migrations/20260415_add-product-validation/ops.jsonexamples/retail-store/test/manual-migration.test.tspackages/1-framework/3-tooling/migration/package.jsonpackages/1-framework/3-tooling/migration/src/exports/migration.tspackages/1-framework/3-tooling/migration/src/migration-base.tspackages/1-framework/3-tooling/migration/test/migration-base.test.tspackages/1-framework/3-tooling/migration/tsdown.config.tspackages/2-mongo-family/9-family/README.mdpackages/2-mongo-family/9-family/package.jsonpackages/2-mongo-family/9-family/src/core/mongo-migration.tspackages/2-mongo-family/9-family/src/exports/migration.tspackages/2-mongo-family/9-family/tsdown.config.tspackages/3-mongo-target/1-mongo-target/README.mdpackages/3-mongo-target/1-mongo-target/package.jsonpackages/3-mongo-target/1-mongo-target/src/core/migration-factories.tspackages/3-mongo-target/1-mongo-target/src/core/migration-strategies.tspackages/3-mongo-target/1-mongo-target/src/exports/migration.tspackages/3-mongo-target/1-mongo-target/test/migration-e2e.test.tspackages/3-mongo-target/1-mongo-target/test/migration-factories.test.tspackages/3-mongo-target/1-mongo-target/test/migration-strategies.test.tspackages/3-mongo-target/1-mongo-target/tsdown.config.tstest/integration/test/mongo/migration-authoring-e2e.test.ts
There was a problem hiding this comment.
♻️ Duplicate comments (2)
packages/1-framework/3-tooling/migration/src/migration-base.ts (2)
108-110:⚠️ Potential issue | 🟠 MajorValidate
describe()output before manifest creation.Lines 108-110 trust runtime metadata shape. A JS migration (or leaked
any) can emit malformedfrom/to/kind/labelsintomigration.json, which can fail downstream consumers.🛡️ Proposed fix (Arktype runtime validation)
+import { type } from 'arktype'; import { realpathSync, writeFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { dirname, join } from 'pathe'; +const migrationMetaSchema = type({ + from: 'string', + to: 'string', + 'kind?': "'regular' | 'baseline'", + 'labels?': 'string[]', +}); + export interface MigrationMeta { readonly from: string; readonly to: string; readonly kind?: 'regular' | 'baseline'; readonly labels?: readonly string[]; } @@ - const meta: MigrationMeta | undefined = - typeof instance.describe === 'function' ? instance.describe() : undefined; + const rawMeta: unknown = + typeof instance.describe === 'function' ? instance.describe() : undefined; + let meta: MigrationMeta | undefined; + if (rawMeta !== undefined) { + const parsed = migrationMetaSchema(rawMeta); + if (parsed instanceof type.errors) { + throw new Error(`describe() returned invalid metadata: ${parsed.summary}`); + } + meta = parsed; + } const manifest = meta ? buildManifest(meta) : undefined;#!/bin/bash set -euo pipefail # Verify existing Arktype runtime-validation style used in this package/repo. rg -n --type=ts -C2 "from 'arktype'|instanceof type\\.errors|\\.summary" packages/1-framework/3-tooling/migration # Verify current unvalidated describe()->buildManifest path. sed -n '100,116p' packages/1-framework/3-tooling/migration/src/migration-base.tsAs per coding guidelines: "Use Arktype instead of Zod for schema validation and type definitions" and "Use schema validators (Arktype) for structural validation of required fields, types, and shapes rather than redundant manual checks for these properties".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/1-framework/3-tooling/migration/src/migration-base.ts` around lines 108 - 110, The code calls instance.describe() and passes its result straight to buildManifest, risking malformed runtime data; add an Arktype runtime validator for the MigrationMeta shape (e.g., create a migrationMetaValidator using arktype matching MigrationMeta's required fields like from/to/kind/labels), validate the output of instance.describe() before calling buildManifest, and only call buildManifest with the validated value; on validation failure surface a clear error (throw or processLogger.error + exit) and include the Arktype error summary so downstream consumers never receive malformed manifests.
59-69:⚠️ Potential issue | 🟡 MinorHelp output still points to a non-working TS-first invocation.
Line 62 still says
node <migration-file>, which is misleading for.tsmigration files in this workflow.📝 Proposed fix
- 'Usage: node <migration-file> [options]', + 'Usage: tsx <migration-file> [options]',🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/1-framework/3-tooling/migration/src/migration-base.ts` around lines 59 - 69, The help text in printHelp currently says "node <migration-file>" which is misleading for the TS-first workflow; update the usage string inside the printHelp function to reflect invoking TypeScript migrations (for example "ts-node <migration-file.ts> [options]" or the project's actual TS runner), and update the example and any related help lines to mention ".ts" so users see the correct invocation for TypeScript migration files.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@packages/1-framework/3-tooling/migration/src/migration-base.ts`:
- Around line 108-110: The code calls instance.describe() and passes its result
straight to buildManifest, risking malformed runtime data; add an Arktype
runtime validator for the MigrationMeta shape (e.g., create a
migrationMetaValidator using arktype matching MigrationMeta's required fields
like from/to/kind/labels), validate the output of instance.describe() before
calling buildManifest, and only call buildManifest with the validated value; on
validation failure surface a clear error (throw or processLogger.error + exit)
and include the Arktype error summary so downstream consumers never receive
malformed manifests.
- Around line 59-69: The help text in printHelp currently says "node
<migration-file>" which is misleading for the TS-first workflow; update the
usage string inside the printHelp function to reflect invoking TypeScript
migrations (for example "ts-node <migration-file.ts> [options]" or the project's
actual TS runner), and update the example and any related help lines to mention
".ts" so users see the correct invocation for TypeScript migration files.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 1cc53245-8274-4790-a923-a05284fd3b50
📒 Files selected for processing (2)
packages/1-framework/3-tooling/migration/src/migration-base.tspackages/1-framework/3-tooling/migration/test/migration-base.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/1-framework/3-tooling/migration/test/migration-base.test.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/3-mongo-target/1-mongo-target/src/core/migration-factories.ts`:
- Around line 60-64: The CreateIndexCommand construction silently drops an
explicit false for options.unique because the code uses `options?.unique ||
undefined`; replace that with a nullish check or conditional spread so false is
preserved (e.g. use `options?.unique ?? undefined` or spread
`...(options?.unique !== undefined ? { unique: options.unique } : {})`) when
building the command arguments for CreateIndexCommand (refer to the
`CreateIndexCommand`, `options`, `unique`, and `name` symbols).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 1248d5da-58a9-40e8-a35c-88b3842f4d24
⛔ Files ignored due to path filters (5)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlprojects/mongo-migration-authoring/plan.mdis excluded by!projects/**projects/mongo-migration-authoring/spec.mdis excluded by!projects/**projects/mongo-migration-authoring/specs/migration-subsystem-refactor.spec.mdis excluded by!projects/**projects/mongo-migration-authoring/specs/planner-dual-output.spec.mdis excluded by!projects/**
📒 Files selected for processing (18)
examples/mongo-demo/migrations/20260415_add-posts-author-index/migration.tsexamples/mongo-demo/package.jsonexamples/mongo-demo/test/manual-migration.test.tsexamples/retail-store/migrations/20260415_add-product-validation/migration.jsonexamples/retail-store/migrations/20260415_add-product-validation/migration.tsexamples/retail-store/migrations/20260415_add-product-validation/ops.jsonexamples/retail-store/package.jsonexamples/retail-store/test/manual-migration.test.tspackages/1-framework/3-tooling/migration/src/migration-base.tspackages/1-framework/3-tooling/migration/test/migration-base.test.tspackages/2-mongo-family/9-family/src/exports/migration.tspackages/3-mongo-target/1-mongo-target/README.mdpackages/3-mongo-target/1-mongo-target/package.jsonpackages/3-mongo-target/1-mongo-target/src/core/migration-factories.tspackages/3-mongo-target/1-mongo-target/src/exports/migration.tspackages/3-mongo-target/1-mongo-target/test/migration-e2e.test.tspackages/3-mongo-target/1-mongo-target/test/migration-factories.test.tstest/integration/test/mongo/migration-authoring-e2e.test.ts
✅ Files skipped from review due to trivial changes (8)
- examples/retail-store/migrations/20260415_add-product-validation/migration.json
- examples/retail-store/migrations/20260415_add-product-validation/ops.json
- examples/mongo-demo/migrations/20260415_add-posts-author-index/migration.ts
- packages/3-mongo-target/1-mongo-target/README.md
- examples/mongo-demo/package.json
- examples/mongo-demo/test/manual-migration.test.ts
- packages/1-framework/3-tooling/migration/test/migration-base.test.ts
- packages/3-mongo-target/1-mongo-target/test/migration-factories.test.ts
🚧 Files skipped from review as they are similar to previous changes (5)
- packages/2-mongo-family/9-family/src/exports/migration.ts
- packages/3-mongo-target/1-mongo-target/package.json
- packages/3-mongo-target/1-mongo-target/src/exports/migration.ts
- examples/retail-store/migrations/20260415_add-product-validation/migration.ts
- packages/1-framework/3-tooling/migration/src/migration-base.ts
d796c2f to
c52bcc9
Compare
@prisma-next/mongo-runtime
@prisma-next/family-mongo
@prisma-next/sql-runtime
@prisma-next/family-sql
@prisma-next/middleware-telemetry
@prisma-next/mongo
@prisma-next/extension-paradedb
@prisma-next/extension-pgvector
@prisma-next/postgres
@prisma-next/sql-orm-client
@prisma-next/sqlite
@prisma-next/target-mongo
@prisma-next/adapter-mongo
@prisma-next/driver-mongo
@prisma-next/contract
@prisma-next/utils
@prisma-next/config
@prisma-next/errors
@prisma-next/framework-components
@prisma-next/operations
@prisma-next/contract-authoring
@prisma-next/ids
@prisma-next/psl-parser
@prisma-next/psl-printer
@prisma-next/cli
@prisma-next/emitter
@prisma-next/migration-tools
@prisma-next/vite-plugin-contract-emit
@prisma-next/runtime-executor
@prisma-next/mongo-codec
@prisma-next/mongo-contract
@prisma-next/mongo-value
@prisma-next/mongo-contract-psl
@prisma-next/mongo-contract-ts
@prisma-next/mongo-emitter
@prisma-next/mongo-schema-ir
@prisma-next/mongo-query-ast
@prisma-next/mongo-orm
@prisma-next/mongo-pipeline-builder
@prisma-next/mongo-lowering
@prisma-next/mongo-wire
@prisma-next/sql-contract
@prisma-next/sql-errors
@prisma-next/sql-operations
@prisma-next/sql-schema-ir
@prisma-next/sql-contract-psl
@prisma-next/sql-contract-ts
@prisma-next/sql-contract-emitter
@prisma-next/sql-lane-query-builder
@prisma-next/sql-relational-core
@prisma-next/sql-builder
@prisma-next/target-postgres
@prisma-next/target-sqlite
@prisma-next/adapter-postgres
@prisma-next/adapter-sqlite
@prisma-next/driver-postgres
@prisma-next/driver-sqlite
commit: |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/1-framework/3-tooling/migration/src/migration-base.ts (1)
114-114: Redundant type check fordescribemethod.Since
describe()is defined on the abstractMigrationbase class (returningundefinedby default),typeof instance.describe === 'function'will always betrue. The check is defensive but unnecessary given the class hierarchy.This is a minor nit and safe to keep for robustness if desired.
♻️ Optional simplification
let manifest: Record<string, unknown> | undefined; - if (typeof instance.describe === 'function') { - const rawMeta: unknown = instance.describe(); - if (rawMeta !== undefined) { - const parsed = MigrationMetaSchema(rawMeta); - if (parsed instanceof type.errors) { - throw new Error(`describe() returned invalid metadata: ${parsed.summary}`); - } - manifest = buildManifest(parsed); + const rawMeta: unknown = instance.describe(); + if (rawMeta !== undefined) { + const parsed = MigrationMetaSchema(rawMeta); + if (parsed instanceof type.errors) { + throw new Error(`describe() returned invalid metadata: ${parsed.summary}`); } + manifest = buildManifest(parsed); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/1-framework/3-tooling/migration/src/migration-base.ts` at line 114, The typeof check around instance.describe is redundant because the abstract Migration class defines describe (returns undefined by default); remove the conditional guard and call instance.describe() directly where it's used (reference the Migration base class and the instance.describe method in migration-base.ts) so the code simplifies to a straight invocation while preserving behavior; alternatively, if you want to keep defensive checks, replace the typeof guard with a comment explaining why it remains.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/1-framework/3-tooling/migration/src/migration-base.ts`:
- Line 114: The typeof check around instance.describe is redundant because the
abstract Migration class defines describe (returns undefined by default); remove
the conditional guard and call instance.describe() directly where it's used
(reference the Migration base class and the instance.describe method in
migration-base.ts) so the code simplifies to a straight invocation while
preserving behavior; alternatively, if you want to keep defensive checks,
replace the typeof guard with a comment explaining why it remains.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 8de708a8-f386-485c-9825-62ff6e1e7db6
📒 Files selected for processing (5)
examples/mongo-demo/migrations/20260415_add-posts-author-index/migration.tsexamples/retail-store/migrations/20260415_add-product-validation/migration.tspackages/1-framework/3-tooling/migration/src/migration-base.tspackages/1-framework/3-tooling/migration/test/migration-base.test.tspackages/3-mongo-target/1-mongo-target/test/migration-e2e.test.ts
✅ Files skipped from review due to trivial changes (1)
- packages/1-framework/3-tooling/migration/test/migration-base.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- examples/retail-store/migrations/20260415_add-product-validation/migration.ts
- examples/mongo-demo/migrations/20260415_add-posts-author-index/migration.ts
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (4)
test/integration/test/mongo/migration-authoring-e2e.test.ts (2)
203-208: Use object matchers for related field checks.These assertions check related fields one-by-one; prefer a single object matcher for clearer intent and guideline consistency.
Example refactor pattern
- for (let i = 0; i < original.length; i++) { - expect(deserialized[i]!.id).toBe(original[i]!.id); - expect(deserialized[i]!.label).toBe(original[i]!.label); - expect(deserialized[i]!.operationClass).toBe(original[i]!.operationClass); - } + for (let i = 0; i < original.length; i++) { + expect(deserialized[i]).toMatchObject({ + id: original[i]!.id, + label: original[i]!.label, + operationClass: original[i]!.operationClass, + }); + }As per coding guidelines: "
**/*.test.ts: Prefer object matchers (toMatchObject) over multiple individual expect().toBe() calls when checking 2 or more related values in tests".Also applies to: 230-232, 255-257
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/integration/test/mongo/migration-authoring-e2e.test.ts` around lines 203 - 208, The loop at lines checking deserialized[i] against original[i] should replace multiple per-field expects with a single object matcher: use expect(deserialized[i]).toMatchObject({ id: original[i].id, label: original[i].label, operationClass: original[i].operationClass }) inside the same loop (and similarly refactor the other occurrences noted around the file at the blocks currently at 230-232 and 255-257) so tests assert related fields together using toMatchObject.
299-350: ReuserunOpspath in lifecycle steps to avoid drift and strengthen assertions.Step 2/3 duplicate runner wiring and only assert
result.ok. Reusing a single helper path (with optional origin/destination hashes) will reduce duplication and let you assertoperationsExecutedconsistently.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/integration/test/mongo/migration-authoring-e2e.test.ts` around lines 299 - 350, The test duplicates MongoMigrationRunner wiring for step2/step3 and only asserts result.ok; refactor to reuse the existing runOps helper (or create one if missing) to execute migrations with optional origin/destination hashes so both steps call runOps(serializedOps, { originHash?, destinationHash? }) instead of repeating create/close/controlDriver/runner.execute logic; then assert not only result.ok but also the runner's operationsExecuted (or the helper's returned operationsExecuted) for each step to ensure operations were applied and avoid lifecycle drift—target symbols: runOps, MongoMigrationRunner, runner.execute, operationsExecuted, serialized2/serialized3.examples/mongo-demo/test/manual-migration.test.ts (2)
54-56: Consolidate related operation assertions into one object matcher.These are related checks on the same structure; prefer a single matcher to align with repo test style.
♻️ Proposed refactor
const instance = new AddPostsAuthorIndex(); const ops = instance.plan(); expect(ops).toHaveLength(2); - expect(ops[0].id).toBe('index.posts.create(authorId:1)'); - expect(ops[1].id).toBe('index.posts.create(createdAt:-1,authorId:1)'); + expect(ops).toMatchObject([ + { id: 'index.posts.create(authorId:1)' }, + { id: 'index.posts.create(createdAt:-1,authorId:1)' }, + ]);As per coding guidelines:
examples/**/test/**/*.{ts,js}: Prefer object matchers (toMatchObject) over multiple individual expect().toBe() calls when checking 2 or more related values in tests.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/mongo-demo/test/manual-migration.test.ts` around lines 54 - 56, The test currently asserts related properties of the same ops array using multiple expect(...).toBe calls; replace those with a single object matcher: assert ops length is 2 and use toMatchObject (or toEqual with partial objects) on ops to verify both entries at once (e.g., match ops[0].id and ops[1].id) so the assertions consolidate into one object matcher for the ops array; update assertions referencing ops, ops[0].id and ops[1].id accordingly.
62-67: Use a single manifest shape assertion instead of field-by-fieldtoBechecks.These fields are one related payload; use
toMatchObjectwith string matchers for the formatted fields.♻️ Proposed refactor
- expect(manifest.migrationId).toBeNull(); - expect(manifest.kind).toBe('regular'); - expect(manifest.labels).toEqual(['add-posts-author-index']); - expect(manifest.from).toMatch(/^sha256:/); - expect(manifest.to).toMatch(/^sha256:/); - expect(manifest.createdAt).toMatch(/^\d{4}-\d{2}-\d{2}T/); + expect(manifest).toMatchObject({ + migrationId: null, + kind: 'regular', + labels: ['add-posts-author-index'], + from: expect.stringMatching(/^sha256:/), + to: expect.stringMatching(/^sha256:/), + createdAt: expect.stringMatching(/^\d{4}-\d{2}-\d{2}T/), + });As per coding guidelines:
examples/**/test/**/*.{ts,js}: Prefer object matchers (toMatchObject) over multiple individual expect().toBe() calls when checking 2 or more related values in tests.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/mongo-demo/test/manual-migration.test.ts` around lines 62 - 67, Replace the multiple field-by-field assertions on the manifest with a single object-shape assertion: use expect(manifest).toMatchObject({...}) to assert migrationId, kind, labels exactly and use expect.stringMatching(/regex/) for formatted strings (for example use expect.stringMatching(/^sha256:/) for from and to and expect.stringMatching(/^\d{4}-\d{2}-\d{2}T/) for createdAt); update the test in manual-migration.test.ts to assert the whole manifest shape in one toMatchObject call rather than separate expect(...).toBe() assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/2-mongo-family/9-family/package.json`:
- Line 50: The package export adds a plane-specific subpath "./migration" which
violates the multi-plane subpath contract; update the package.json exports by
removing the "./migration" subpath and expose that same module under the
migration/control plane subpath (use "./control" as the export key) so the
existing target module (the current "./dist/migration.mjs" artifact) is
reachable via "./control"; ensure no duplicate plane subpaths remain and that
any consumers referencing "./migration" are updated to use "./control".
In `@test/integration/test/mongo/migration-authoring-e2e.test.ts`:
- Around line 50-56: The teardown's single try block can skip replSet?.stop() if
client?.close() throws; update the afterAll teardown so both resources are
always attempted independently (e.g., call client?.close() in its own try/catch
and replSet?.stop() in a separate try/catch, or use a try/finally where close is
attempted then replSet.stop() in finally). Locate the afterAll block with calls
to client?.close() and replSet?.stop() and ensure errors from one do not prevent
the other from running, logging or ignoring each error separately.
---
Nitpick comments:
In `@examples/mongo-demo/test/manual-migration.test.ts`:
- Around line 54-56: The test currently asserts related properties of the same
ops array using multiple expect(...).toBe calls; replace those with a single
object matcher: assert ops length is 2 and use toMatchObject (or toEqual with
partial objects) on ops to verify both entries at once (e.g., match ops[0].id
and ops[1].id) so the assertions consolidate into one object matcher for the ops
array; update assertions referencing ops, ops[0].id and ops[1].id accordingly.
- Around line 62-67: Replace the multiple field-by-field assertions on the
manifest with a single object-shape assertion: use
expect(manifest).toMatchObject({...}) to assert migrationId, kind, labels
exactly and use expect.stringMatching(/regex/) for formatted strings (for
example use expect.stringMatching(/^sha256:/) for from and to and
expect.stringMatching(/^\d{4}-\d{2}-\d{2}T/) for createdAt); update the test in
manual-migration.test.ts to assert the whole manifest shape in one toMatchObject
call rather than separate expect(...).toBe() assertions.
In `@test/integration/test/mongo/migration-authoring-e2e.test.ts`:
- Around line 203-208: The loop at lines checking deserialized[i] against
original[i] should replace multiple per-field expects with a single object
matcher: use expect(deserialized[i]).toMatchObject({ id: original[i].id, label:
original[i].label, operationClass: original[i].operationClass }) inside the same
loop (and similarly refactor the other occurrences noted around the file at the
blocks currently at 230-232 and 255-257) so tests assert related fields together
using toMatchObject.
- Around line 299-350: The test duplicates MongoMigrationRunner wiring for
step2/step3 and only asserts result.ok; refactor to reuse the existing runOps
helper (or create one if missing) to execute migrations with optional
origin/destination hashes so both steps call runOps(serializedOps, {
originHash?, destinationHash? }) instead of repeating
create/close/controlDriver/runner.execute logic; then assert not only result.ok
but also the runner's operationsExecuted (or the helper's returned
operationsExecuted) for each step to ensure operations were applied and avoid
lifecycle drift—target symbols: runOps, MongoMigrationRunner, runner.execute,
operationsExecuted, serialized2/serialized3.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: ed4fff7d-9d4c-4a29-b2ae-cff615ab1b94
⛔ Files ignored due to path filters (6)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlprojects/mongo-migration-authoring/assets/migration-authoring-design.mdis excluded by!projects/**projects/mongo-migration-authoring/plan.mdis excluded by!projects/**projects/mongo-migration-authoring/spec.mdis excluded by!projects/**projects/mongo-migration-authoring/specs/migration-subsystem-refactor.spec.mdis excluded by!projects/**projects/mongo-migration-authoring/specs/planner-dual-output.spec.mdis excluded by!projects/**
📒 Files selected for processing (28)
examples/mongo-demo/migrations/20260415_add-posts-author-index/migration.jsonexamples/mongo-demo/migrations/20260415_add-posts-author-index/migration.tsexamples/mongo-demo/migrations/20260415_add-posts-author-index/ops.jsonexamples/mongo-demo/package.jsonexamples/mongo-demo/test/manual-migration.test.tsexamples/retail-store/migrations/20260415_add-product-validation/migration.jsonexamples/retail-store/migrations/20260415_add-product-validation/migration.tsexamples/retail-store/migrations/20260415_add-product-validation/ops.jsonexamples/retail-store/package.jsonexamples/retail-store/test/manual-migration.test.tspackages/1-framework/3-tooling/migration/package.jsonpackages/1-framework/3-tooling/migration/src/exports/migration.tspackages/1-framework/3-tooling/migration/src/migration-base.tspackages/1-framework/3-tooling/migration/test/migration-base.test.tspackages/1-framework/3-tooling/migration/tsdown.config.tspackages/2-mongo-family/9-family/README.mdpackages/2-mongo-family/9-family/package.jsonpackages/2-mongo-family/9-family/src/core/mongo-migration.tspackages/2-mongo-family/9-family/src/exports/migration.tspackages/2-mongo-family/9-family/tsdown.config.tspackages/3-mongo-target/1-mongo-target/README.mdpackages/3-mongo-target/1-mongo-target/package.jsonpackages/3-mongo-target/1-mongo-target/src/core/migration-factories.tspackages/3-mongo-target/1-mongo-target/src/exports/migration.tspackages/3-mongo-target/1-mongo-target/test/migration-e2e.test.tspackages/3-mongo-target/1-mongo-target/test/migration-factories.test.tspackages/3-mongo-target/1-mongo-target/tsdown.config.tstest/integration/test/mongo/migration-authoring-e2e.test.ts
✅ Files skipped from review due to trivial changes (17)
- packages/1-framework/3-tooling/migration/tsdown.config.ts
- examples/retail-store/package.json
- packages/2-mongo-family/9-family/src/exports/migration.ts
- packages/2-mongo-family/9-family/tsdown.config.ts
- examples/mongo-demo/migrations/20260415_add-posts-author-index/migration.json
- packages/3-mongo-target/1-mongo-target/src/exports/migration.ts
- packages/3-mongo-target/1-mongo-target/tsdown.config.ts
- packages/2-mongo-family/9-family/src/core/mongo-migration.ts
- examples/retail-store/migrations/20260415_add-product-validation/migration.json
- packages/3-mongo-target/1-mongo-target/README.md
- examples/mongo-demo/migrations/20260415_add-posts-author-index/ops.json
- examples/mongo-demo/package.json
- examples/retail-store/migrations/20260415_add-product-validation/ops.json
- examples/retail-store/migrations/20260415_add-product-validation/migration.ts
- packages/1-framework/3-tooling/migration/src/exports/migration.ts
- packages/3-mongo-target/1-mongo-target/test/migration-factories.test.ts
- packages/1-framework/3-tooling/migration/src/migration-base.ts
🚧 Files skipped from review as they are similar to previous changes (8)
- packages/1-framework/3-tooling/migration/package.json
- packages/3-mongo-target/1-mongo-target/package.json
- examples/mongo-demo/migrations/20260415_add-posts-author-index/migration.ts
- examples/retail-store/test/manual-migration.test.ts
- packages/2-mongo-family/9-family/README.md
- packages/1-framework/3-tooling/migration/test/migration-base.test.ts
- packages/3-mongo-target/1-mongo-target/test/migration-e2e.test.ts
- packages/3-mongo-target/1-mongo-target/src/core/migration-factories.ts
Scaffold project for adding a TypeScript migration authoring surface to the Mongo target. Factory functions produce operations directly, migration files are self-executing via a Migration base class, and strategies are plain function composition over the factories.
Five factory functions (createIndex, dropIndex, createCollection, dropCollection, collMod) that produce MongoMigrationPlanOperation objects identical to what the planner generates. Extracted from the planner's inline logic, reusing existing AST primitives and helpers. Exported from @prisma-next/target-mongo/migration.
Generic Migration<TOperation> with abstract plan() and static run() for self-executing migration files. Entrypoint detection uses import.meta.url (not import.meta object) for tsx compatibility. Supports --dry-run and --help flags. Exported from @prisma-next/migration-tools/migration.
MongoMigration extends Migration<MongoMigrationPlanOperation> so users get a single import for both Migration and factory functions from @prisma-next/target-mongo/migration.
validatedCollection composes createCollection (with validator) + createIndex calls into a flat operation list. E2E tests verify the full pipeline: write migration.ts, run with tsx, validate ops.json structure, --dry-run output, and strategy composition.
Add migration entrypoint, usage example, factory and strategy reference to the package README.
Migration files can now implement describe() to provide metadata (from, to, kind, labels). When present, Migration.run() writes both ops.json and migration.json. The manifest is a draft (migrationId: null) with createdAt auto-set. Dry-run prints both files to stdout.
MongoMigration is a family-level concern (not target-specific). Canonical import is now @prisma-next/family-mongo/migration which re-exports factories and strategies from @prisma-next/target-mongo/migration.
Covers all five factory functions (createCollection, createIndex, dropIndex, dropCollection, collMod) and the validatedCollection strategy. Verifies the full round-trip: factory → JSON.stringify → deserializeMongoOps → MongoMigrationRunner → verify DDL in MongoDB. Also tests a multi-step create → modify → drop lifecycle.
Canonical import for migration authoring is now @prisma-next/family-mongo/migration. Updated both target-mongo and family-mongo READMEs with correct import paths and describe() example.
Demonstrates the migration authoring workflow: a TypeScript migration file using factory functions and describe() to produce both ops.json and migration.json. Test verifies the migration imports, runs against a real MongoDB, and produces valid artifacts.
Demonstrates collMod (JSON Schema validation on products) and compound index creation. Test verifies the migration can be imported, run against a real MongoDB, and produces valid artifacts.
…hods noImplicitOverride is enabled in the shared tsconfig base, requiring the override keyword on methods that override base class members.
Two task specs under the mongo-migration-authoring project: 1. migration-subsystem-refactor: move planner, runner, serializer, and supporting modules from adapter-mongo to target-mongo; refactor runner to accept abstract visitor interfaces instead of Db. 2. planner-dual-output: introduce OpFactoryCall intermediate representation, with renderers for raw operations (existing behavior) and TypeScript migration files.
- Replace node:path with pathe in E2E and demo test files (F01, F05) - Remove unused collection param from keyFilter helper (F02) - Add optional operationClass override to collMod factory (F03) - Remove factory re-exports from family-mongo/migration (F06) - Split demo migration imports: Migration from family-mongo, factories from target-mongo
- Migration.run(import.meta) -> Migration.run(import.meta.url) - Document describe() and migration.json as optional features - Document collMod operationClass override parameter
…strategies - Remove thin collMod wrapper; add setValidation factory with schema-level API - Move validatedCollection from separate strategies file into factories - Delete migration-strategies.ts and its test file - Update README to remove atomic/non-atomic differentiation - Update demo migrations and all tests to use new API
…tion - Rewrite doc comment to clearly explain entrypoint guard behavior - Rename executeMigration to serializeMigration (it serializes, not executes) - Update help text from node to tsx - Validate describe() return with arktype before building manifest
- Replace dynamic await import() with static imports for migration classes - Load migration.json from disk to verify structure - Remove unused Migration import from mongo-demo test
…d of re-importing Eliminates the dynamic import() in serializeMigration by accepting the migration class directly. This makes the dependency graph static and the serialization fully synchronous. API change: Migration.run(import.meta.url, MyMigration)
Use Result.failure (not .error) and cast CollectionInfo to Record<string, unknown> for options access.
Spec and plan for adding data transform support to MongoDB migrations. Users author transforms using existing query builders (mongoRaw, mongoPipeline), which produce MongoQueryPlan ASTs from a scaffolded contract. Plans serialize to ops.json as JSON using the same kind-based pattern as DDL commands and execute at apply time via MongoAdapter.
…rity Restructure to lead with the problem and a grounding example, build the narrative progressively (authoring → serialization → execution), move decisions before implementation details, and push alternatives considered to the end.
Replace || with ?? to avoid coercing false to undefined.
Ensures replSet.stop() runs even if client.close() throws.
3db0eed to
4ecabe1
Compare
closes TML-2244
Intent
Enable users to author MongoDB migrations by hand in TypeScript. A migration file exports a class, runs as a standalone script (
tsx migration.ts), and producesops.jsonandmigration.jsonthat the existingMongoMigrationRunnerconsumes unchanged. The pattern is designed to generalize to SQL targets later.Change map
Migration<TOperation>base class,MigrationMeta, self-execution, manifest outputvalidatedCollectioncompound strategyMongoMigrationtype-fixed aliasThe story
Factory functions for the five Mongo DDL operations. Each function (
createIndex,dropIndex,createCollection,dropCollection,collMod) produces aMongoMigrationPlanOperationwith correct prechecks, DDL commands, and postchecks — identical output to the existing planner.A target-agnostic
Migration<TOperation>base class. Lives in@prisma-next/migration-tools(framework layer). Providesplan()(abstract),describe()(optional metadata formigration.json), andstatic run(import.meta.url)(self-execution with entrypoint detection,--dry-run,--help).A Mongo-specific
MongoMigrationalias in the family package. Fixes the type parameter toMongoMigrationPlanOperation. Exported from@prisma-next/family-mongo/migrationalongside the re-exported factories and strategies — a single import point for users.Compound strategy functions.
validatedCollectioncomposescreateCollection+createIndexcalls into a reusable multi-operation helper, demonstrating the composition pattern users would follow.migration.jsonoutput. Whendescribe()is implemented,Migration.run()writes a draft manifest (migrationId: null) alongsideops.json, withfrom/tohashes,kind,labels, andcreatedAt.Real-DB E2E tests. Integration tests exercise the full round-trip (factory →
JSON.stringify→deserializeMongoOps→MongoMigrationRunner→ verify DDL in MongoDB Memory Server) for all five operations and the compound strategy.Demo app migrations. Both
mongo-demoandretail-storeinclude a hand-authored.tsmigration alongside their existing planner-generated migration, with tests that verify the migration imports, generates valid artifacts, and executes against a real DB.Behavior changes & evidence
Adds migration factory functions producing
MongoMigrationPlanOperationobjects: Five factory functions (createIndex,dropIndex,createCollection,dropCollection,collMod) that produce the same operation structure the planner does, with correct prechecks/postchecks.collModfor schema validation, custom index strategies).Adds a self-executing
Migrationbase class:Migration<TOperation>in the framework withplan(),describe(), andstatic run(import.meta.url). Handles entrypoint detection (run vs import),--dry-run(stdout preview),--help(usage), and file writing (ops.json+ optionalmigration.json).tsx migration.ts).Adds
MongoMigrationalias in@prisma-next/family-mongo: A type-fixedMigration<MongoMigrationPlanOperation>subclass, exported alongside factories from@prisma-next/family-mongo/migrationas the canonical user import.MongoMigrationis a family-level concern (not target-specific). The single import point simplifies the authoring experience.Adds
validatedCollectioncompound strategy: ComposescreateCollection(with JSON Schema validator) +createIndexcalls into a flat operation list.Adds demo app hand-authored migrations: Both
mongo-demoandretail-storeinclude a.tsmigration alongside their existing planner-generated migration, with generatedops.json+migration.jsoncommitted as evidence.migrations/directory.Compatibility / migration / risk
MongoMigrationPlannerandMongoMigrationRunnerare untouched. Factory-produced operations are indistinguishable from planner-produced ones.import.meta.urlvsimport.meta: The spec saysMigration.run(import.meta). The implementation usesMigration.run(import.meta.url)becausetsxdoes not preserveimport.metaproperties when the object is passed as a function argument. This is a necessary adaptation for the dev toolchain.Migrationare co-located in@prisma-next/target-mongo/migration. The implementation movesMongoMigrationto@prisma-next/family-mongo/migration(a higher layer) to better reflect the family-level concern, and uses the family package as the canonical user import. Factories remain in target-mongo; family-mongo re-exports them.describe()andmigration.json: The spec does not mention manifest output. The implementation adds an optionaldescribe()method andmigration.jsonwriting, which is additive and opt-in.Follow-ups / open questions
prisma migration new/plan/verifyfor Mongo) — explicitly deferred in specmigration.tsfrom planner output) — future workMigration.run(import.meta)— the spec should be updated to reflect theimport.meta.urldecisionNon-goals / intentionally out of scope
Summary by CodeRabbit
New Features
Examples
Documentation
Tests