Skip to content

TML-2953: type Mongo enum fields from a stored value set (like SQL)#900

Merged
wmadden-electric merged 6 commits into
mainfrom
tml-2953-mongo-store-enum-values-the-same-way-sql-does
Jul 2, 2026
Merged

TML-2953: type Mongo enum fields from a stored value set (like SQL)#900
wmadden-electric merged 6 commits into
mainfrom
tml-2953-mongo-store-enum-values-the-same-way-sql-does

Conversation

@wmadden-electric

@wmadden-electric wmadden-electric commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

At a glance

A Mongo model with an enum field:

enum UserRole {
  @@type("mongo/string@1")
  Admin  = "admin"
  Author = "author"
  Reader = "reader"
}

model User {
  role UserRole
}

Reading role back gives you the union of its allowed values — not string:

const u = await db.user.findOne({ where: { id } })
u.role   // 'admin' | 'author' | 'reader'

That already worked. What this PR changes is where that union comes from. Previously Mongo read the allowed values straight off the domain enum. Now they live once, in the storage block, as a named value set — and the field's type and the collection's validator are both built from it:

// contract.json → storage
"entries": {
  "valueSet": {
    "UserRole": { "kind": "valueSet", "values": ["admin", "author", "reader"] }
  },
  "collection": {
    "users": { "validator": { /* $jsonSchema "enum" built from the value set */ } }
  }
}

The decision

A field's type is determined by its value set — the union of the codec-rendered literals of its allowed values — not the plain codec type. That is the primitive SQL already uses (shipped in #896); this PR brings Mongo onto it. The domain enum stops being a typing or enforcement input and becomes runtime-only: it still powers db.enums, and nothing else.

Why this is worth doing, beyond removing a SQL/Mongo divergence: a "value set" is a generic restriction — "the permitted values here are x, y, z". A domain enum is one thing that produces one; a check constraint, a range, or a native database enum could produce one too, and each would be typed through the identical path with no enum-specific code. This closes the last place Mongo typed a field by reaching for the enum directly.

What it does

  • Adds the value-set entity to Mongo storage, the same shape as SQL's ({ kind: 'valueSet', values }, codec-encoded, at storage.namespaces[ns].entries.valueSet[Name]).
  • Authoring emits it — the Mongo PSL interpreter and the TypeScript builder write the value set alongside the domain enum.
  • Typing and the validator read it — the emitter types fields from the value set (through the shared codec renderer that TML-2952: type SQL enum columns through the codec instead of printing their stored values #896 added), and the $jsonSchema enum keyword is built from it. The code that read domain.enum for these is deleted; db.enums is the only reader of domain.enum left.

Why it's safe

  • Nothing observable changes. The value set's values are exactly what the domain enum produced, so the switch-over is byte-identical: the emitted types and the validator are unchanged, and fixtures:check is clean across it.
  • No migrations. A value set is a typing/contract entity with no database object of its own — the collection validator is the physical artifact, and it is unchanged. The planner only walks collections, so adding a value set produces zero migration operations; db verify and migration behaviour are unchanged (pinned by a test).
  • For the same reason this is uniformity, not a bug fix: Mongo's validator already carries the enum values inline in the storage block that storageHash covers, so an enum change was already tracked.

How it's verified

  • A Mongo enum field types as the value union on the emitted contract.d.ts (both the ORM row and FieldOutputTypes) and on typeof contract, matching SQL's shape — a typecheck-enforced test.
  • A non-identity mock codec (stores 0|1|2, reads back 'low'|'high'|'urgent') proves the type is produced through the codec, not by printing the stored value.
  • Build, typecheck, lints, fixtures:check, upgrade-coverage, and the Mongo suites are green; no new casts.

Upgrade (0.14 → 0.15)

  • Users: no action. Contracts regenerate to carry the value set, but the emitted types and the validator are identical and db.enums is unchanged.
  • Extension authors: deriveJsonSchema / derivePolymorphicJsonSchema (public @prisma-next/mongo-contract-psl exports) now take a value-set map instead of a domain-enum map.

Alternatives considered

  • Give the field an explicit stored reference to its value set, and make the Mongo query builder type straight from the storage block (as SQL's does). Deferred to TML-2961. It needs an explicit per-collection document-structure projection, which nothing here requires: Mongo's query builder types via FieldOutputTypes, and the feature that would drive storage-only typing — native Postgres enums — is Postgres-only and never touches Mongo. This PR links a field to its value set by name in the emitter instead, which is enough for every consumer that needs it today.
  • Rework the typeof contract path to read the value set too. Unnecessary. That path is handed the authored literals directly and is already the value union — the same posture SQL keeps.

Follow-up: TML-2961 — the explicit Mongo document-structure projection.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added support for stored enum value sets in Mongo contracts, including schema derivation, contract serialization, and target planning behavior.
    • Exposed Mongo codec descriptors via a new public codecs entry point.
  • Bug Fixes
    • Improved contract hashing and migration fingerprints to account for value-set content.
    • Ensured enum values are encoded/typed consistently through the configured codec, with clearer errors when a required enum codec is missing.
  • Tests
    • Added/updated coverage for value-set hydration, JSON round-trips, schema validation, and emitted type behavior.

…TML-2953)

Bring Mongo enum typing onto the storage value set, mirroring the shipped SQL
work: add a value-set entity to Mongo storage (same shape as SQL), source the
$jsonSchema validator and the emit typing from it instead of domain.enum, and
delete the interim resolver. Uniformity + value-set-driven typing, not a
storageHash fix (the validator is already materialized in storage). Field to
value-set link stays by-name in the emitter; the explicit ref + storage-only
query builder are deferred to TML-2961.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Mirror SQL StorageValueSet in the Mongo family: MongoValueSet
({ kind: 'valueSet', values }, codec-encoded, no codecId), a valueSet slot on
the namespace entries (contract.storage.namespaces[ns].entries.valueSet[Name]),
serializer/hydration via the entity-kind registry, and the arktype schema.
Round-trips and validates. Nothing reads it yet — authoring populates it next,
typing/validator source from it after.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…-2953)

Both Mongo authoring paths (TS builder + PSL interpreter) now emit the storage
value set into entries.valueSet (values = codec-encoded member values), mirroring
SQL build-contract, and thread it through the hashed storage body. The Mongo
target serializer, which serialized only entries.collection, now carries valueSet
on both the serialize and hydrate paths; widen the namespace entries input type so
authoring places a value set without a cast.

Example contracts (mongo-demo, retail-store) regenerate to carry the value set;
the physical migration ops are unchanged (ops.json byte-identical) — the planner
walks only entries.collection, so the value set is inherently non-physical (zero
migration ops), verified by test. Typing/validator still read domain.enum here;
re-sourced next.

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…t (TML-2953)

Re-source the Mongo emit typing and the $jsonSchema validator from the storage
value set instead of domain.enum, and delete the interim resolver. resolveFieldValueSet
reads storage.namespaces[ns].entries.valueSet[name] (codecId from the field);
derive-json-schema takes a value-set map and sources the enum keyword from it, so it
structurally cannot read domain.enum. The interpreter threads the value sets to the
deriver and still emits domain.enum for the db.enums runtime dictionary (the keep).

Byte-identical: fixtures:check clean, zero example contract changes (the value set
values equal what domain.enum produced), FieldOutputTypes and the validator unchanged.
No Mongo emitter or validator path reads domain.enum; only db.enums does. Document the
identity guarantee at the two value-set-build sites (enum member values are JsonValue,
so the codec encodeJson is identity by construction).

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Emit/no-emit type-parity test (real emitted contract.d.ts): a Mongo enum field
types as the value union on FieldOutputTypes, the ORM row, and typeof contract,
matching SQL. A codec-through-path test with a non-identity mock lookup proves
the emit typing flows through renderValueSetType/renderValueLiteralFor (codec
output, not the encoded value), not a raw print.

Record the 0.14->0.15 upgrade entries: user side incidental (contracts regenerate
to carry the value set; emitted types + validator byte-identical; db.enums
unchanged; no user action); extension-author entry for the deriveJsonSchema /
derivePolymorphicJsonSchema signature change (domain-enum map -> value-set map).

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
@wmadden-electric wmadden-electric requested a review from a team as a code owner July 2, 2026 07:20
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@wmadden-electric, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 23 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 81a89948-0466-4458-a1a5-4063751f3434

📥 Commits

Reviewing files that changed from the base of the PR and between e2e254f and 0d187b4.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (20)
  • packages/1-framework/1-core/errors/src/control.ts
  • packages/1-framework/1-core/errors/src/exports/control.ts
  • packages/1-framework/1-core/errors/test/control.test.ts
  • packages/1-framework/1-core/framework-components/src/control/control-stack.ts
  • packages/2-mongo-family/2-authoring/contract-psl/package.json
  • packages/2-mongo-family/2-authoring/contract-psl/src/interpreter.ts
  • packages/2-mongo-family/2-authoring/contract-ts/package.json
  • packages/2-mongo-family/2-authoring/contract-ts/src/contract-builder.ts
  • packages/2-mongo-family/2-authoring/contract-ts/test/enum-type.authoring.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-execution-stack.test.ts
  • packages/3-mongo-target/1-mongo-target/src/core/descriptor-meta.ts
  • packages/3-mongo-target/1-mongo-target/src/exports/pack.ts
  • packages/3-mongo-target/1-mongo-target/test/descriptor-meta.test.ts
  • packages/3-mongo-target/1-mongo-target/test/mongo-planner.test.ts
  • packages/3-mongo-target/1-mongo-target/test/mongo-target-contract-serializer.test.ts
  • packages/3-mongo-target/2-mongo-adapter/package.json
  • packages/3-mongo-target/2-mongo-adapter/src/exports/codecs.ts
  • packages/3-mongo-target/2-mongo-adapter/src/exports/control.ts
  • packages/3-mongo-target/2-mongo-adapter/src/exports/runtime.ts
  • packages/3-mongo-target/2-mongo-adapter/tsdown.config.ts
📝 Walkthrough

Walkthrough

Adds Mongo valueSet storage support for enum values, wires it through authoring, emission, target serialization, generated example contracts, and related upgrade guidance.

Changes

Mongo valueSet feature

Layer / File(s) Summary
MongoValueSet IR and schema
packages/2-mongo-family/1-foundation/mongo-contract/src/ir/mongo-value-set.ts, .../contract-schema.ts, .../entity-kinds.ts, .../ir/mongo-storage.ts, .../exports/*, .../test/*
Adds MongoValueSet/MongoValueSetInput, StorageValueSetSchema, and valueSetEntityKind; registers it in composeMongoEntityKinds; extends namespace entry types; adds tests for construction, hydration, freezing, and schema validation.
Contract authoring and JSON-schema derivation
packages/2-mongo-family/2-authoring/contract-psl/src/*, contract-ts/src/contract-builder.ts, related tests
Derives storageValueSets from enums in interpreter/contract-builder and attaches to the unbound namespace/storage hash; reworks deriveJsonSchema/derivePolymorphicJsonSchema to source enum keywords from a FieldValueSets map instead of ContractEnum.
Emitter valueSet resolution and codec typing
packages/2-mongo-family/3-tooling/emitter/src/index.ts, package.json, tests
Changes resolveFieldValueSet to read encoded values from contract.storage...entries.valueSet and codecId from field type; adds @prisma-next/utils dependency and tests for resolution precedence and codec-decoded literal typing.
Mongo target database, serializer, and codec descriptor plumbing
packages/1-framework/1-core/framework-components/src/control/control-stack.ts, packages/3-mongo-target/1-mongo-target/src/core/*, packages/3-mongo-target/1-mongo-target/src/exports/*, packages/3-mongo-target/2-mongo-adapter/*, test/*
Expands MongoTargetDatabaseInput.entries and contract serialization for valueSet entries, updates codec descriptor ownership and target pack metadata, and adds the adapter codecs export plus related tests.
Codec lookup errors and runtime codec export
packages/1-framework/1-core/errors/src/*, packages/1-framework/1-core/errors/test/*, packages/3-mongo-target/2-mongo-adapter/*
Adds the missing-codec structured error, re-exports it, updates the Mongo adapter runtime and control exports, and adds the codec subpath export.
Regenerated example contracts, migrations, and type tests
examples/mongo-demo/*, examples/retail-store/*
Updates generated contract/migration JSON and .d.ts files with new valueSet entries and updated hashes; adds a type-level test validating enum typing consistency.
Upgrade guide documentation
skills/.../0.14-to-0.15/instructions.md
Documents the parameter and storage semantics changes for extension authors and end users.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • prisma/prisma-next#750: Same enum→storage value-set groundwork reflected in the regenerated mongo-demo contract/migration artifacts.
  • prisma/prisma-next#812: Builds on the same open, kind-keyed entries dictionary refactor extended here with the valueSet entity kind.
  • prisma/prisma-next#826: Extends the same descriptor-driven entity-kind system with valueSetEntityKind and composeMongoEntityKinds updates.

Suggested reviewers: wmadden

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: Mongo enum fields are now typed from a stored value set.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tml-2953-mongo-store-enum-values-the-same-way-sql-does

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

size-limit report 📦

Path Size
postgres / no-emit 160.2 KB (0%)
postgres / emit 147.39 KB (+0.01% 🔺)
mongo / no-emit 97.81 KB (+1.34% 🔺)
mongo / emit 89.19 KB (-0.05% 🔽)
cf-worker / no-emit 188.25 KB (+0.01% 🔺)
cf-worker / emit 173.69 KB (0%)

@pkg-pr-new

pkg-pr-new Bot commented Jul 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

@prisma-next/extension-author-tools

npm i https://pkg.pr.new/@prisma-next/extension-author-tools@900

@prisma-next/mongo-runtime

npm i https://pkg.pr.new/@prisma-next/mongo-runtime@900

@prisma-next/family-mongo

npm i https://pkg.pr.new/@prisma-next/family-mongo@900

@prisma-next/sql-runtime

npm i https://pkg.pr.new/@prisma-next/sql-runtime@900

@prisma-next/family-sql

npm i https://pkg.pr.new/@prisma-next/family-sql@900

@prisma-next/extension-arktype-json

npm i https://pkg.pr.new/@prisma-next/extension-arktype-json@900

@prisma-next/middleware-cache

npm i https://pkg.pr.new/@prisma-next/middleware-cache@900

@prisma-next/mongo

npm i https://pkg.pr.new/@prisma-next/mongo@900

@prisma-next/extension-paradedb

npm i https://pkg.pr.new/@prisma-next/extension-paradedb@900

@prisma-next/extension-pgvector

npm i https://pkg.pr.new/@prisma-next/extension-pgvector@900

@prisma-next/extension-postgis

npm i https://pkg.pr.new/@prisma-next/extension-postgis@900

@prisma-next/postgres

npm i https://pkg.pr.new/@prisma-next/postgres@900

@prisma-next/sql-orm-client

npm i https://pkg.pr.new/@prisma-next/sql-orm-client@900

@prisma-next/sqlite

npm i https://pkg.pr.new/@prisma-next/sqlite@900

@prisma-next/extension-supabase

npm i https://pkg.pr.new/@prisma-next/extension-supabase@900

@prisma-next/target-mongo

npm i https://pkg.pr.new/@prisma-next/target-mongo@900

@prisma-next/adapter-mongo

npm i https://pkg.pr.new/@prisma-next/adapter-mongo@900

@prisma-next/driver-mongo

npm i https://pkg.pr.new/@prisma-next/driver-mongo@900

@prisma-next/contract

npm i https://pkg.pr.new/@prisma-next/contract@900

@prisma-next/utils

npm i https://pkg.pr.new/@prisma-next/utils@900

@prisma-next/config

npm i https://pkg.pr.new/@prisma-next/config@900

@prisma-next/errors

npm i https://pkg.pr.new/@prisma-next/errors@900

@prisma-next/framework-components

npm i https://pkg.pr.new/@prisma-next/framework-components@900

@prisma-next/operations

npm i https://pkg.pr.new/@prisma-next/operations@900

@prisma-next/ts-render

npm i https://pkg.pr.new/@prisma-next/ts-render@900

@prisma-next/contract-authoring

npm i https://pkg.pr.new/@prisma-next/contract-authoring@900

@prisma-next/ids

npm i https://pkg.pr.new/@prisma-next/ids@900

@prisma-next/psl-parser

npm i https://pkg.pr.new/@prisma-next/psl-parser@900

@prisma-next/psl-printer

npm i https://pkg.pr.new/@prisma-next/psl-printer@900

@prisma-next/cli

npm i https://pkg.pr.new/@prisma-next/cli@900

@prisma-next/cli-telemetry

npm i https://pkg.pr.new/@prisma-next/cli-telemetry@900

@prisma-next/config-loader

npm i https://pkg.pr.new/@prisma-next/config-loader@900

@prisma-next/emitter

npm i https://pkg.pr.new/@prisma-next/emitter@900

@prisma-next/language-server

npm i https://pkg.pr.new/@prisma-next/language-server@900

@prisma-next/migration-tools

npm i https://pkg.pr.new/@prisma-next/migration-tools@900

prisma-next

npm i https://pkg.pr.new/prisma-next@900

@prisma-next/vite-plugin-contract-emit

npm i https://pkg.pr.new/@prisma-next/vite-plugin-contract-emit@900

@prisma-next/mongo-codec

npm i https://pkg.pr.new/@prisma-next/mongo-codec@900

@prisma-next/mongo-contract

npm i https://pkg.pr.new/@prisma-next/mongo-contract@900

@prisma-next/mongo-value

npm i https://pkg.pr.new/@prisma-next/mongo-value@900

@prisma-next/mongo-contract-psl

npm i https://pkg.pr.new/@prisma-next/mongo-contract-psl@900

@prisma-next/mongo-contract-ts

npm i https://pkg.pr.new/@prisma-next/mongo-contract-ts@900

@prisma-next/mongo-emitter

npm i https://pkg.pr.new/@prisma-next/mongo-emitter@900

@prisma-next/mongo-schema-ir

npm i https://pkg.pr.new/@prisma-next/mongo-schema-ir@900

@prisma-next/mongo-query-ast

npm i https://pkg.pr.new/@prisma-next/mongo-query-ast@900

@prisma-next/mongo-orm

npm i https://pkg.pr.new/@prisma-next/mongo-orm@900

@prisma-next/mongo-query-builder

npm i https://pkg.pr.new/@prisma-next/mongo-query-builder@900

@prisma-next/mongo-lowering

npm i https://pkg.pr.new/@prisma-next/mongo-lowering@900

@prisma-next/mongo-wire

npm i https://pkg.pr.new/@prisma-next/mongo-wire@900

@prisma-next/sql-contract

npm i https://pkg.pr.new/@prisma-next/sql-contract@900

@prisma-next/sql-errors

npm i https://pkg.pr.new/@prisma-next/sql-errors@900

@prisma-next/sql-operations

npm i https://pkg.pr.new/@prisma-next/sql-operations@900

@prisma-next/sql-schema-ir

npm i https://pkg.pr.new/@prisma-next/sql-schema-ir@900

@prisma-next/sql-contract-psl

npm i https://pkg.pr.new/@prisma-next/sql-contract-psl@900

@prisma-next/sql-contract-ts

npm i https://pkg.pr.new/@prisma-next/sql-contract-ts@900

@prisma-next/sql-contract-emitter

npm i https://pkg.pr.new/@prisma-next/sql-contract-emitter@900

@prisma-next/sql-lane-query-builder

npm i https://pkg.pr.new/@prisma-next/sql-lane-query-builder@900

@prisma-next/sql-relational-core

npm i https://pkg.pr.new/@prisma-next/sql-relational-core@900

@prisma-next/sql-builder

npm i https://pkg.pr.new/@prisma-next/sql-builder@900

@prisma-next/target-postgres

npm i https://pkg.pr.new/@prisma-next/target-postgres@900

@prisma-next/target-sqlite

npm i https://pkg.pr.new/@prisma-next/target-sqlite@900

@prisma-next/adapter-postgres

npm i https://pkg.pr.new/@prisma-next/adapter-postgres@900

@prisma-next/adapter-sqlite

npm i https://pkg.pr.new/@prisma-next/adapter-sqlite@900

@prisma-next/driver-postgres

npm i https://pkg.pr.new/@prisma-next/driver-postgres@900

@prisma-next/driver-sqlite

npm i https://pkg.pr.new/@prisma-next/driver-sqlite@900

commit: 0d187b4

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/3-mongo-target/1-mongo-target/src/core/mongo-target-contract-serializer.ts (1)

25-31: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate inline type for dbInput.entries.

This intersection type duplicates MongoTargetDatabaseInput['entries'] from mongo-target-database.ts. If that type changes, this local copy can silently drift out of sync.

♻️ Proposed fix to reuse the shared type
         const dbInput: {
           id: string;
-          entries?: Readonly<Record<string, Readonly<Record<string, unknown>>>> & {
-            readonly collection?: Readonly<Record<string, MongoCollectionInput>>;
-            readonly valueSet?: Readonly<Record<string, MongoValueSetInput>>;
-          };
+          entries?: MongoTargetDatabaseInput['entries'];
         } = { id: nsData.id };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/3-mongo-target/1-mongo-target/src/core/mongo-target-contract-serializer.ts`
around lines 25 - 31, The inline type for dbInput.entries in
mongo-target-contract-serializer should reuse the shared
MongoTargetDatabaseInput['entries'] type instead of duplicating the same
intersection locally. Update the dbInput declaration in
mongoTargetContractSerializer to reference the existing type from
mongo-target-database, and keep the surrounding MongoCollectionInput and
MongoValueSetInput usage aligned with that shared contract so the serializer
stays in sync automatically.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@packages/3-mongo-target/1-mongo-target/src/core/mongo-target-contract-serializer.ts`:
- Around line 25-31: The inline type for dbInput.entries in
mongo-target-contract-serializer should reuse the shared
MongoTargetDatabaseInput['entries'] type instead of duplicating the same
intersection locally. Update the dbInput declaration in
mongoTargetContractSerializer to reference the existing type from
mongo-target-database, and keep the surrounding MongoCollectionInput and
MongoValueSetInput usage aligned with that shared contract so the serializer
stays in sync automatically.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 7bd36911-355d-414e-89a5-0bfccdcce0b8

📥 Commits

Reviewing files that changed from the base of the PR and between 5c898e7 and abb8850.

⛔ Files ignored due to path filters (4)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • projects/refactor-enum-typing-via-codec/mongo-value-set-design.md is excluded by !projects/**
  • projects/refactor-enum-typing-via-codec/mongo-value-set-plan.md is excluded by !projects/**
  • projects/refactor-enum-typing-via-codec/mongo-value-set-spec.md is excluded by !projects/**
📒 Files selected for processing (42)
  • examples/mongo-demo/migrations/app/20260626T1605_add_user_role_enum/end-contract.d.ts
  • examples/mongo-demo/migrations/app/20260626T1605_add_user_role_enum/end-contract.json
  • examples/mongo-demo/migrations/app/20260626T1605_add_user_role_enum/migration.json
  • examples/mongo-demo/migrations/app/20260626T1916_add_posts_indexes/end-contract.d.ts
  • examples/mongo-demo/migrations/app/20260626T1916_add_posts_indexes/end-contract.json
  • examples/mongo-demo/migrations/app/20260626T1916_add_posts_indexes/migration.json
  • examples/mongo-demo/migrations/app/20260626T1916_add_posts_indexes/start-contract.d.ts
  • examples/mongo-demo/migrations/app/20260626T1916_add_posts_indexes/start-contract.json
  • examples/mongo-demo/src/contract.d.ts
  • examples/mongo-demo/src/contract.json
  • examples/mongo-demo/test/enum-value-set.types.test-d.ts
  • examples/retail-store/migrations/app/20260628T0931_add_product_status_order_type_enums/end-contract.d.ts
  • examples/retail-store/migrations/app/20260628T0931_add_product_status_order_type_enums/end-contract.json
  • examples/retail-store/migrations/app/20260628T0931_add_product_status_order_type_enums/migration.json
  • examples/retail-store/src/contract.d.ts
  • examples/retail-store/src/contract.json
  • packages/2-mongo-family/1-foundation/mongo-contract/src/contract-schema.ts
  • packages/2-mongo-family/1-foundation/mongo-contract/src/entity-kinds.ts
  • packages/2-mongo-family/1-foundation/mongo-contract/src/exports/entity-kinds.ts
  • packages/2-mongo-family/1-foundation/mongo-contract/src/exports/index.ts
  • packages/2-mongo-family/1-foundation/mongo-contract/src/ir/mongo-storage.ts
  • packages/2-mongo-family/1-foundation/mongo-contract/src/ir/mongo-value-set.ts
  • packages/2-mongo-family/1-foundation/mongo-contract/test/entity-kinds.test.ts
  • packages/2-mongo-family/1-foundation/mongo-contract/test/ir/mongo-value-set.test.ts
  • packages/2-mongo-family/1-foundation/mongo-contract/test/mongo-storage.test.ts
  • packages/2-mongo-family/1-foundation/mongo-contract/test/value-set-schema.test.ts
  • packages/2-mongo-family/2-authoring/contract-psl/src/derive-json-schema.ts
  • packages/2-mongo-family/2-authoring/contract-psl/src/exports/index.ts
  • packages/2-mongo-family/2-authoring/contract-psl/src/interpreter.ts
  • packages/2-mongo-family/2-authoring/contract-psl/test/derive-json-schema.test.ts
  • packages/2-mongo-family/2-authoring/contract-ts/src/contract-builder.ts
  • packages/2-mongo-family/2-authoring/contract-ts/test/enum-type.authoring.test.ts
  • packages/2-mongo-family/3-tooling/emitter/package.json
  • packages/2-mongo-family/3-tooling/emitter/src/index.ts
  • packages/2-mongo-family/3-tooling/emitter/test/emitter-hook.resolve-field-value-set.test.ts
  • packages/2-mongo-family/3-tooling/emitter/test/emitter-hook.value-set-codec-path.test.ts
  • packages/3-extensions/mongo/test/mongo.enum.e2e.test.ts
  • packages/3-mongo-target/1-mongo-target/src/core/mongo-target-contract-serializer.ts
  • packages/3-mongo-target/1-mongo-target/src/core/mongo-target-database.ts
  • packages/3-mongo-target/1-mongo-target/test/mongo-planner.test.ts
  • skills/extension-author/prisma-next-extension-upgrade/upgrades/0.14-to-0.15/instructions.md
  • skills/upgrade/prisma-next-upgrade/upgrades/0.14-to-0.15/instructions.md

@wmadden-electric wmadden-electric changed the title TML-2953: Mongo — store enum values the same way SQL does TML-2953: type Mongo enum fields from a stored value set (like SQL) Jul 2, 2026

@wmadden wmadden left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-emptively approved. Address the comments then merge

Comment thread packages/1-framework/1-core/framework-components/src/control/control-stack.ts Outdated
Comment thread packages/2-mongo-family/2-authoring/contract-psl/src/interpreter.ts Outdated
Comment thread packages/3-mongo-target/1-mongo-target/src/core/descriptor-meta.ts Outdated
Comment thread packages/3-mongo-target/1-mongo-target/src/core/descriptor-meta.ts Outdated
@wmadden-electric wmadden-electric force-pushed the tml-2953-mongo-store-enum-values-the-same-way-sql-does branch from bd5b6fd to e2e254f Compare July 2, 2026 14:35
auto-merge was automatically disabled July 2, 2026 16:03

Pull request was closed

…et pack (TML-2953)

The value set must hold codec-encoded values (spec R1). The Mongo TS builder was
storing raw member values because it had no codec. Fix: the Mongo target owns its
codec descriptors (mongo-target descriptor-meta carries types.codecTypes.codecDescriptors,
imported from adapter-mongo/codecs), and both authoring paths resolve the codec by id
from definition.target via extractCodecLookup and encode the value set + domain enum
member values through codec.encodeJson. The builder receives the pack — it does not
import the adapter, so no layering inversion.

A codec not in the contract pack stack is a structured, user-facing error
(PN-CON-4016), thrown identically by the TS builder (encodeEnumValue) and the PSL
interpreter — never a raw fallback. Runtime encode/decode is unaffected: it resolves
through the adapter codecs() registry, so the target pack is the sole contributor of
codec descriptors to the composed control stack (adapter descriptor registration
removed; the duplicate-owner guard stays plain).

Also: the planner test builds the value set through real IR factories; a direct
serializer round-trip test for entries.valueSet.

Byte-identical for shipped identity codecs (fixtures:check zero diff). A non-identity
test codec proves real encoding. retail-store client build green (no bson leak).

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
@wmadden-electric wmadden-electric force-pushed the tml-2953-mongo-store-enum-values-the-same-way-sql-does branch from e2e254f to 0d187b4 Compare July 2, 2026 16:31
@wmadden-electric wmadden-electric added this pull request to the merge queue Jul 2, 2026
Merged via the queue into main with commit 228931d Jul 2, 2026
21 checks passed
@wmadden-electric wmadden-electric deleted the tml-2953-mongo-store-enum-values-the-same-way-sql-does branch July 2, 2026 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants