Skip to content

feat: add x-postgrest-typegen-metadata to openapi#6

Draft
avallete wants to merge 1 commit into
supabase:mainfrom
avallete:feat/add-x-postgrest-typegen-metadata-openapi-block
Draft

feat: add x-postgrest-typegen-metadata to openapi#6
avallete wants to merge 1 commit into
supabase:mainfrom
avallete:feat/add-x-postgrest-typegen-metadata-openapi-block

Conversation

@avallete

Copy link
Copy Markdown
Member

Add additional metadata to the openapi specs endpoint from postgrest.

A new x-postgrest-typegen-metadata block allowing postgrest-js type generation to be totally driven by a PostgREST endpoint.

Related: supabase/pg-toolbelt#303

@avallete
avallete force-pushed the feat/add-x-postgrest-typegen-metadata-openapi-block branch 3 times, most recently from cf5933b to 9c25e09 Compare June 20, 2026 16:57
Opt-in `openapi-metadata` config that adds a top-level
`x-postgrest-typegen-metadata` vendor extension to the OpenAPI output,
carrying catalog-grade metadata not otherwise expressible in OpenAPI:
object kind, identity/generated columns, the full relationship graph with
cardinality, function return types (incl. OUT/TABLE columns), composite
types and computed fields.

This lets clients (e.g. @supabase/postgrest-typegen) generate faithful
types from the OpenAPI document alone, with no database connection.
Disabled by default; standard OpenAPI consumers ignore the extra x- key.
@avallete
avallete force-pushed the feat/add-x-postgrest-typegen-metadata-openapi-block branch from 9c25e09 to fb3a733 Compare June 20, 2026 17:14
Typegen metadata extension
--------------------------

PostgREST's OpenAPI is a name-based description of the API surface, which is lossy for client type generation (it cannot distinguish tables from views, identity columns, function return types, composite types, etc.). To support faithful type generation directly from the OpenAPI document, set ``openapi-metadata`` to ``true``. PostgREST then adds a top-level ``x-postgrest-typegen-metadata`` `vendor extension <https://spec.openapis.org/oas/v2.0#specification-extensions>`_ to the output, carrying catalog-grade metadata not otherwise expressible in OpenAPI:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@laurenceisla Since you've done a lot of work on OpenAPI, is x-postgrest-typegen-metadata our only option for this new metadata?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The motivation is on slack (private link)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I can see, there are some overlapping fields between x-postgrest-typegen-metadata and regular OpenAPI/JSONSchema like nullable, enum, default, etc. for tables and views (and some others for functions). So, an alternative would be to add these x-<my-custom-field> to each Object (parameter, path, etc.), similar to what's proposed here. However the relationships field has more info that may be difficult to express in the OpenAPI output, I can't find a way to easily convey this rn.

I guess having all the relevant info inside the x-postgrest-typegen-metadata is an easier way to retrieve the data that is needed. However, I think we should still check if there's a way to avoid doing this and using the default OpenAPI output instead to avoid duplicity. But, if there's no alternative then yes, the custom field would be needed.

@laurenceisla laurenceisla Jun 23, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The motivation is on slack (private link)

From a comment there:

I'm not sure if OpenAPI is the right approach since it might not support all usecases needed by the typegen package. I think it's easier if each typegen target has its own SQL code you run against the db and it builds the output from that.

I wonder if having https://github.com/PostgREST/postgrest-openapi would make the creation of custom fields like this one easier (since it's using SQL directly). The customers that need to modify the output wouldn't need to wait for a PR to be approved or to check if PostgREST would allow it in core in the first place.

Comment on lines +648 to +671
-- | Distinct-by-key, preserving first occurrence.
nubOn :: Eq b => (a -> b) -> [a] -> [a]
nubOn f = go []
where
go _ [] = []
go seen (x:xs)
| f x `elem` seen = go seen xs
| otherwise = x : go (f x : seen) xs

-- | Map a pg regtype text (SQL spelling, possibly schema-qualified) to the
-- pg_catalog short type name the typegen generator expects (int8, _text, …).
shortType :: Text -> Text
shortType raw
| "[]" `T.isSuffixOf` raw = "_" <> shortType (T.dropEnd 2 raw)
| otherwise = maybe bare snd (find ((== bare) . fst) sqlToShort)
where
bare = T.takeWhileEnd (/= '.') raw
sqlToShort =
[ ("integer", "int4"), ("bigint", "int8"), ("smallint", "int2")
, ("boolean", "bool"), ("double precision", "float8"), ("real", "float4")
, ("character varying", "varchar"), ("character", "bpchar")
, ("timestamp with time zone", "timestamptz")
, ("timestamp without time zone", "timestamp")
, ("time with time zone", "timetz"), ("time without time zone", "time") ]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we move this Haskell logic to SQL?

@laurenceisla laurenceisla Jun 23, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are Postgres types, right? Then yeah, I think what this is doing is taking the long names that PostgREST retrieves from PostgreSQL and then converting them to short names. So there's no need to do this transformation if the schema cache query also takes the short names alongside the long names.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants