Docs / Batteries
Typed JSONB
Declare a JSONB column's shape once with @gqlith.jsonSchema — get real GraphQL types, validated writes, typed filtering and ordering, optional CHECK constraints, and a drift-check CLI.
Most APIs surface a JSONB column as an opaque JSON scalar: no types, no validation, no filtering. If your app knows the column’s shape, declare it once — on the column — and gqlith compiles the whole story from it:
COMMENT ON COLUMN orders.shipping_info IS 'Shipping details captured at checkout.
@gqlith.jsonSchema(fields: "
carrier: enum(ups|fedex|dhl)!,
eta: datetime,
weightKg: float {minimum: 0},
dims: {w:float!, h:float!, d:float!},
tags: [string] {maxItems: 20}
", name: "OrderShippingInfo")';
Large shapes can instead be registered in gqlith.yaml (typedJson.schemas, a constrained JSON-Schema subset) and referenced with @gqlith.jsonSchema(ref: "…").
From that one declaration:
- Real types on the wire — GraphQL object types and genuine enums instead of a
JSONblob; the client SDK sub-selects into the shape with full inference. Reads are fail-soft: a legacy row that predates the shape doesn’t crash the query. - Validated writes — create and update inputs are typed, and values are strictly validated with Zod before the database is touched. Partial updates get a first-class
patch(RFC 7396 deep-merge, re-validated) alongsideset. - Typed filtering, quantifiers, ordering — filter on declared paths with real operators, quantify over JSONB arrays with
some/every/none, and order by leaves you’ve markedsortable. The same expressions work on GraphQL, REST and MCP. - Optional database enforcement —
typedJson.checkModeemits reference DDL: portableCHECKconstraints orpg_jsonschemavalidation, plus index templates, so the shape holds even for writes that bypass the API. - Drift detection —
gqlith typed-json checkreports where stored data has drifted from the declared shape, and how adopted a shape is, before you tighten enforcement.
Untyped JSONB keeps working exactly as before — has_key, has_keys_any / has_keys_all, containment, is empty. @gqlith.jsonSchema is opt-in per column; declaring a shape is what unlocks path-level filtering and ordering.