TML-2952: type SQL enum columns through the codec instead of printing their stored values#896
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (5)
✅ Files skipped from review due to trivial changes (1)
📝 WalkthroughWalkthroughThis PR replaces the ChangesValue-literal codec narrowing
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 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 📦
|
… + plan Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…ing stored values (TML-2952) An enum column/field TypeScript type is produced by the codec, from the storage value set, instead of being printed straight from the stored values in two separate emit paths (which bypassed the codec and only worked by coincidence for text/int codecs). - Add a codec renderValueType seam (CodecDescriptor + CodecLookup); implement for the Postgres and Mongo primitive codecs. - Route the SQL column emit through it via a shared renderValueSetType helper, relocated to the framework emitter so column and field emit share one path. - Replace the hardcoded domain-enum field override with a family-supplied EmissionSpi.resolveFieldValueSet hook. SQL sources permitted values from the storage value set; Mongo supplies an interim resolver reading domain.enum, removed once Mongo stores enum values as a value set (TML-2953). The domain enum is no longer a typing input; it keeps only the runtime db.enums dictionary. Byte-identical for text/int enums on both families (empty contract diff, fixtures:check clean). A non-identity test codec proves the emitted type is the codec output, not the raw encoded literal; emit and no-emit agree. Structural guards keep the deleted direct-render helpers gone and pin the only domain-enum typing reader to the Mongo interim resolver. No new casts; lint:deps clean. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
e6fa3cc to
1d473db
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/3-targets/3-targets/postgres/src/core/codecs.ts (1)
1001-1016: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winAvoid reusing the identity literal renderer for
PgCharDescriptor.SqlCharCodec.decode()trims trailing spaces, soCHAR(n)is not identity-preserving in the same way asVARCHAR.renderValueTypeshould apply the same normalization path or otherwise account for padded values to avoid mismatches onpg/char@1.🤖 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-targets/3-targets/postgres/src/core/codecs.ts` around lines 1001 - 1016, PgCharDescriptor is incorrectly using the identity literal renderer, which assumes values round-trip unchanged; update PgCharDescriptor.renderValueType to follow the same normalization path used by SqlCharCodec.decode() for CHAR values, since trailing-space padding is trimmed and pg/char@1 is not identity-preserving. Use the PgCharDescriptor and SqlCharCodec symbols to locate the fix, and ensure the rendered value type accounts for padded CHAR semantics instead of delegating to renderPrimitiveLiteral directly.
🧹 Nitpick comments (6)
packages/2-mongo-family/3-tooling/emitter/src/index.ts (1)
262-278: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCorrect interim implementation; minor type-duplication nit.
The logic correctly gates on
entityKind === 'enum', resolves the domain enum, and returns{ encodedValues, codecId }matching theFieldValueSetResolvercontract. The inline return type{ readonly encodedValues: readonly JsonValue[]; readonly codecId: string } | undefinedduplicates theResolvedFieldValueSettype already exported fromdomain-type-generation.ts(and is duplicated again inpackages/2-sql/3-tooling/emitter/src/index.ts'sresolveFieldValueSet). Importing and reusingResolvedFieldValueSetwould keep both family emitters structurally locked to the same contract instead of independently redeclaring it.♻️ Suggested fix
-import type { - Contract, - ContractModel, - ContractModelBase, - JsonValue, -} from '`@prisma-next/contract/types`'; +import type { Contract, ContractModel, ContractModelBase } from '`@prisma-next/contract/types`'; +import type { ResolvedFieldValueSet } from '`@prisma-next/emitter/domain-type-generation`'; ... - resolveFieldValueSet( - _modelName: string, - fieldName: string, - model: ContractModelBase, - contract: Contract, - ): { readonly encodedValues: readonly JsonValue[]; readonly codecId: string } | undefined { + resolveFieldValueSet( + _modelName: string, + fieldName: string, + model: ContractModelBase, + contract: Contract, + ): ResolvedFieldValueSet | undefined {🤖 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/3-tooling/emitter/src/index.ts` around lines 262 - 278, The interim logic in resolveFieldValueSet is correct, but the return type is being redeclared inline instead of reusing the shared ResolvedFieldValueSet type. Update this emitter’s resolveFieldValueSet signature to import and reference ResolvedFieldValueSet from domain-type-generation.ts, and apply the same cleanup in the matching resolveFieldValueSet implementation in the SQL family emitter so both stay aligned with the single exported contract type.packages/2-sql/3-tooling/emitter/src/index.ts (1)
318-357: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCorrect implementation; duplicate value-set lookup with
computeColumnType.The table/column/value-set resolution chain is correct and matches the fixtures exercised in
emitter-hook.storage-column-types.test.ts. However, theentityAt<StorageValueSet>(storage, { namespaceId: column.valueSet.namespaceId, entityKind: column.valueSet.entityKind, entityName: column.valueSet.entityName })call here is identical to the one incomputeColumnType(Line 457-461). Extracting a smallresolveColumnValueSet(storage, column)helper would remove the duplication and keep the lookup logic in one place.Also, similar to the Mongo emitter, the inline return type duplicates
ResolvedFieldValueSetfrom@prisma-next/emitter/domain-type-generationrather than importing it.♻️ Suggested helper extraction
+function resolveColumnValueSet( + storage: SqlStorage, + column: StorageColumn, +): StorageValueSet | undefined { + if (!column.valueSet) return undefined; + return entityAt<StorageValueSet>(storage, { + namespaceId: column.valueSet.namespaceId, + entityKind: column.valueSet.entityKind, + entityName: column.valueSet.entityName, + }); +}Then in both
resolveFieldValueSetandcomputeColumnType, replace the inlineentityAtcalls withresolveColumnValueSet(storage, column).🤖 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-sql/3-tooling/emitter/src/index.ts` around lines 318 - 357, `resolveFieldValueSet` duplicates the same `entityAt<StorageValueSet>(...)` lookup already performed in `computeColumnType`; extract that shared logic into a small `resolveColumnValueSet(storage, column)` helper and have both methods call it. While touching `resolveFieldValueSet`, replace the inline return shape with the shared `ResolvedFieldValueSet` type imported from `@prisma-next/emitter/domain-type-generation` so the emitter uses the canonical type instead of redefining it.packages/1-framework/3-tooling/emitter/test/enum-typing-codec-seam.guard.test.ts (1)
79-83: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winDOMAIN_ENUM_READ regex has a blind spot for dot-property access.
The pattern only catches
.enum(,.enum[, and.enum?.[. A future read likens.enum.Priority(plain dot-name access) would silently bypass this guard, defeating its purpose of catching domain.enum typing regressions.🛡️ Suggested widening
-const DOMAIN_ENUM_READ = /\.enum\s*(\?\.\[|\[|\))/; +const DOMAIN_ENUM_READ = /\.enum\s*(\?\.\[|\[|\)|\?\.[A-Za-z_$]|\.[A-Za-z_$])/;🤖 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/3-tooling/emitter/test/enum-typing-codec-seam.guard.test.ts` around lines 79 - 83, The DOMAIN_ENUM_READ guard regex is too narrow because it misses plain dot-property access after `.enum`, so update the matcher in the enum-typing-codec-seam test to also recognize reads like `ns.enum.Priority`. Keep the existing intent of matching only real access syntax in the test, but widen the pattern in DOMAIN_ENUM_READ so it covers dot-name property reads in addition to the current paren/bracket forms.packages/1-framework/3-tooling/emitter/test/domain-type-generation.test.ts (1)
41-54: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTest-only codec-lookup mock duplicated 3x with a subtle quoting inconsistency.
literalCodecLookup()here properly escapes strings viaserializeValue, but the near-identical helpers inemitter.integration.test.ts(lines 12-25) andgenerate-contract-dts.spi-branches.test.ts(lines 14-27) build the string literal with a raw template (`'${value}'`) that doesn't escape embedded quotes. Consider extracting one shared test helper (e.g. in a shared test-utils module) so all three suites stay in sync and use the safer escaping.🤖 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/3-tooling/emitter/test/domain-type-generation.test.ts` around lines 41 - 54, The test-only literal codec lookup mock is duplicated across multiple test suites, and two copies build string literals without escaping embedded quotes. Extract a shared test helper based on literalCodecLookup()/renderValueTypeFor() and use serializeValue for string values so emitter.integration.test.ts and generate-contract-dts.spi-branches.test.ts stay consistent with this safer implementation.packages/3-targets/3-targets/postgres/src/core/codecs.ts (1)
88-105: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
renderPrimitiveLiteralis duplicated verbatim across the Mongo and Postgres target packages (and a test helper).The exact same function body exists in
packages/3-mongo-target/2-mongo-adapter/src/core/codecs.ts. Given the architecture separates per-family target implementations, this may be an intentional isolation choice, but if the two copies ever diverge (e.g., one gets the escaping fix above and the other doesn't), correctness silently drifts between families. Consider hoisting a sharedrenderPrimitiveLiteral/escaping utility into a common location (e.g.framework-components/codec) that both target packages import.Also applies to: 163-171, 246-254, 288-296, 330-338, 372-380, 414-422, 456-464, 1001-1016, 1025-1040, 1054-1066, 1075-1087
🤖 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-targets/3-targets/postgres/src/core/codecs.ts` around lines 88 - 105, The `renderPrimitiveLiteral` implementation in `codecs.ts` is duplicated across the Postgres and Mongo target packages, so update the shared literal-rendering logic by extracting it into a common utility (for example under `framework-components/codec`) and have both target `codecs.ts` files import it. Make sure any callers of `renderPrimitiveLiteral` and the related `renderValueType` paths keep using the shared helper so escaping and literal formatting stay consistent across families and test helpers.packages/3-targets/3-targets/postgres/test/codec-render-value-type.test.ts (1)
1-94: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueLGTM! Solid coverage of quoting/escaping, numeric/boolean literals, and the non-narrowable fallback case.
One minor gap: the alias-based descriptors (
pgCharDescriptor,pgVarcharDescriptor,pgIntDescriptor,pgFloatDescriptor) that also gainedrenderValueTypearen't exercised here — low risk since they delegate to the same testedrenderPrimitiveLiteral, but worth adding for completeness.🤖 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-targets/3-targets/postgres/test/codec-render-value-type.test.ts` around lines 1 - 94, Add test coverage in codec-render-value-type.test.ts for the alias-based descriptors that also implement renderValueType: pgCharDescriptor, pgVarcharDescriptor, pgIntDescriptor, and pgFloatDescriptor. Use valueRendererFor alongside the existing pgTextDescriptor/pgInt4Descriptor-style tests to verify they produce the same primitive literal rendering as their underlying codecs, ensuring the alias exports are exercised directly.
🤖 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/3-mongo-target/2-mongo-adapter/src/core/codecs.ts`:
- Around line 88-102: renderPrimitiveLiteral currently only escapes backslashes
and apostrophes, so string values containing line terminators can generate
invalid TS in the .d.ts output. Update renderPrimitiveLiteral to also escape raw
newline, carriage return, and Unicode line/paragraph separators before wrapping
the value in single quotes, while keeping the existing handling for numbers and
booleans unchanged.
In `@packages/3-targets/3-targets/postgres/src/core/codecs.ts`:
- Around line 88-105: The renderPrimitiveLiteral helper in codecs.ts is missing
control-character escaping for string literals, so update its string handling to
escape newline, carriage return, and Unicode line-separator characters in
addition to backslashes and apostrophes. Keep the fix localized to
renderPrimitiveLiteral so any callers that rely on its TS-literal output get
valid generated source.
---
Outside diff comments:
In `@packages/3-targets/3-targets/postgres/src/core/codecs.ts`:
- Around line 1001-1016: PgCharDescriptor is incorrectly using the identity
literal renderer, which assumes values round-trip unchanged; update
PgCharDescriptor.renderValueType to follow the same normalization path used by
SqlCharCodec.decode() for CHAR values, since trailing-space padding is trimmed
and pg/char@1 is not identity-preserving. Use the PgCharDescriptor and
SqlCharCodec symbols to locate the fix, and ensure the rendered value type
accounts for padded CHAR semantics instead of delegating to
renderPrimitiveLiteral directly.
---
Nitpick comments:
In `@packages/1-framework/3-tooling/emitter/test/domain-type-generation.test.ts`:
- Around line 41-54: The test-only literal codec lookup mock is duplicated
across multiple test suites, and two copies build string literals without
escaping embedded quotes. Extract a shared test helper based on
literalCodecLookup()/renderValueTypeFor() and use serializeValue for string
values so emitter.integration.test.ts and
generate-contract-dts.spi-branches.test.ts stay consistent with this safer
implementation.
In
`@packages/1-framework/3-tooling/emitter/test/enum-typing-codec-seam.guard.test.ts`:
- Around line 79-83: The DOMAIN_ENUM_READ guard regex is too narrow because it
misses plain dot-property access after `.enum`, so update the matcher in the
enum-typing-codec-seam test to also recognize reads like `ns.enum.Priority`.
Keep the existing intent of matching only real access syntax in the test, but
widen the pattern in DOMAIN_ENUM_READ so it covers dot-name property reads in
addition to the current paren/bracket forms.
In `@packages/2-mongo-family/3-tooling/emitter/src/index.ts`:
- Around line 262-278: The interim logic in resolveFieldValueSet is correct, but
the return type is being redeclared inline instead of reusing the shared
ResolvedFieldValueSet type. Update this emitter’s resolveFieldValueSet signature
to import and reference ResolvedFieldValueSet from domain-type-generation.ts,
and apply the same cleanup in the matching resolveFieldValueSet implementation
in the SQL family emitter so both stay aligned with the single exported contract
type.
In `@packages/2-sql/3-tooling/emitter/src/index.ts`:
- Around line 318-357: `resolveFieldValueSet` duplicates the same
`entityAt<StorageValueSet>(...)` lookup already performed in
`computeColumnType`; extract that shared logic into a small
`resolveColumnValueSet(storage, column)` helper and have both methods call it.
While touching `resolveFieldValueSet`, replace the inline return shape with the
shared `ResolvedFieldValueSet` type imported from
`@prisma-next/emitter/domain-type-generation` so the emitter uses the canonical
type instead of redefining it.
In `@packages/3-targets/3-targets/postgres/src/core/codecs.ts`:
- Around line 88-105: The `renderPrimitiveLiteral` implementation in `codecs.ts`
is duplicated across the Postgres and Mongo target packages, so update the
shared literal-rendering logic by extracting it into a common utility (for
example under `framework-components/codec`) and have both target `codecs.ts`
files import it. Make sure any callers of `renderPrimitiveLiteral` and the
related `renderValueType` paths keep using the shared helper so escaping and
literal formatting stay consistent across families and test helpers.
In `@packages/3-targets/3-targets/postgres/test/codec-render-value-type.test.ts`:
- Around line 1-94: Add test coverage in codec-render-value-type.test.ts for the
alias-based descriptors that also implement renderValueType: pgCharDescriptor,
pgVarcharDescriptor, pgIntDescriptor, and pgFloatDescriptor. Use
valueRendererFor alongside the existing pgTextDescriptor/pgInt4Descriptor-style
tests to verify they produce the same primitive literal rendering as their
underlying codecs, ensuring the alias exports are exercised directly.
🪄 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: 29642cbd-cce6-407a-baa5-d472d72cf35b
⛔ Files ignored due to path filters (2)
projects/refactor-enum-typing-via-codec/plan.mdis excluded by!projects/**projects/refactor-enum-typing-via-codec/spec.mdis excluded by!projects/**
📒 Files selected for processing (20)
examples/prisma-next-demo/test/demo-dx.types.test.tspackages/1-framework/1-core/framework-components/src/control/control-stack.tspackages/1-framework/1-core/framework-components/src/control/emission-types.tspackages/1-framework/1-core/framework-components/src/shared/codec-descriptor.tspackages/1-framework/1-core/framework-components/src/shared/codec-types.tspackages/1-framework/1-core/framework-components/test/control-stack.test.tspackages/1-framework/3-tooling/emitter/src/domain-type-generation.tspackages/1-framework/3-tooling/emitter/src/generate-contract-dts.tspackages/1-framework/3-tooling/emitter/test/domain-type-generation.test.tspackages/1-framework/3-tooling/emitter/test/emitter.integration.test.tspackages/1-framework/3-tooling/emitter/test/enum-typing-codec-seam.guard.test.tspackages/1-framework/3-tooling/emitter/test/generate-contract-dts.spi-branches.test.tspackages/2-mongo-family/3-tooling/emitter/src/index.tspackages/2-sql/3-tooling/emitter/src/index.tspackages/2-sql/3-tooling/emitter/test/emitter-hook.storage-column-types.test.tspackages/2-sql/3-tooling/emitter/test/value-set-codec-lookups.tspackages/3-extensions/mongo/test/mongo.enum.e2e.test.tspackages/3-mongo-target/2-mongo-adapter/src/core/codecs.tspackages/3-targets/3-targets/postgres/src/core/codecs.tspackages/3-targets/3-targets/postgres/test/codec-render-value-type.test.ts
…b; fix literal escaping Review feedback on PR #896 — naming/doc only, byte-identical (fixtures:check clean), plus one real escaping fix. - Rename the codec SPI for what it does: renderValueType -> renderValueLiteral and renderValueTypeFor -> renderValueLiteralFor (it renders a stored value as a TS literal). Rewrite the descriptor doc to lead with the plain statement. - Rename the opaque `channel` param to `side` (matching the existing convention) and document it: output = the read/SELECT type, input = the create/update type. A non-identity codec can render a stored value to a different literal per side. - De-enum the value-set vocabulary: a value set is a generic set of a field/column permitted values, independent of enums (an enum is one producer). Purge "enum" from the value-set docs, and strip the downstream SQL reference from framework-emitter code (it must not name a consumer). - Escape newlines and line/paragraph separators in renderPrimitiveLiteral (both the Postgres and Mongo copies) so a value containing a line terminator cannot emit invalid TypeScript in the generated .d.ts; add a test. 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.
🧹 Nitpick comments (1)
packages/3-targets/3-targets/postgres/src/core/codecs.ts (1)
95-113: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueOptional: collapse repeated override boilerplate.
All 12
renderValueLiteraloverrides are identical 3-line delegations torenderPrimitiveLiteral. Since its signature is structurally compatible with the required(value, side)shape, these can be a single-line class field instead.♻️ Example collapse (repeat per descriptor)
- override renderValueLiteral(value: JsonValue): string | undefined { - return renderPrimitiveLiteral(value); - } + override renderValueLiteral = renderPrimitiveLiteral;Also applies to: 178-180, 261-263, 303-305, 345-347, 387-389, 429-431, 471-473, 1019-1021, 1043-1045, 1069-1071, 1090-1092
🤖 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-targets/3-targets/postgres/src/core/codecs.ts` around lines 95 - 113, Collapse the repeated renderValueLiteral override boilerplate by replacing the identical multi-line delegations with single-line class field assignments where the descriptor classes call renderPrimitiveLiteral directly. Use the existing renderPrimitiveLiteral helper and update each renderValueLiteral override mentioned in the diff (for example in the descriptor classes around those symbols) to preserve the same behavior with less duplication.
🤖 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-targets/3-targets/postgres/src/core/codecs.ts`:
- Around line 95-113: Collapse the repeated renderValueLiteral override
boilerplate by replacing the identical multi-line delegations with single-line
class field assignments where the descriptor classes call renderPrimitiveLiteral
directly. Use the existing renderPrimitiveLiteral helper and update each
renderValueLiteral override mentioned in the diff (for example in the descriptor
classes around those symbols) to preserve the same behavior with less
duplication.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: dd7c50e3-98b5-4f85-8d01-8f8db7aa859a
⛔ Files ignored due to path filters (1)
projects/refactor-enum-typing-via-codec/spec.mdis excluded by!projects/**
📒 Files selected for processing (17)
packages/1-framework/1-core/framework-components/src/control/control-stack.tspackages/1-framework/1-core/framework-components/src/control/emission-types.tspackages/1-framework/1-core/framework-components/src/shared/codec-descriptor.tspackages/1-framework/1-core/framework-components/src/shared/codec-types.tspackages/1-framework/1-core/framework-components/test/control-stack.test.tspackages/1-framework/3-tooling/emitter/src/domain-type-generation.tspackages/1-framework/3-tooling/emitter/test/domain-type-generation.test.tspackages/1-framework/3-tooling/emitter/test/emitter.integration.test.tspackages/1-framework/3-tooling/emitter/test/enum-typing-codec-seam.guard.test.tspackages/1-framework/3-tooling/emitter/test/generate-contract-dts.spi-branches.test.tspackages/2-mongo-family/3-tooling/emitter/src/index.tspackages/2-sql/3-tooling/emitter/test/emitter-hook.storage-column-types.test.tspackages/2-sql/3-tooling/emitter/test/value-set-codec-lookups.tspackages/3-extensions/mongo/test/mongo.enum.e2e.test.tspackages/3-mongo-target/2-mongo-adapter/src/core/codecs.tspackages/3-targets/3-targets/postgres/src/core/codecs.tspackages/3-targets/3-targets/postgres/test/codec-render-value-literal.test.ts
✅ Files skipped from review due to trivial changes (1)
- packages/3-targets/3-targets/postgres/test/codec-render-value-literal.test.ts
🚧 Files skipped from review as they are similar to previous changes (10)
- packages/2-sql/3-tooling/emitter/test/value-set-codec-lookups.ts
- packages/3-extensions/mongo/test/mongo.enum.e2e.test.ts
- packages/1-framework/3-tooling/emitter/test/emitter.integration.test.ts
- packages/1-framework/3-tooling/emitter/test/enum-typing-codec-seam.guard.test.ts
- packages/2-mongo-family/3-tooling/emitter/src/index.ts
- packages/1-framework/3-tooling/emitter/test/generate-contract-dts.spi-branches.test.ts
- packages/1-framework/1-core/framework-components/src/control/emission-types.ts
- packages/1-framework/3-tooling/emitter/src/domain-type-generation.ts
- packages/2-sql/3-tooling/emitter/test/emitter-hook.storage-column-types.test.ts
- packages/1-framework/3-tooling/emitter/test/domain-type-generation.test.ts
…um typing Extension-author entry: a value-set-restricted (e.g. enum) field/column now narrows its TS literal union through the codec, not the deleted domain-enum override. A custom CodecDescriptorImpl typing such a column must implement renderValueLiteral(value, side) or the column widens to the codec output type; a hand-built CodecLookup driving generateContractDts must expose renderValueLiteralFor (framework-built lookups already supply it). Validated by execution: reverting packages/3-extensions/ makes the mongo enum e2e go red, re-applying the entry reproduces the branch state, tests green 92/92. User entry: incidental (changes: [] unchanged) — the only examples/ touch is a type test asserting emit-vs-no-emit agreement; emitted contract byte-identical. Unblocks the check:upgrade-coverage Lint gate on PR #896. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…are renderTsLiteral - Delete the source-scanning guard test (enum-typing-codec-seam.guard): a grep-over-source vitest is not a real test; its A1/A2 properties hold by design and the behavioral tests. Soften the spec line that prescribed it. - Use the ifDefined helper for the Mongo-adapter descriptor conditional property spreads (renderOutputType / renderValueLiteral). - Extract the duplicated renderPrimitiveLiteral (Postgres + Mongo adapter) into a shared renderTsLiteral in @prisma-next/framework-components — it renders a TS literal (a framework concern both targets already depend on), not data. Both targets and the emitter test fixture import the one helper. Refactor-only; fixtures:check clean, lint:deps/casts clean. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
An enum column/field's TypeScript type is the union of its allowed values (
'low' | 'high' | 'urgent'). Today that union is built by printing the stored, codec-encoded values straight to TS literals in two separate emit-path spots — which bypasses the codec, the one component that knows a stored value's real TypeScript type. It's correct only by coincidence: today's enums use text/int codecs where the encoded form happens to equal the output type. This routes emit typing through the codec, on one path, and removes the duplication. SQL only; Mongo is the sibling TML-2953.No user-visible change for today's enums — correctness + de-duplication.
What changed
renderValueType(encodedValue, channel)onCodecDescriptorandrenderValueTypeForonCodecLookup— the value-keyed counterpart of the existingrenderOutputType. It renders a single codec-encoded value as its TS output literal, orundefinedwhen the codec can't (e.g. aDate-output codec — no base-class default, so non-identity codecs opt out). Implemented for the Postgres and Mongo primitive codecs.renderValueSetTypehelper, instead of printing the stored values directly (renderValueSetUnionBase/renderValueSetLiteraldeleted).DomainEnumLookup,renderEnumValueUnion,renderEnumMemberLiteral) is deleted; a new family-suppliedEmissionSpi.resolveFieldValueSethook supplies a field's permitted values, rendered through the same codec helper. The domainenumis no longer a typing input — it keeps only the runtimedb.enumsdictionary.Keeping Mongo byte-identical (the one design call worth flagging)
FieldOutputTypesis generated once for both families, and the framework emitter must not readstorage. So deleting the shared override bare would regress Mongo's emitted enum fields (the demorole: 'admin' | 'author' | 'reader'would widen tostring). The resolver hook resolves this cleanly:domain.enum(it has no value-set entity yet), keeping its output byte-identical. This is removed by TML-2953, which brings Mongo onto the value-set model.So the acceptance criterion "domain enum is not a typing input" holds for SQL now, and repo-wide once TML-2953 lands.
The no-emit (
typeof contract) path is unchanged — it already propagated the authored, typed values, and is the reference the emit path now matches.Acceptance evidence
db.enumsdictionary block and the Mongo interim resolver; the SQL emitter reads none.contract.jsondiff,fixtures:checkclean, the mongo-democontract.d.ts/.jsongit-unchanged across every commit.0|1|2, outputs'low'|'high'|'urgent') types as the codec output, not the raw encoded literal — on both the column and field surfaces.typeof contractunion.lint:castsdelta 0),lint:depsclean; build, typecheck, and the full test suites (packages/integration/e2e) green.Notes
projects/refactor-enum-typing-via-codec/. The spec was corrected during shaping: the family-resolver design (the framework must not reach into storage) and the SQL-scoping of A2.mainincluding Exercise Mongo enums in retail-store; add raw/execute/mongoEnums to the Mongo client #880 (Mongo enums in retail-store), which re-emits byte-identically under this change.Upgrade instructions (0.14 → 0.15)
skills/extension-author/prisma-next-extension-upgrade/upgrades/0.14-to-0.15/— a real entry: an extension that types a value-set-restricted (enum) column via a customCodecDescriptorImplmust implementrenderValueLiteral(and exposerenderValueLiteralForon a hand-builtCodecLookup), or the column widens to the codec output type. Framework-built lookups already supply it. Validated by execution (revertingpackages/3-extensions/reddens the mongo enum e2e; re-applying reproduces the branch, tests green).skills/upgrade/prisma-next-upgrade/upgrades/0.14-to-0.15/— user side is incidental (changes: []); the onlyexamples/touch is a type test and the emitted contract is byte-identical.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
stringtypes.Bug Fixes
Tests