The ordered row array defining the pipeline.
The current job data used to resolve {data.*}
and {activity.*} references.
Optionalcontext: PipeContextOptional iteration context ($item, $key,
$output, etc.) supplied during @reduce execution.
Executes the pipeline row-by-row, resolving and transforming until the final value is produced.
Optional pre-resolved seed values (used
internally by reduce to inject the accumulator).
The first cell of the final resolved row.
Row 0 is resolved independently (values only). Each subsequent
row feeds the prior row's resolved output as arguments to the
function named in cell 0. Nested @pipe rows are queued
(fan-out) and collected into the next standard row (fan-in).
@reduce rows iterate over the prior row's array output.
Resolves a single cell value by detecting its type — function
call ({@domain.fn}), context variable ({$item}, {$key},
etc.), mappable reference ({data.*}), or literal.
The cell to resolve.
The resolved runtime value.
Resolves a {data.*} or {activity.*} reference by walking
the dot-delimited path into jobData.
The mappable reference string (e.g. {data.user.name}).
StaticisReturns true if the value is a @pipe object (i.e. { '@pipe': [...] }).
The value to test.
StaticresolveStaticresolve
A functional data-transformation pipeline that resolves expressions row-by-row against live job data.
Remarks
Overview
Pipe is the engine behind HotMesh's
@pipesyntax — a uniform, functional approach to data mapping and transformation. Every ECMAScript operation is expressed as a function with inputs, eliminating the syntactic variability of the language (ternaries, property access, instance methods) in favor of a single, composable pattern.Postfix notation (Reverse Polish Notation)
If you've used an RPN calculator,
@pipewill feel familiar. Operands come first, then the operator consumes them:That's the entire model. Operands are pushed, an operator pops them, and the result becomes an operand for the next row.
How it works — row by row
A pipe is an ordered array of rows. Each row is an array of cells. The key rule: every resolved value on a row flows into cell 0 of the next row (the operator). The operator consumes all upstream operands, resolves to a new value, and that result becomes an operand. Any remaining cells on the same row are resolved independently and appended as additional operands. Then the cycle repeats.
Step by step:
{data.*}references, or nullary functions like{@date.now}). The resolved values are all operands.{@domain.method}). It receives all operands from Row 0 as its arguments and produces a result. That result replaces cell 0 — it is now an operand. Any remaining cells (cell 1, 2, ...) on this row are resolved independently and become additional operands.When an additional cell on an operator row needs computed (not just a static value or simple reference), use a nested
@pipe(sub-pipe) to resolve it. See Example 4 below.Three types of cell values
42,"hello",true{path}{a.output.data.name}{@domain.method}{@string.concat},{@math.add}Available function domains
get,length,join,concat,push,indexOf, ...and,or,xor,not, ...ternary,equality,nullish, ...nextDelaynow,toLocaleString,yyyymmdd, ...parse,stringifyand,or,notadd,multiply,pow,max,min,abs, ...isEven,isOdd,gte,lte, ...create,get,set,keys, ...concat,split,charAt,toLowerCase,includes, ...Example 1 — Simple field mapping (YAML)
Most fields need only a one-to-one reference. Curly braces pull values from upstream activity outputs:
The equivalent JavaScript object passed to the mapper:
Example 2 — String transformation (YAML → JS)
Build a
user_namelikejdoefrom "John Doe". Follow the RPN flow — operands feed into the operator on the next row, the result becomes an operand, extra cells append more operands:RPN trace (given first_name="John", last_name="Doe"):
Example 3 — Conditional logic (YAML → JS)
Classify an employee as "Senior" or "Junior" based on age:
RPN trace (given age=30):
Example 4 — Nested pipes (fan-out / fan-in)
Extract initials from a full name. Each nested
@piperuns independently (fan-out), then the first standard row after them receives all sub-pipe results as inputs (fan-in):Example 5 — Reduce (iterate and accumulate)
Transform an array of
{ full_name }objects into{ first, last }pairs using@reduce. Context variables{$item},{$key},{$index},{$input}, and{$output}are available inside the reducer body:Example 6 — Transition conditions
Pipes power conditional transitions between workflow activities. In YAML, a transition fires only when the
@piperesolves to theexpectedvalue:Example 7 — Inline YAML with HotMesh.deploy
HotMesh ships with an inline YAML parser, so a complete workflow with data mapping can be deployed in a single call: