TML-2915: Infer an enum's @@type from its members#905
Conversation
…2915) Slice contract + two-dispatch plan. The parser/interpreter already handle bare names and numeric member values; the only gap is that @@type is mandatory. Infer it when omitted — text codec for bare/string members, int for integers, error otherwise — via a shared classifier + per-pack default codec ids, both families. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
A PSL enum block may omit @@type; the codec is inferred from the members — the target's text codec when every member is a bare name or string value, the int codec when every member is an integer, and a PSL_ENUM_CANNOT_INFER_TYPE diagnostic otherwise. Explicit @@type is unchanged. Works for Postgres, SQLite, and Mongo. A shared classifyEnumMemberType helper classifies the members; each family enum factory infers when @@type is absent. The target's default codec ids ride on an optional AuthoringEntityContext.enumInferenceCodecs, populated on the PSL path; the TypeScript authoring path never infers, so the field is optional there. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
📝 WalkthroughWalkthroughAdds PSL enum ChangesEnum type inference
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Config as defineConfig
participant Provider as prismaContract/mongoContract provider
participant Interpreter as interpretPslDocumentToXContract
participant Factory as family enum descriptor factory
participant Resolver as resolveEnumCodecId
Config->>Provider: enumInferenceCodecs (text/int codec ids)
Provider->>Interpreter: enumInferenceCodecs
Interpreter->>Factory: entityContext with enumInferenceCodecs
Factory->>Resolver: resolveEnumCodecId(block, ctx)
Resolver->>Resolver: classifyEnumMemberType(block) if @@type omitted
Resolver-->>Factory: codecId + codecSpan, or diagnostic
Factory-->>Interpreter: enum entity or undefined
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
@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: |
size-limit report 📦
|
wmadden
left a comment
There was a problem hiding this comment.
Why is there a comment about an incomplete Mongo dispatch?
The comment referenced a transient dispatch id and described a temporary "required field" state that no longer exists — the mongo factory reads the inferred codecs in this PR, and the field is optional. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
packages/2-mongo-family/9-family/test/authoring-entity-types.enum.test.ts (1)
102-177: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider mirroring SQL family's test coverage for parity.
The SQL enum test suite (
packages/2-sql/9-family/test/authoring-entity-types.enum.test.ts) additionally covers a boolean-member-cannot-infer case and an "explicit@@typeoverrides a value that would otherwise fail inference" case. Since the mongo factory implementation is identical, mirroring those cases here would guard against regressions in the shared logic.🤖 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/9-family/test/authoring-entity-types.enum.test.ts` around lines 102 - 177, Add the missing Mongo enum inference parity cases in authoring-entity-types.enum.test.ts by mirroring the SQL suite: extend the mongoFamilyEnumEntityDescriptor coverage to include a boolean-member-cannot-infer test and an explicit @@type overrides a value that would otherwise fail inference test. Reuse the existing factory, enumBlock, bareMember/valueMember, makeContext, and codecId assertions so the shared inference logic is exercised consistently across mongo and SQL families.packages/2-mongo-family/9-family/src/core/authoring-entity-types.ts (1)
13-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate inference/parsing logic between Mongo and SQL family factories.
parseQuotedStringand the entire@@typeinference/parsing branch (Lines 32-62) are byte-identical to the SQL family'spackages/2-sql/9-family/src/core/authoring-entity-types.ts. SinceclassifyEnumMemberTypeis already shared viaframework-components, consider also hoisting this codec-resolution logic (parseQuotedString + the branch that derivescodecId/typeArgSpan) into a shared helper so both families stay in sync as this logic evolves.Also applies to: 32-62
🤖 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/9-family/src/core/authoring-entity-types.ts` around lines 13 - 18, The quoted-string parsing and @@type codec-resolution branch in authoring-entity-types are duplicated between the Mongo and SQL family factories. Extract parseQuotedString and the logic that derives codecId and typeArgSpan into a shared helper, then have both family implementations call that helper so the behavior stays consistent with classifyEnumMemberType and future changes only need to be made once.
🤖 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.
Inline comments:
In `@packages/2-mongo-family/2-authoring/contract-psl/src/interpreter.ts`:
- Around line 961-963: Update the stale comment near enumInferenceCodecs in
interpreter.ts so it reflects the current behavior: Mongo’s enum factory already
consumes ctx.enumInferenceCodecs via classifyEnumMemberType(block), so remove
the “lands in TML-2915 D2”/“until Mongo’s own factory reads it” wording and
replace it with a note that inference is active now. Keep the change limited to
the comment text around the enumInferenceCodecs assignment and align it with the
implementation in authoring-entity-types.ts.
---
Nitpick comments:
In `@packages/2-mongo-family/9-family/src/core/authoring-entity-types.ts`:
- Around line 13-18: The quoted-string parsing and @@type codec-resolution
branch in authoring-entity-types are duplicated between the Mongo and SQL family
factories. Extract parseQuotedString and the logic that derives codecId and
typeArgSpan into a shared helper, then have both family implementations call
that helper so the behavior stays consistent with classifyEnumMemberType and
future changes only need to be made once.
In `@packages/2-mongo-family/9-family/test/authoring-entity-types.enum.test.ts`:
- Around line 102-177: Add the missing Mongo enum inference parity cases in
authoring-entity-types.enum.test.ts by mirroring the SQL suite: extend the
mongoFamilyEnumEntityDescriptor coverage to include a
boolean-member-cannot-infer test and an explicit @@type overrides a value that
would otherwise fail inference test. Reuse the existing factory, enumBlock,
bareMember/valueMember, makeContext, and codecId assertions so the shared
inference logic is exercised consistently across mongo and SQL families.
🪄 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: ec026b47-2b47-4ab5-a5cb-1460367743b7
⛔ Files ignored due to path filters (2)
projects/enums-as-domain-concept/slices/infer-enum-type-from-members/plan.mdis excluded by!projects/**projects/enums-as-domain-concept/slices/infer-enum-type-from-members/spec.mdis excluded by!projects/**
📒 Files selected for processing (31)
packages/1-framework/1-core/framework-components/src/exports/authoring.tspackages/1-framework/1-core/framework-components/src/shared/framework-authoring.tspackages/1-framework/1-core/framework-components/test/framework-components.authoring.test.tspackages/2-mongo-family/2-authoring/contract-psl/src/interpreter.tspackages/2-mongo-family/9-family/src/core/authoring-entity-types.tspackages/2-mongo-family/9-family/test/authoring-entity-types.enum.test.tspackages/2-sql/2-authoring/contract-psl/src/interpreter.tspackages/2-sql/2-authoring/contract-psl/src/provider.tspackages/2-sql/2-authoring/contract-psl/test/composed-mutation-defaults.test.tspackages/2-sql/2-authoring/contract-psl/test/fixtures.tspackages/2-sql/2-authoring/contract-psl/test/interpreter.control-policy.test.tspackages/2-sql/2-authoring/contract-psl/test/interpreter.defaults.test.tspackages/2-sql/2-authoring/contract-psl/test/interpreter.diagnostics.test.tspackages/2-sql/2-authoring/contract-psl/test/interpreter.enum.test.tspackages/2-sql/2-authoring/contract-psl/test/interpreter.extensions.test.tspackages/2-sql/2-authoring/contract-psl/test/interpreter.namespaces.test.tspackages/2-sql/2-authoring/contract-psl/test/interpreter.polymorphism.test.tspackages/2-sql/2-authoring/contract-psl/test/interpreter.relations.many-to-many.test.tspackages/2-sql/2-authoring/contract-psl/test/interpreter.relations.test.tspackages/2-sql/2-authoring/contract-psl/test/interpreter.test.tspackages/2-sql/2-authoring/contract-psl/test/interpreter.types.test.tspackages/2-sql/2-authoring/contract-psl/test/interpreter.value-objects.test.tspackages/2-sql/2-authoring/contract-psl/test/provider.test.tspackages/2-sql/2-authoring/contract-psl/test/psl-ts-namespace-parity.test.tspackages/2-sql/2-authoring/contract-psl/test/ts-psl-parity.test.tspackages/2-sql/9-family/src/core/authoring-entity-types.tspackages/2-sql/9-family/test/authoring-entity-types.enum.test.tspackages/3-extensions/postgres/src/config/define-config.tspackages/3-extensions/sqlite/src/config/define-config.tspackages/3-targets/3-targets/postgres/src/core/postgres-contract-serializer.tstest/integration/test/mongo/interpreter.enum.test.ts
… not the interpreter Mirror the Postgres/SQLite pattern: the mongo defineConfig injects enumInferenceCodecs into the provider, which threads it into the interpreter as input; the family-layer interpreter no longer hardcodes mongo codec ids. Adds a @prisma-next/adapter-mongo/codec-ids entrypoint (the mongo analogue of target-postgres/codec-ids) so the config imports the constants. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
… churn Address review: collapse the duplicated infer/explicit @@type resolution from both family factories (and the test fixture) into a single resolveEnumCodecId in framework-components, so SQL/Mongo symmetry is structural, not copied. Revert the ~15 test files that only carried a vestigial enumInferenceCodecs line from the abandoned "required-field" iteration (the field is optional). Record the additive change as incidental for the 0.14->0.15 extension-author upgrade. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…ences # Conflicts: # packages/2-sql/2-authoring/contract-psl/src/interpreter.ts # packages/2-sql/2-authoring/contract-psl/test/interpreter.enum.test.ts # skills/extension-author/prisma-next-extension-upgrade/upgrades/0.14-to-0.15/instructions.md
There was a problem hiding this comment.
🧹 Nitpick comments (2)
packages/2-mongo-family/9-family/src/core/authoring-entity-types.ts (1)
13-138: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy liftEnum factory body (member decoding/validation, lines ~52-136) is byte-for-byte identical to
packages/2-sql/9-family/src/core/authoring-entity-types.ts.Only the
@@typeresolution (lines 24-47, now delegated to the newresolveEnumCodecId) was deduplicated in this PR; the remaining ~85 lines of member iteration/decoding/duplicate-detection logic remain duplicated verbatim across the Mongo and SQL families. Given this PR already established the pattern of extracting shared enum logic intoframework-components, extending that to the member-decoding loop would remove the remaining duplication (pre-existing, not introduced by this diff).🤖 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/9-family/src/core/authoring-entity-types.ts` around lines 13 - 138, The enum factory in mongoFamilyEnumEntityDescriptor still duplicates the member decoding, validation, and duplicate-detection logic found in the SQL family’s authoring-entity-types module. Extract the shared loop and related error handling into a reusable helper in framework-components, then have mongoFamilyEnumEntityDescriptor.factory and the SQL equivalent call that helper after resolveEnumCodecId so the two families only differ in their small family-specific setup.packages/1-framework/1-core/framework-components/src/shared/framework-authoring.ts (1)
191-198: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDoc comment on exported function may run against the "avoid comments" guideline.
This is an 8-line JSDoc block explaining
resolveEnumCodecId's contract (codecSpan semantics, diagnostic push side-effect, cross-family sharing rationale). As per coding guidelines,**/*.{ts,tsx,js,jsx,mts,mjs}: "Don't add comments if avoidable, prefer code that expresses its intent." Given the non-obvious return semantics (implicit error signaling viaundefined+ diagnostics sink), this may be a reasonable exception, but flagging for awareness since it's a fairly large comment block for a codebase with this rule.🤖 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/1-framework/1-core/framework-components/src/shared/framework-authoring.ts` around lines 191 - 198, The JSDoc on resolveEnumCodecId is larger than needed and may conflict with the “avoid comments” guideline. Trim or remove the block in framework-authoring.ts, keeping only the essential contract details that cannot be expressed by the function signature or types, and prefer concise code or naming to convey the codecSpan/diagnostic behavior. If documentation is still needed, shorten it substantially and keep it directly aligned with resolveEnumCodecId’s exported API.Source: Coding guidelines
🤖 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/1-framework/1-core/framework-components/src/shared/framework-authoring.ts`:
- Around line 191-198: The JSDoc on resolveEnumCodecId is larger than needed and
may conflict with the “avoid comments” guideline. Trim or remove the block in
framework-authoring.ts, keeping only the essential contract details that cannot
be expressed by the function signature or types, and prefer concise code or
naming to convey the codecSpan/diagnostic behavior. If documentation is still
needed, shorten it substantially and keep it directly aligned with
resolveEnumCodecId’s exported API.
In `@packages/2-mongo-family/9-family/src/core/authoring-entity-types.ts`:
- Around line 13-138: The enum factory in mongoFamilyEnumEntityDescriptor still
duplicates the member decoding, validation, and duplicate-detection logic found
in the SQL family’s authoring-entity-types module. Extract the shared loop and
related error handling into a reusable helper in framework-components, then have
mongoFamilyEnumEntityDescriptor.factory and the SQL equivalent call that helper
after resolveEnumCodecId so the two families only differ in their small
family-specific setup.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 7782b4f5-4c78-4a54-a259-1373da6862ff
📒 Files selected for processing (16)
packages/1-framework/1-core/framework-components/src/exports/authoring.tspackages/1-framework/1-core/framework-components/src/shared/framework-authoring.tspackages/2-mongo-family/2-authoring/contract-psl/src/interpreter.tspackages/2-mongo-family/2-authoring/contract-psl/src/provider.tspackages/2-mongo-family/9-family/src/core/authoring-entity-types.tspackages/2-sql/2-authoring/contract-psl/src/interpreter.tspackages/2-sql/2-authoring/contract-psl/src/provider.tspackages/2-sql/2-authoring/contract-psl/test/fixtures.tspackages/2-sql/2-authoring/contract-psl/test/interpreter.enum.test.tspackages/2-sql/9-family/src/core/authoring-entity-types.tspackages/3-extensions/mongo/src/config/define-config.tspackages/3-mongo-target/2-mongo-adapter/package.jsonpackages/3-mongo-target/2-mongo-adapter/src/exports/codec-ids.tspackages/3-mongo-target/2-mongo-adapter/tsdown.config.tsskills/extension-author/prisma-next-extension-upgrade/upgrades/0.14-to-0.15/instructions.mdtest/integration/test/mongo/interpreter.enum.test.ts
✅ Files skipped from review due to trivial changes (1)
- skills/extension-author/prisma-next-extension-upgrade/upgrades/0.14-to-0.15/instructions.md
🚧 Files skipped from review as they are similar to previous changes (7)
- packages/1-framework/1-core/framework-components/src/exports/authoring.ts
- packages/2-sql/2-authoring/contract-psl/src/provider.ts
- test/integration/test/mongo/interpreter.enum.test.ts
- packages/2-sql/2-authoring/contract-psl/src/interpreter.ts
- packages/2-mongo-family/2-authoring/contract-psl/src/interpreter.ts
- packages/2-sql/2-authoring/contract-psl/test/interpreter.enum.test.ts
- packages/2-sql/2-authoring/contract-psl/test/fixtures.ts
At a glance
Before, an
enumhad to spell out its@@type. Now it can leave it off:The decision
Let an
enumblock omit@@type, and infer the codec from its members. The rule is deliberately small:PSL_ENUM_CANNOT_INFER_TYPEdiagnostic that says to add an explicit@@type(...)An explicit
@@typestill wins and behaves exactly as before. This covers the two common cases and asks you to be explicit for everything else. It applies to Postgres, SQLite, and Mongo.Why it's a small change
Most of this already worked. The parser already tags each enum member as bare (
admin) or a value (admin = 1), and the interpreter already lowers both — a bare member feeds its name through the codec, a value member decodes its right-hand side. So bare names and numeric values already parsed and lowered fine; the only thing that forced you to write@@typewas that it was mandatory. This PR replaces that "missing@@type" error, when the attribute is absent, with the inference above.How it works
A shared
classifyEnumMemberTypehelper looks at the members and returnstext,int, or "can't tell". Each family's enum factory calls it when@@typeis absent and picks the target's default codec. Those default codec ids (pg/text@1/pg/int@1,sqlite/text@1/sqlite/integer@1,mongo/string@1/mongo/int32@1) are supplied by each target on the authoring context. The field is optional on that context, because the TypeScript authoring path always names its codec explicitly and never infers.Testing
Per-family factory tests for every branch (bare→text, string→text, integer→int, and float/boolean/mixed → the diagnostic), a unit test for the classifier, and a Mongo integration test proving a no-
@@typeenum lowers with the inferred codec end to end. Explicit-@@typefixtures are unchanged (fixtures:checkclean). Build, typecheck, lint, and the test suites pass.Alternatives considered
enum Role text { … }). Rejected — this is@@typeomission, which needs no new grammar and reads as "the obvious default"; a keyword is more surface for the same result.enumType/memberAPI already takes an explicit codec and has no ambiguity to resolve, so there's nothing to infer. (That's also why the context field is optional rather than required.)Spec + plan:
projects/enums-as-domain-concept/slices/infer-enum-type-from-members/. Closes TML-2915.🤖 Generated with Claude Code
Summary by CodeRabbit
@@typeis omitted, based on member values.