Mongo PSL: bare-member enums fail interpretation unless enum inference codecs are wired explicitly#934
Mongo PSL: bare-member enums fail interpretation unless enum inference codecs are wired explicitly#934ankur-arch wants to merge 3 commits into
Conversation
A bare-member enum (`enum Direction { INBOUND OUTBOUND }`) in a Mongo PSL
schema failed contract interpretation with PSL_ENUM_CANNOT_INFER_TYPE
cascading into PSL_UNSUPPORTED_FIELD_TYPE on every enum-typed field,
unless the config passed enumInferenceCodecs explicitly — only
@prisma-next/mongo's defineConfig did.
The interpreter now derives the default inference codecs from the
target-contributed PSL String/Int scalar type descriptors, so every
config surface resolves classic enums identically; the explicit option
still overrides. defineConfig drops its now-redundant wiring.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Ankur Datta <64993082+ankur-arch@users.noreply.github.com>
📝 WalkthroughWalkthroughThe Mongo PSL interpreter now derives default enum inference codec ids from target scalar type descriptors when not explicitly supplied. The change is reflected in config wiring, unit coverage, CLI integration coverage, and upgrade notes. ChangesEnum inference codec defaulting
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
size-limit report 📦
|
@prisma-next/extension-author-tools
@prisma-next/mongo-runtime
@prisma-next/family-mongo
@prisma-next/sql-runtime
@prisma-next/family-sql
@prisma-next/extension-arktype-json
@prisma-next/middleware-cache
@prisma-next/mongo
@prisma-next/extension-paradedb
@prisma-next/extension-pgvector
@prisma-next/extension-postgis
@prisma-next/postgres
@prisma-next/sql-orm-client
@prisma-next/sqlite
@prisma-next/extension-supabase
@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/ts-render
@prisma-next/contract-authoring
@prisma-next/ids
@prisma-next/psl-parser
@prisma-next/psl-printer
@prisma-next/cli
@prisma-next/cli-telemetry
@prisma-next/config-loader
@prisma-next/emitter
@prisma-next/language-server
@prisma-next/migration-tools
prisma-next
@prisma-next/vite-plugin-contract-emit
@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-query-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 (2)
packages/2-mongo-family/2-authoring/contract-psl/test/interpreter.enums.test.ts (1)
152-166: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueOptional: add coverage for the derived
intcodec path.Current tests cover default text-codec inference, explicit override, and failure when
Intis missing, but no test exercises an integer bare-member enum successfully resolving via the derivedintcodec end-to-end.🤖 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/2-mongo-family/2-authoring/contract-psl/test/interpreter.enums.test.ts` around lines 152 - 166, Add a test in interpreter.enums.test.ts to cover the successful derived int codec path for bare-member enums. Extend the existing enum inference coverage around interpretPslDocumentToMongoContract by creating an int-valued enum case that resolves through the derived int codec end-to-end, then assert the resulting namespace enum codecId matches the expected mongo/int32@1 codec. Use the existing test helpers and symbols like bareMemberEnumSchema, mongoScalarTypeDescriptors, mongoCodecLookup, authoringContributions, and UNBOUND_NAMESPACE_ID to keep it aligned with the current enum inference tests.test/integration/test/cli.emit-command.additional.test.ts (1)
383-417: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winSplit the combined
toMatchObjectinto targeted assertions.This single
toMatchObjectbundlestargetFamily,target, and deeply nested enum/model/field checks. Based on learnings, this repo's test convention is to prefer separateexpect()assertions per field overtoMatchObject()for multi-field validation, since it produces clearer, more actionable failure messages pinpointing exactly which field failed.♻️ Example split
- expect(contractJson).toMatchObject({ - targetFamily: 'mongo', - target: 'mongo', - domain: { - namespaces: { - __unbound__: { - enum: { - WhatsAppMessageDirection: { - codecId: 'mongo/string@1', - members: [ - { name: 'INBOUND', value: 'INBOUND' }, - { name: 'OUTBOUND', value: 'OUTBOUND' }, - ], - }, - }, - models: { - WhatsAppMessages: expect.objectContaining({ - fields: expect.objectContaining({ - direction: { - type: { kind: 'scalar', codecId: 'mongo/string@1' }, - nullable: false, - valueSet: { - plane: 'domain', - entityKind: 'enum', - namespaceId: '__unbound__', - entityName: 'WhatsAppMessageDirection', - }, - }, - }), - }), - }, - }, - }, - }, - }); + expect(contractJson.targetFamily).toBe('mongo'); + expect(contractJson.target).toBe('mongo'); + const enumEntry = + contractJson.domain.namespaces.__unbound__.enum.WhatsAppMessageDirection; + expect(enumEntry.codecId).toBe('mongo/string@1'); + expect(enumEntry.members).toEqual([ + { name: 'INBOUND', value: 'INBOUND' }, + { name: 'OUTBOUND', value: 'OUTBOUND' }, + ]); + const field = + contractJson.domain.namespaces.__unbound__.models.WhatsAppMessages.fields.direction; + expect(field.type).toEqual({ kind: 'scalar', codecId: 'mongo/string@1' }); + expect(field.nullable).toBe(false); + expect(field.valueSet).toEqual({ + plane: 'domain', + entityKind: 'enum', + namespaceId: '__unbound__', + entityName: 'WhatsAppMessageDirection', + });🤖 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 `@test/integration/test/cli.emit-command.additional.test.ts` around lines 383 - 417, The test in the contract JSON assertion is using one large toMatchObject for multiple unrelated checks, which should be split into focused expect() assertions. Update the assertions around contractJson to validate targetFamily, target, and the nested domain/namespace/enum/model/field structure separately, using the existing WhatsAppMessageDirection and WhatsAppMessages references to keep each failure message precise.Source: Learnings
🤖 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/2-mongo-family/2-authoring/contract-psl/test/interpreter.enums.test.ts`:
- Around line 152-166: Add a test in interpreter.enums.test.ts to cover the
successful derived int codec path for bare-member enums. Extend the existing
enum inference coverage around interpretPslDocumentToMongoContract by creating
an int-valued enum case that resolves through the derived int codec end-to-end,
then assert the resulting namespace enum codecId matches the expected
mongo/int32@1 codec. Use the existing test helpers and symbols like
bareMemberEnumSchema, mongoScalarTypeDescriptors, mongoCodecLookup,
authoringContributions, and UNBOUND_NAMESPACE_ID to keep it aligned with the
current enum inference tests.
In `@test/integration/test/cli.emit-command.additional.test.ts`:
- Around line 383-417: The test in the contract JSON assertion is using one
large toMatchObject for multiple unrelated checks, which should be split into
focused expect() assertions. Update the assertions around contractJson to
validate targetFamily, target, and the nested domain/namespace/enum/model/field
structure separately, using the existing WhatsAppMessageDirection and
WhatsAppMessages references to keep each failure message precise.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: d517c9fa-2aeb-423c-b314-080ef7179670
📒 Files selected for processing (6)
packages/2-mongo-family/2-authoring/contract-psl/src/interpreter.tspackages/2-mongo-family/2-authoring/contract-psl/src/provider.tspackages/2-mongo-family/2-authoring/contract-psl/test/interpreter.enums.test.tspackages/3-extensions/mongo/src/config/define-config.tstest/integration/test/cli.emit-command.additional.test.tstest/integration/test/fixtures/cli/cli-integration-test-app/fixtures/emit-command/prisma-next.config.mongo-define.ts
|
Follow-up for the second issue in the same Discord thread (extendable |
…nce default wiring Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Ankur Datta <64993082+ankur-arch@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Ankur Datta <64993082+ankur-arch@users.noreply.github.com>
|
Ponytail review (lazy-senior-dev ladder over the diff):
→ skipped: same defaulting for the SQL PSL interpreter — add if/when a SQL user hits the equivalent report (its defineConfig paths already wire the ids). |
What this fixes
Using an enum in a MongoDB PSL schema failed contract resolution:
Reported on Discord ([NEXT], 2026-07-07). After this PR, a plain enum just works, on every config surface:
What was broken
An enum without
@@type(...)infers its codec from its members — but the codec ids to infer to were only wired in one place:@prisma-next/mongo'sdefineConfig. Any config that used themongoContract()provider directly hitPSL_ENUM_CANNOT_INFER_TYPE, which then cascaded into the misleadingPSL_UNSUPPORTED_FIELD_TYPEon every field typed by the enum — exactly the reported "2 of 2" diagnostics.The fix
The Mongo PSL interpreter now derives the default inference codecs from the target's own scalar type descriptors (
String→mongo/string@1,Int→mongo/int32@1) — the same valuesdefineConfigpassed by hand.defineConfigdrops its now-redundant wiring, and the explicitenumInferenceCodecsoption still overrides.packages/2-mongo-family/2-authoring/contract-psl/src/interpreter.ts— derive the default when the input omitsenumInferenceCodecspackages/3-extensions/mongo/src/config/define-config.ts— remove the duplicate wiringskills/extension-author/.../0.14-to-0.15/instructions.md— no-action upgrade declaration (behaviour identical for extension authors)Testing
Tests were written first and failed for the right reason, then went green:
interpreter.enums.test.ts): a bare-member enum resolves with no explicit wiring (domain enum + typed field + storage value set); an explicitenumInferenceCodecsstill overrides; the original diagnostic pair is still reported when no default can be derived.contract emitwith both config styles — rawmongoContract()(previously failing) and@prisma-next/mongodefineConfig(new fixture).pnpm test:packagessweep, the integration emit suite,pnpm lint:deps, andpnpm fixtures:check(no fixture drift) all pass.The same Discord thread's second ask — an extendable
Collectionclass for the Mongo ORM — is shipped separately in #936.🤖 Generated with Claude Code