JAQ Transformations
So far every payload matched the wire schema field for field. Real feeds rarely do. When a partner sends orders as a nested envelope, a JAQ codec reshapes the payload at the boundary instead of declaring a wire schema: the codec parses the native format and runs a jq-style program whose outputs must each be a JSON object matching the internal schema. The concise JAQ Reference links the complete, version-matched upstream manual.
Suppose the partner posts this envelope:
{"order":{"id":"o-5001","customer":"acme","state":"new"},"totals":{"amount":1200,"quantity":4}}
A JAQ Codec
A JAQ codec replaces the wire schema entirely — it goes straight from the format to the internal schema, with the program inline:
BEGIN;
CREATE CODEC partner_order_codec
FROM JSON
TO SCHEMA order_record
WITH JAQ TRANSFORMATIONS ON INGESTION $jaq$
{
order_id: .order.id,
customer: .order.customer,
status: .order.state,
amount: .totals.amount,
quantity: .totals.quantity
}
$jaq$;
The explicit ON INGESTION direction means this codec decodes but cannot encode. A bidirectional
codec adds ON EMITTING '<program>' after the ingestion program
(JAQ Transformations). FROM accepts JSON, YAML,
TOML, XML, and CBOR.
Two rules to remember: any field the program can produce as null must be OPTIONAL in the
internal schema, and surplus keys in the program’s output are silently dropped.
Wire It To An Endpoint
Reuse the vhost from HTTP Ingestion with a second path:
CREATE RELAY partner_orders SCHEMA order_record UNBRANCHED;
CREATE ENDPOINT partner_ingress ON edge PATH '/partner-orders' TYPE HTTP;
CREATE HTTP ENDPOINT INGESTOR partner_order_source
FROM partner_ingress MODE NO ACK
ON QUIESCE BUFFER MAX SIZE 1MiB DECODE USING partner_order_codec
TO partner_orders
INHERIT ALL
UNBRANCHED
FLUSH IMMEDIATE
ON MESSAGE ERROR LOG
ON GENERAL ERROR LOG;
COMMIT;
Send The Envelope
nervix-cli --domain quickstart subscribe partner_watch partner_orders
curl -i -X POST http://127.0.0.1:8080/partner-orders \
-H 'Host: orders.example.com' \
-H 'Content-Type: application/json' \
-d '{"order":{"id":"o-5001","customer":"acme","state":"new"},"totals":{"amount":1200,"quantity":4}}'
The subscription shows the flattened order_record — the envelope never enters the graph.
Unfold A Batch
A partner that sends several orders in one body needs no second endpoint. Every object the program yields becomes its own message, so a program that iterates an array unfolds one POST into one record per element:
CREATE CODEC partner_batch_codec
FROM JSON
TO SCHEMA order_record
WITH JAQ TRANSFORMATIONS ON INGESTION $jaq$
.orders[] | {
order_id: .order.id,
customer: .order.customer,
status: .order.state,
amount: .totals.amount,
quantity: .totals.quantity
}
$jaq$;
An ingestor decoding with partner_batch_codec turns a body of {"orders":[...]} into one
order_record per element, in array order. The body is still accepted or rejected as a whole: if
one element does not fit the schema, no record from that body enters the graph.
Unfolding Payloads covers acknowledgement, limits, and
diagnostics.
Next: binary payloads in Protobuf Codecs.