7.10 Wrappers and response shaping

The pipeline service is a store of many named flows. When you need exactly one fixed flow in front of another mount, use wrapper: the pipeline lives inline in mount config and governs every verb and subpath.

A read-only facade

{ "path": "/users", "service": "wrapper", "config": {
    "access": { "read": "authenticated", "write": "A" },
    "pattern": "store-view",
    "facets": ["schema"],
    "pipeline": ["GET /data/users${url.rest}"]
} }

GET /users/ada@example.com runs the inline pipeline, and ${url.rest} forwards /ada@example.com exactly. This example deliberately presents a read-only store view; a full store facade uses method conditions to dispatch GET, PUT, PATCH, POST, and DELETE to matching call steps. There is no .pipelines/ authoring subtree and no .root; changing the wrapper means changing tenant config.

Unlike most prebuilt services, a wrapper declares the conversation shape it presents:

  • pattern is one of store, store-transform, store-view, view, or api (default store-transform).
  • facets advertises optional behavior such as schema or patch.
  • inputSchema is compile-checked and enforced on PUT/POST/PATCH before the pipeline runs.
  • outputSchema is compile-checked and advertised in discovery/OpenAPI, but is advisory because one facade may return several response shapes.

The wrapper's own access is enforced first, and internal calls still carry the caller to the wrapped mount. elevate and external httpOut calls work exactly as they do on a pipeline mount. Use a wrapper for one fixed facade; use a pipeline mount for many authored, per-path specs.

Shaping status, headers, media type, and body

A normal transform replaces the JSON body. A transform whose output has the single key $response can shape the full HTTP response:

{ "transform": { "$response": {
    "status": "201",
    "headers": { "Location": "'/things/1'" },
    "mediaType": "'text/html'",
    "body": "'<p>created</p>'"
} } }

These strings are JSONata expressions, like every transform leaf; the inner quotes produce literal strings. All fields are optional. A string body is raw text (default text/plain); other body values remain JSON. Omitting body keeps the body that entered the transform, which is useful when you only need to set a status, header, or media type. Invalid status codes or non-scalar header values are 400 errors.

A captured (as) $response object is ordinary data; capture never secretly changes the outward response. This keeps response shaping explicit at the point where the flow returns to its caller.


Previous: 7.9 Debugging a pipeline · Manual home · Next: 7.11 Webhooks and schedules →