Accept/Content-Type media-type negotiation, mirroring PostgREST's
PostgREST.MediaType.
A parsed media type is a %Bier.MediaType{} struct carrying the canonical
symbol (:json, :csv, :singular, :array_strip, …), the rendered MIME
string (toMime), and any preserved parameters (plan for/options, the
nulls=stripped flag, etc.).
Negotiation (negotiate/2) takes the request's ordered Accept preferences
and the set of media types a producer can emit, and returns the first
acceptable one (client order wins), or :not_acceptable.
Summary
Functions
Render the response Content-Type value for a resolved media type. charset
controls whether ; charset=utf-8 is appended — every type except
octet-stream / custom (:other) / :any carries the charset.
Parse one media type token (no q-value handling) into a struct, or nil for
an unrecognized custom/unknown token (still tracked so */* can rescue it).
The query-executor output format for a negotiated media type: :geojson
for application/geo+json (rows aggregated into a FeatureCollection via
ST_AsGeoJSON), :json_strip for any nulls=stripped type (the aggregate is
wrapped in json_strip_nulls, upstream's addNullsToSnip), :csv for
text/csv (rows aggregated as ordered [key, value] pair lists), :json for
everything else.
The media type a producer emits for symbol — the same struct negotiate/2
yields for that type.
Negotiate the client's ordered Accept preferences against the producer's
available media types (a list of symbols). Returns {:ok, %MediaType{}} for
the first acceptable preference (client order wins), or :not_acceptable.
Parse an Accept header into an ordered list of %Bier.MediaType{} entries.
Order follows client order (PostgREST does not reorder by q-value); a q=0
entry is dropped.
Types
Functions
Render the response Content-Type value for a resolved media type. charset
controls whether ; charset=utf-8 is appended — every type except
octet-stream / custom (:other) / :any carries the charset.
Parse one media type token (no q-value handling) into a struct, or nil for
an unrecognized custom/unknown token (still tracked so */* can rescue it).
The query-executor output format for a negotiated media type: :geojson
for application/geo+json (rows aggregated into a FeatureCollection via
ST_AsGeoJSON), :json_strip for any nulls=stripped type (the aggregate is
wrapped in json_strip_nulls, upstream's addNullsToSnip), :csv for
text/csv (rows aggregated as ordered [key, value] pair lists), :json for
everything else.
These belong in SQL rather than in Bier.Render because decoding the body
into Elixir terms and re-encoding it loses JSON key order and the exact
numeric text PostgreSQL emitted (#109, #110).
The media type a producer emits for symbol — the same struct negotiate/2
yields for that type.
Used where the response's Content-Type is fixed by the resource instead of
being negotiated: the generated root document always renders
toContentType MTOpenAPI whatever the request asked for
(Response.hs actionResponse (MaybeDbResult InspectPlan …)).
Negotiate the client's ordered Accept preferences against the producer's
available media types (a list of symbols). Returns {:ok, %MediaType{}} for
the first acceptable preference (client order wins), or :not_acceptable.
*/* matches the producer's default (first available). A specific preference
listed before */* overrides */*.
Parse an Accept header into an ordered list of %Bier.MediaType{} entries.
Order follows client order (PostgREST does not reorder by q-value); a q=0
entry is dropped.