fix(typegen): omit generated columns from Insert and Update types - #1105
Closed
daviddallakyan2005 wants to merge 1 commit into
Closed
fix(typegen): omit generated columns from Insert and Update types#1105daviddallakyan2005 wants to merge 1 commit into
daviddallakyan2005 wants to merge 1 commit into
Conversation
Stored GENERATED columns are not writable, but TypeScript typegen only excluded identity-ALWAYS columns. Treat is_generated the same way.
daviddallakyan2005
requested review from
a team,
avallete and
soedirgo
as code owners
August 14, 2026 23:05
Contributor
|
Thank you for the contribution! postgres-meta's type generation is moving to the shared |
spydon
added a commit
to supabase/sdk
that referenced
this pull request
Aug 31, 2026
… Args, trigger-writable views (#125) ## Summary Ports the worthwhile TypeScript generator fixes from postgres-meta's open template PRs into this package (the templates are being deleted in favor of this package in supabase/postgres-meta#1084, so open fixes there are triaged and re-landed here). Four fixes, one commit each: 1. **Stored generated columns omitted from Insert/Update** (from supabase/postgres-meta#1105): `GENERATED ALWAYS AS ... STORED` columns reject writes in Postgres, but only identity-ALWAYS columns were excluded; both now emit `?: never`. 2. **Non-nullable json narrowed to `NonNullable<Json>`** (from supabase/postgres-meta#1085): the emitted `Json` type includes `null`, so a NOT NULL json/jsonb column structurally permitted null. Known accepted edge: a NOT NULL jsonb column holding a JSON `'null'::jsonb` value still serializes as JS `null`, so Row is optimistic in that case; Insert/Update narrowing is fully sound. 3. **Zero-argument function Args typed `Record<PropertyKey, never>`** (the still-valid half of supabase/postgres-meta#1035): `Args: never` makes postgrest-js treat every zero-argument function as a computed field (`never extends { '': Row }` always holds), dropping same-named columns from `select('*')` results, and an uninhabited `Database` breaks sound type tooling. Verified against postgrest-js, whose `IsMatchingArgs` special-cases `Record<PropertyKey, never>`. 4. **Insert/Update types for INSTEAD OF trigger views** (from supabase/postgres-meta#1062, reimplemented): views made writable by INSTEAD OF triggers got no Insert/Update types. Views now carry `is_insert_enabled`/`is_update_enabled` computed via `pg_relation_is_updatable(oid, true)` (bit 8 INSERT, bit 4 UPDATE; also covers INSTEAD rules), gated independently, and column updatability counts triggers too (`pg_column_is_updatable(oid, attnum, true)` plus an explicit INSTEAD OF INSERT trigger check, since that function only considers the UPDATE event). The origin PR duplicated hand-rolled pg_trigger subqueries with one pair of wrong bit values and left trigger-writable columns degrading to `?: never`, visible in its own snapshot. The two new `PostgresView` fields are additive (metadata version stays 1), documented, and mirrored in the frozen equivalence contract. ## Triage of origin PRs | postgres-meta PR | Verdict | Reasoning | |---|---|---| | #1105 | Ported | Two-line correctness fix; `is_generated` was already introspected. | | #1085 | Ported | Nullability chokepoint fix; function returns and composite attributes untouched. | | #1035 | Ported (zero-arg half) | The computed-field-filtering half is superseded: this package introspects with `includeTableTypes: true`, so table/view row types already resolve (parity golden shows computed fields working). Only foreign-table row types remain uncovered; the PR's name-string matching is too fragile to port for that niche. | | #1062 | Reimplemented | Right idea, broken execution (wrong tgtype bits in one duplicated subquery pair, all-`never` Update output in its own snapshot). | | #1063 (TS part) | Skipped | Superseded: composite attributes already emit `| null` on main; the PR's remaining delta (`unknown | null`) is the identical type. | | #1048 (vector to `number[]`) | Skipped | Wrong as a global remap: PostgREST serializes pgvector as strings in responses, so Row types would regress; the reviewer asked for e2e evidence and got none. Needs input/output-aware mapping, a design discussion. | | #973 (`| string` numeric inserts) | Skipped | Maintainer requested changes: breaking for consumers expecting `number`; per-column overrides are the escape hatch. | | #573 | Skipped | Blanket `| null` on function args/returns is breaking (author concedes); the centralization half is superseded by the current generator; the domain-resolution gap is real but needs a metadata contract extension (feature-scale, raised separately). | | #750 (`Json` to `unknown`) | Skipped | Breaking; major-version decision. | | #1044 (int8 to `bigint`) | Skipped | Breaking, and incorrect without a custom JSON parser. | | #1083 (`bigint_as` option) | Skipped | Feature/option with API design questions, not a fix. | | #814 (json_schema constraint types) | Skipped | New feature. | ## Validation - Unit tests per fix, plus Docker-backed introspection integration tests proving a join view with an INSTEAD OF INSERT trigger introspects as insert-enabled/update-disabled with updatable columns, and auto-updatable views keep both flags. - Parity golden regenerated and reviewed line by line: the only change is 14 zero-argument functions switching `Args: never` to `Args: Record<PropertyKey, never>`. Fixes 1, 2 and 4 have no fixture-visible effect. - `check-types`, `format-and-lint`, `knip`, `build`, `test` (99 pass across 12 files) all green. - Note: the nightly parity job against real postgres-meta will show this intentional drift until postgres-meta consumes a release containing it (supabase/postgres-meta#1084 replaces the templates with this package, closing the gap).
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.
Fixes #838
Stored
GENERATED ALWAYS AS … STOREDcolumns are not writable, but TypeScript typegen only excluded identity-ALWAYS columns.is_generatedis already populated by column introspection; Insert/Update now treat it the same way and emitfield?: never, while the column remains on Row. Go, Swift, and Python generators are separate and still include generated columns — this PR is TypeScript-only.How to test
npm install npm testnpm teststarts Postgres viatest/db/docker-compose.yml(Docker required) and runs Vitest. Use Node 22 (.nvmrc). The new assertion istypegen: typescript omits generated columns from Insert and Updateagainst fixture tablepublic.people.