feat(codegen-ts): jsonb value-object typing + collection-name control + shared VO module resolver#49
Merged
dmealing merged 1 commit intoJun 20, 2026
Conversation
… + shared VO module resolver
Three independent codegen-ts adoption fixes that share the same render
pipeline (so they land together to avoid intermingled-file rebases), plus a
timestamp-mode config knob.
1. Postgres jsonb value objects
- field.object no longer emits a native .array() — an object array lives in
ONE jsonb column, not jsonb[]. Suppressed when subType === object.
- jsonb object columns now carry .$type<VO>() / .$type<VO[]>() (the previous
.$type path was sqlite-only, so Postgres object columns inferred `unknown`).
Added an `array` flag to ColumnSpec.dollarTypeRef so the renderer picks the
single vs collection form. Applies to single objects too, not just arrays.
2. Collection (table) variable naming control
- New codegen config: `pluralizeCollections` (default true) and
`collectionNameOverrides` (per-entity exact names). Surfaced as a single
`ctx.collectionName(entity)` resolver used by every template that emits or
references a table var (schema, queries, routes, relations, inferred types),
so the declaration and all references stay consistent. Naming is a per-port
codegen concern, so this is config — not a metadata attribute — and carries
no cross-port conformance cost.
3. Shared value-object module resolver (consistency fix)
- New `valueObjectModuleSpecifier()` is the single source of truth feeding all
three places that reference a VO module — the field's TS type, its Zod
schema, and the Drizzle .$type<>(). Previously each hardcoded `./<VO>.js`,
which was wrong under package layout + cross-package refs and ignored
extStyle. Now layout/package/extStyle-aware (matching FK-reference
resolution); proven by a two-package end-to-end fixture.
4. `timestampMode` config ("date" | "string", default "string") applied
uniformly to the plain timestamp + timestamptz override branches, keeping the
Drizzle column aligned with the generated Zod + the cross-port wire contract.
Default config reproduces byte-identical output, so all golden/conformance
fixtures are unchanged. New coverage: jsonb-VO column cases, the
pluralize/override resolver, the VO module resolver (flat/same-pkg/cross-pkg/
extStyle), and an end-to-end cross-package VO fixture asserting all three
references resolve identically.
Tests: codegen-ts 799/0, codegen-ts-react/angular/tanstack + conformance 134/0,
migrate-ts 488/0, cli 277/0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three independent codegen-ts adoption fixes that share the same render pipeline (so they land together to avoid intermingled-file rebases), plus a timestamp-mode config knob.
1. Postgres jsonb value objects
field.objectno longer emits a native.array()— an object array lives in one jsonb column, notjsonb[]. Suppressed whensubType === object..$type<VO>()/.$type<VO[]>()(the previous.$typepath was sqlite-only, so Postgres object columns inferredunknown). Added anarrayflag toColumnSpec.dollarTypeRefso the renderer picks single vs collection. Applies to single objects too, not just arrays.2. Collection (table) variable naming control
pluralizeCollections(defaulttrue) +collectionNameOverrides(per-entity exact names). Surfaced as a singlectx.collectionName(entity)resolver used by every template that emits or references a table var (schema, queries, routes, relations, inferred types), so the declaration and all references stay consistent. Naming is a per-port codegen concern → config, not a metadata attribute → no cross-port conformance cost.3. Shared value-object module resolver (consistency fix)
valueObjectModuleSpecifier()is the single source of truth feeding the three places that reference a VO module — the field's TS type, its Zod schema, and the Drizzle.$type<>(). Previously each hardcoded./<VO>.js, wrong under package layout + cross-package refs and ignoringextStyle. Now layout/package/extStyle-aware (matching FK-reference resolution); proven by a two-package end-to-end fixture.4.
timestampMode"date" | "string"(default"string"), applied uniformly to the plaintimestamp+timestamptzoverride branches, keeping the Drizzle column aligned with the generated Zod + the cross-port wire contract.Compatibility & tests
Default config reproduces byte-identical output, so all golden/conformance fixtures are unchanged. New coverage: jsonb-VO column cases, the pluralize/override resolver, the VO module resolver (flat / same-pkg / cross-pkg / extStyle), and an end-to-end cross-package VO fixture asserting all three references resolve identically.
🤖 Generated with Claude Code