~/gqlith — docs/typed-jsonb.md
Early access gqlith is in private early access — the code is not publicly available yet. These docs preview the surface so you know what to expect. Join the list →

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 JSON blob; 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) alongside set.
  • 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 marked sortable. The same expressions work on GraphQL, REST and MCP.
  • Optional database enforcementtypedJson.checkMode emits reference DDL: portable CHECK constraints or pg_jsonschema validation, plus index templates, so the shape holds even for writes that bypass the API.
  • Drift detectiongqlith typed-json check reports 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.