Per-request context enrichment.
An enricher is a fn / protocol impl that runs once per GraphQL operation before validators and the backend chain. It receives the current request ctx (headers plus any values added by earlier enrichers) and returns a map of new values to merge in.
Typical use case in a Spring Boot app: pull the customer / equipment identifiers out of Redis using the JWT subject, so every step and validator downstream can read them from ctx without repeating the lookup.
Enrichers are supplied to bff.core/create-handler as an ordered
sequence; each sees the accumulated ctx from earlier enrichers.
Per-request context enrichment. An enricher is a fn / protocol impl that runs once per GraphQL operation before validators and the backend chain. It receives the current request ctx (headers plus any values added by earlier enrichers) and returns a map of new values to merge in. Typical use case in a Spring Boot app: pull the customer / equipment identifiers out of Redis using the JWT subject, so every step and validator downstream can read them from ctx without repeating the lookup. Enrichers are supplied to `bff.core/create-handler` as an ordered sequence; each sees the accumulated ctx from earlier enrichers.
Example custom validator wired into the demo spec by key.
Example custom validator wired into the demo spec by key.
Boundary conversion between Clojure and Java implementations of BFF extension points. Java authors expect String-keyed java.util.Map and java.util.List; the rest of the engine uses keyword-keyed Clojure maps.
Boundary conversion between Clojure and Java implementations of BFF extension points. Java authors expect String-keyed java.util.Map and java.util.List; the rest of the engine uses keyword-keyed Clojure maps.
Impl-resolution helper shared across every extension point.
A spec references an extension in one of two forms:
{:key "my-fn"} → look up in the caller's registry map {:ns "my.ns" :fn "my-fn"} → resolve a Clojure var by symbol
Both forms return the extension implementation; the caller invokes it with whatever arity is appropriate for the extension type.
Impl-resolution helper shared across every extension point.
A spec references an extension in one of two forms:
{:key "my-fn"} → look up in the caller's registry map
{:ns "my.ns" :fn "my-fn"} → resolve a Clojure var by symbol
Both forms return the extension implementation; the caller invokes it
with whatever arity is appropriate for the extension type.Step-level retry with an optional pre-retry hook.
A step declares retry behaviour under its :retry key:
:retry {:max 2
:on_code [:unauthorized]
:before_retry {:key "cmap-token-refresh"}}
The hook is called before each retry attempt with a failure-context map; its return value replaces the request-ctx used for the next call. Common use case: refresh a bearer token and inject it into the Authorization header before the retry.
Step-level retry with an optional pre-retry hook.
A step declares retry behaviour under its `:retry` key:
:retry {:max 2
:on_code [:unauthorized]
:before_retry {:key "cmap-token-refresh"}}
The hook is called before each retry attempt with a failure-context map;
its return value replaces the request-ctx used for the next call. Common
use case: refresh a bearer token and inject it into the Authorization
header before the retry.Custom GraphQL scalar types.
A scalar declared in the spec's top-level scalars: list must have a
matching implementation in the handler's :scalars extension map. Each
implementation provides two fns:
• parse: input from client (string / number / etc.) → internal value. Throws on invalid input. • serialize: internal value → JSON primitive (String / Number / Boolean / nil).
The engine wires these into Lacinia's :scalars schema section at build-schema time.
Built-in convenience scalars for common date/time types are provided — {@code bff.scalar/date-time}, {@code bff.scalar/date}, {@code bff.scalar/local-date-time} — that users can drop into their config without writing parse/serialize themselves.
Custom GraphQL scalar types.
A scalar declared in the spec's top-level `scalars:` list must have a
matching implementation in the handler's :scalars extension map. Each
implementation provides two fns:
• parse: input from client (string / number / etc.) → internal value.
Throws on invalid input.
• serialize: internal value → JSON primitive
(String / Number / Boolean / nil).
The engine wires these into Lacinia's :scalars schema section at
build-schema time.
Built-in convenience scalars for common date/time types are provided —
{@code bff.scalar/date-time}, {@code bff.scalar/date},
{@code bff.scalar/local-date-time} — that users can drop into their config
without writing parse/serialize themselves.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |