7.2 The typed spec and the string DSL (two inputs, one stored form)
A pipeline can be written two ways. Both are accepted as input; the runtime canonicalizes to the typed spec and stores that. You author in whichever reads better; you read back typed.
The typed spec
The structured form — a JSON object with a mode and an array of steps:
{
"mode": "serial",
"onFail": "stop",
"steps": [
{ "call": { "method": "GET", "url": "/data/orders/${id}" }, "as": "$order" },
{ "if": "$order.status == 'open'",
"call": { "method": "POST", "url": "/payments/charge", "effect": "keyed" },
"try": true },
{ "transform": { "total": "$sum($order.lines.price)", "charged": "$_ok" } }
]
}
This is exactly what the runtime stores and what ?$plan shows. It's the form to
reach for when a step needs fields the DSL can't express compactly (an explicit
effect, headers, nested joins).
The string DSL
The terse form carried over from Restspace v1 — a JSON array, one string per step:
[
"GET /data/orders/${id} :$order",
"try if ($order.status == 'open') POST /payments/charge",
{ "total": "$sum($order.lines.price)", "charged": "$_ok" }
]
It's accepted anywhere a spec is (the envelope's pipeline field, rs2 migrate)
and converted on the way in. For straight-line call/condition/capture flows it's
markedly more readable, which is why it's often the better authoring choice.
DSL element kinds
| Element | Meaning |
|---|---|
| Leading mode token | "serial", "parallel", "conditional", "tee", "teeWait" — optionally with fail/succeed actions ("serial stop end"). Only counts as the first element |
| Step string | try? if (cond)? METHOD url ( :$var | :name)? |
| JSON object | a transform (JSONata template) |
| Nested array | a subpipeline |
"jsonSplit" |
a splitter step |
"jsonObject" |
a joiner |
Step-string anatomy, in order: optional try, optional if (condition), then
METHOD url, then an optional suffix — :$var to capture the result into a
variable, or :name to name the step (used by parallel/join). zip,
unzip, and multipart are not supported in v1.
Equivalence
The two examples above are the same pipeline. The DSL's :$order becomes the
typed "as": "$order"; try if (…) becomes "try": true + "if": "…"; a bare
object is a transform; a nested array is a pipeline step. After writing in the
DSL, run ?$plan to see the typed form the runtime produced (7.8).
The next sections work through what steps can do — first the step kinds, then the modes that combine them.
← Previous: 7.1 The pipeline service · Manual home · Next: 7.3 Step kinds →