Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.