@blokjs/helper 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,7 +13,6 @@ declare const ConditionElseSchema: z.ZodObject<{
13
13
  type: z.ZodEnum<["local", "module", "runtime.python3", "runtime.nodejs", "runtime.bun", "runtime.go", "runtime.java", "runtime.rust", "runtime.php", "runtime.csharp", "runtime.ruby", "runtime.docker", "runtime.wasm"]>;
14
14
  inputs: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
15
15
  runtime: z.ZodOptional<z.ZodEnum<["nodejs", "bun", "python3", "go", "java", "rust", "php", "csharp", "ruby", "docker", "wasm"]>>;
16
- set_var: z.ZodOptional<z.ZodBoolean>;
17
16
  active: z.ZodOptional<z.ZodBoolean>;
18
17
  stop: z.ZodOptional<z.ZodBoolean>;
19
18
  stream_logs: z.ZodOptional<z.ZodBoolean>;
@@ -23,7 +22,6 @@ declare const ConditionElseSchema: z.ZodObject<{
23
22
  type: "local" | "module" | "runtime.python3" | "runtime.nodejs" | "runtime.bun" | "runtime.go" | "runtime.java" | "runtime.rust" | "runtime.php" | "runtime.csharp" | "runtime.ruby" | "runtime.docker" | "runtime.wasm";
24
23
  inputs?: {} | undefined;
25
24
  runtime?: "nodejs" | "bun" | "python3" | "go" | "java" | "rust" | "php" | "csharp" | "ruby" | "docker" | "wasm" | undefined;
26
- set_var?: boolean | undefined;
27
25
  active?: boolean | undefined;
28
26
  stop?: boolean | undefined;
29
27
  stream_logs?: boolean | undefined;
@@ -33,7 +31,6 @@ declare const ConditionElseSchema: z.ZodObject<{
33
31
  type: "local" | "module" | "runtime.python3" | "runtime.nodejs" | "runtime.bun" | "runtime.go" | "runtime.java" | "runtime.rust" | "runtime.php" | "runtime.csharp" | "runtime.ruby" | "runtime.docker" | "runtime.wasm";
34
32
  inputs?: {} | undefined;
35
33
  runtime?: "nodejs" | "bun" | "python3" | "go" | "java" | "rust" | "php" | "csharp" | "ruby" | "docker" | "wasm" | undefined;
36
- set_var?: boolean | undefined;
37
34
  active?: boolean | undefined;
38
35
  stop?: boolean | undefined;
39
36
  stream_logs?: boolean | undefined;
@@ -46,7 +43,6 @@ declare const ConditionElseSchema: z.ZodObject<{
46
43
  type: "local" | "module" | "runtime.python3" | "runtime.nodejs" | "runtime.bun" | "runtime.go" | "runtime.java" | "runtime.rust" | "runtime.php" | "runtime.csharp" | "runtime.ruby" | "runtime.docker" | "runtime.wasm";
47
44
  inputs?: {} | undefined;
48
45
  runtime?: "nodejs" | "bun" | "python3" | "go" | "java" | "rust" | "php" | "csharp" | "ruby" | "docker" | "wasm" | undefined;
49
- set_var?: boolean | undefined;
50
46
  active?: boolean | undefined;
51
47
  stop?: boolean | undefined;
52
48
  stream_logs?: boolean | undefined;
@@ -59,7 +55,6 @@ declare const ConditionElseSchema: z.ZodObject<{
59
55
  type: "local" | "module" | "runtime.python3" | "runtime.nodejs" | "runtime.bun" | "runtime.go" | "runtime.java" | "runtime.rust" | "runtime.php" | "runtime.csharp" | "runtime.ruby" | "runtime.docker" | "runtime.wasm";
60
56
  inputs?: {} | undefined;
61
57
  runtime?: "nodejs" | "bun" | "python3" | "go" | "java" | "rust" | "php" | "csharp" | "ruby" | "docker" | "wasm" | undefined;
62
- set_var?: boolean | undefined;
63
58
  active?: boolean | undefined;
64
59
  stop?: boolean | undefined;
65
60
  stream_logs?: boolean | undefined;
@@ -16,7 +16,6 @@ declare const ConditionSchema: z.ZodObject<{
16
16
  type: z.ZodEnum<["local", "module", "runtime.python3", "runtime.nodejs", "runtime.bun", "runtime.go", "runtime.java", "runtime.rust", "runtime.php", "runtime.csharp", "runtime.ruby", "runtime.docker", "runtime.wasm"]>;
17
17
  inputs: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
18
18
  runtime: z.ZodOptional<z.ZodEnum<["nodejs", "bun", "python3", "go", "java", "rust", "php", "csharp", "ruby", "docker", "wasm"]>>;
19
- set_var: z.ZodOptional<z.ZodBoolean>;
20
19
  active: z.ZodOptional<z.ZodBoolean>;
21
20
  stop: z.ZodOptional<z.ZodBoolean>;
22
21
  stream_logs: z.ZodOptional<z.ZodBoolean>;
@@ -26,7 +25,6 @@ declare const ConditionSchema: z.ZodObject<{
26
25
  type: "local" | "module" | "runtime.python3" | "runtime.nodejs" | "runtime.bun" | "runtime.go" | "runtime.java" | "runtime.rust" | "runtime.php" | "runtime.csharp" | "runtime.ruby" | "runtime.docker" | "runtime.wasm";
27
26
  inputs?: {} | undefined;
28
27
  runtime?: "nodejs" | "bun" | "python3" | "go" | "java" | "rust" | "php" | "csharp" | "ruby" | "docker" | "wasm" | undefined;
29
- set_var?: boolean | undefined;
30
28
  active?: boolean | undefined;
31
29
  stop?: boolean | undefined;
32
30
  stream_logs?: boolean | undefined;
@@ -36,7 +34,6 @@ declare const ConditionSchema: z.ZodObject<{
36
34
  type: "local" | "module" | "runtime.python3" | "runtime.nodejs" | "runtime.bun" | "runtime.go" | "runtime.java" | "runtime.rust" | "runtime.php" | "runtime.csharp" | "runtime.ruby" | "runtime.docker" | "runtime.wasm";
37
35
  inputs?: {} | undefined;
38
36
  runtime?: "nodejs" | "bun" | "python3" | "go" | "java" | "rust" | "php" | "csharp" | "ruby" | "docker" | "wasm" | undefined;
39
- set_var?: boolean | undefined;
40
37
  active?: boolean | undefined;
41
38
  stop?: boolean | undefined;
42
39
  stream_logs?: boolean | undefined;
@@ -50,7 +47,6 @@ declare const ConditionSchema: z.ZodObject<{
50
47
  type: "local" | "module" | "runtime.python3" | "runtime.nodejs" | "runtime.bun" | "runtime.go" | "runtime.java" | "runtime.rust" | "runtime.php" | "runtime.csharp" | "runtime.ruby" | "runtime.docker" | "runtime.wasm";
51
48
  inputs?: {} | undefined;
52
49
  runtime?: "nodejs" | "bun" | "python3" | "go" | "java" | "rust" | "php" | "csharp" | "ruby" | "docker" | "wasm" | undefined;
53
- set_var?: boolean | undefined;
54
50
  active?: boolean | undefined;
55
51
  stop?: boolean | undefined;
56
52
  stream_logs?: boolean | undefined;
@@ -64,7 +60,6 @@ declare const ConditionSchema: z.ZodObject<{
64
60
  type: "local" | "module" | "runtime.python3" | "runtime.nodejs" | "runtime.bun" | "runtime.go" | "runtime.java" | "runtime.rust" | "runtime.php" | "runtime.csharp" | "runtime.ruby" | "runtime.docker" | "runtime.wasm";
65
61
  inputs?: {} | undefined;
66
62
  runtime?: "nodejs" | "bun" | "python3" | "go" | "java" | "rust" | "php" | "csharp" | "ruby" | "docker" | "wasm" | undefined;
67
- set_var?: boolean | undefined;
68
63
  active?: boolean | undefined;
69
64
  stop?: boolean | undefined;
70
65
  stream_logs?: boolean | undefined;
@@ -19,7 +19,6 @@ export default class StepNode extends HelperResponse {
19
19
  node: config.node,
20
20
  type: config.type,
21
21
  runtime: config.runtime,
22
- set_var: config.set_var,
23
22
  active: config.active,
24
23
  stop: config.stop,
25
24
  });
@@ -1 +1 @@
1
- {"version":3,"file":"StepNode.js","sourceRoot":"","sources":["../../src/components/StepNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,mBAAmB,EAEnB,cAAc,GACd,MAAM,mBAAmB,CAAC;AAG3B,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,cAAc;IACnD,OAAO,CAAC,MAAgB;QACvB,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAE7B,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC;QAC9D,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG;YACjC,MAAM,EAAE,MAAM,CAAC,MAAM;SACrB,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC;YACxB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,IAAI,EAAE,MAAM,CAAC,IAAI;SACjB,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG,IAAI,QAAQ,EAAE,CAAC;QACtC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO,cAAc,CAAC;IACvB,CAAC;IAED,YAAY,CAAC,UAA6B;QACzC,mBAAmB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,UAAoC,CAAC;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAA2C,CAAC;QAE5E,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC;QAE9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,KAAK,GAAG,SAAS,CAAC,KAAmB,CAAC;YAE5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACvC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBAEtB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;oBAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;iBACnB,CAAC;gBAEF,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;YACzB,CAAC;QACF,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC;QAC9D,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YAC1C,UAAU,EAAE,QAAQ;SACpB,CAAC;QAEF,MAAM,cAAc,GAAG,IAAI,QAAQ,EAAE,CAAC;QACtC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO,cAAc,CAAC;IACvB,CAAC;CACD"}
1
+ {"version":3,"file":"StepNode.js","sourceRoot":"","sources":["../../src/components/StepNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,mBAAmB,EAEnB,cAAc,GACd,MAAM,mBAAmB,CAAC;AAG3B,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,cAAc;IACnD,OAAO,CAAC,MAAgB;QACvB,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAE7B,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC;QAC9D,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG;YACjC,MAAM,EAAE,MAAM,CAAC,MAAM;SACrB,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC;YACxB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,IAAI,EAAE,MAAM,CAAC,IAAI;SACjB,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG,IAAI,QAAQ,EAAE,CAAC;QACtC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO,cAAc,CAAC;IACvB,CAAC;IAED,YAAY,CAAC,UAA6B;QACzC,mBAAmB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,UAAoC,CAAC;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAA2C,CAAC;QAE5E,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC;QAE9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,KAAK,GAAG,SAAS,CAAC,KAAmB,CAAC;YAE5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACvC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBAEtB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;oBAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;iBACnB,CAAC;gBAEF,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;YACzB,CAAC;QACF,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC;QAC9D,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YAC1C,UAAU,EAAE,QAAQ;SACpB,CAAC;QAEF,MAAM,cAAc,GAAG,IAAI,QAAQ,EAAE,CAAC;QACtC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO,cAAc,CAAC;IACvB,CAAC;CACD"}
@@ -0,0 +1,53 @@
1
+ import type { V2ForEachStep, V2Step } from "../types/StepOpts";
2
+ /**
3
+ * Author-facing options for {@link forEach}.
4
+ *
5
+ * `in` accepts either a literal expression string (`"$.state.items"` or
6
+ * `"js/ctx.state.items"`) or a `$` proxy expression that compiles to
7
+ * the same string at definition time.
8
+ *
9
+ * `as` is the per-iteration variable name. Each iteration sets
10
+ * `ctx.state[as]` to the current item and `ctx.state[as + "Index"]`
11
+ * to the 0-based position. Avoid using a name that collides with
12
+ * any step `id` in the surrounding workflow.
13
+ */
14
+ export interface ForEachOpts {
15
+ /** Stable identifier — visible in traces, referenced as `$.state[id]`. */
16
+ id: string;
17
+ /** Array source. Literal expression string or `$` proxy. */
18
+ in: string | unknown;
19
+ /**
20
+ * Per-iteration variable name. Each iteration sets `ctx.state[as] = item`
21
+ * and `ctx.state[as + "Index"] = i`. Must be a valid JS identifier
22
+ * (letters, digits, underscore; can't start with a digit).
23
+ */
24
+ as: string;
25
+ /** Sub-pipeline run for each item. */
26
+ do: V2Step[];
27
+ /** `"sequential"` (default) awaits each iteration; `"parallel"` runs with bounded concurrency. */
28
+ mode?: "sequential" | "parallel";
29
+ /** When `mode: "parallel"`, max concurrent inner pipelines. Default 10. */
30
+ concurrency?: number;
31
+ /** Skip this step at runtime. Default true (active). */
32
+ active?: boolean;
33
+ /** Halt the workflow after this step completes. */
34
+ stop?: boolean;
35
+ }
36
+ /**
37
+ * Create a forEach step — iterate over a collection running a sub-pipeline
38
+ * per item. Sequential by default; pass `mode: "parallel"` with a
39
+ * `concurrency` cap for parallel fan-out.
40
+ *
41
+ * @example
42
+ * forEach({
43
+ * id: "process-items",
44
+ * in: $.req.body.items,
45
+ * as: "item",
46
+ * mode: "parallel",
47
+ * concurrency: 5,
48
+ * do: [
49
+ * { id: "reserve", use: "inventory-reserve", inputs: { sku: $.state.item.sku } },
50
+ * ],
51
+ * })
52
+ */
53
+ export declare function forEach(opts: ForEachOpts): V2ForEachStep;
@@ -0,0 +1,64 @@
1
+ import { unwrapProxies } from "../proxy/$";
2
+ /**
3
+ * Create a forEach step — iterate over a collection running a sub-pipeline
4
+ * per item. Sequential by default; pass `mode: "parallel"` with a
5
+ * `concurrency` cap for parallel fan-out.
6
+ *
7
+ * @example
8
+ * forEach({
9
+ * id: "process-items",
10
+ * in: $.req.body.items,
11
+ * as: "item",
12
+ * mode: "parallel",
13
+ * concurrency: 5,
14
+ * do: [
15
+ * { id: "reserve", use: "inventory-reserve", inputs: { sku: $.state.item.sku } },
16
+ * ],
17
+ * })
18
+ */
19
+ export function forEach(opts) {
20
+ if (!opts || typeof opts !== "object") {
21
+ throw new Error("forEach() requires an options object.");
22
+ }
23
+ if (!opts.id || typeof opts.id !== "string") {
24
+ throw new Error("forEach() requires a non-empty `id` string.");
25
+ }
26
+ if (opts.in === undefined) {
27
+ throw new Error(`forEach("${opts.id}") requires \`in\` (the array source).`);
28
+ }
29
+ if (!opts.as || typeof opts.as !== "string") {
30
+ throw new Error(`forEach("${opts.id}") requires \`as\` (the per-iteration variable name).`);
31
+ }
32
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(opts.as)) {
33
+ throw new Error(`forEach("${opts.id}") \`as\` must be a valid JS identifier (got "${opts.as}").`);
34
+ }
35
+ if (!Array.isArray(opts.do) || opts.do.length === 0) {
36
+ throw new Error(`forEach("${opts.id}") requires \`do\` to be a non-empty array of steps.`);
37
+ }
38
+ if (opts.mode !== undefined && opts.mode !== "sequential" && opts.mode !== "parallel") {
39
+ throw new Error(`forEach("${opts.id}") \`mode\` must be "sequential" or "parallel" when set.`);
40
+ }
41
+ if (opts.concurrency !== undefined) {
42
+ if (typeof opts.concurrency !== "number" || opts.concurrency < 1 || !Number.isInteger(opts.concurrency)) {
43
+ throw new Error(`forEach("${opts.id}") \`concurrency\` must be a positive integer.`);
44
+ }
45
+ }
46
+ const inExpr = unwrapProxies(opts.in);
47
+ const innerSteps = unwrapProxies(opts.do);
48
+ const result = {
49
+ id: opts.id,
50
+ forEach: {
51
+ in: inExpr,
52
+ as: opts.as,
53
+ do: innerSteps,
54
+ ...(opts.mode !== undefined ? { mode: opts.mode } : {}),
55
+ ...(opts.concurrency !== undefined ? { concurrency: opts.concurrency } : {}),
56
+ },
57
+ };
58
+ if (opts.active === false)
59
+ result.active = false;
60
+ if (opts.stop === true)
61
+ result.stop = true;
62
+ return result;
63
+ }
64
+ //# sourceMappingURL=forEach.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forEach.js","sourceRoot":"","sources":["../../src/components/forEach.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { V2LoopStep, V2Step } from "../types/StepOpts";
2
+ /**
3
+ * Author-facing options for {@link loop}.
4
+ *
5
+ * `while` is a JS expression evaluated against `ctx` BEFORE each
6
+ * iteration. Loop continues while truthy. The loop counter is exposed
7
+ * as `ctx.state[<id>Index]` so the condition can reference it
8
+ * (e.g. `$.state.pollIndex < 5`).
9
+ *
10
+ * `maxIterations` is a HARD cap that throws `LoopMaxIterationsError`
11
+ * when exceeded — a safety net against infinite loops. Default 1000.
12
+ */
13
+ export interface LoopOpts {
14
+ /** Stable identifier. The loop counter is exposed as `ctx.state[<id>Index]`. */
15
+ id: string;
16
+ /**
17
+ * JS expression evaluated against ctx before each iteration. Loop
18
+ * continues while truthy.
19
+ */
20
+ while: string | unknown;
21
+ /** Sub-pipeline run each iteration. */
22
+ do: V2Step[];
23
+ /**
24
+ * Hard cap on iterations. Default 1000 (override via env
25
+ * `BLOK_LOOP_MAX_ITERATIONS`). Hitting the cap throws
26
+ * `LoopMaxIterationsError`.
27
+ */
28
+ maxIterations?: number;
29
+ /** Skip this step at runtime. Default true (active). */
30
+ active?: boolean;
31
+ /** Halt the workflow after this step completes. */
32
+ stop?: boolean;
33
+ }
34
+ /**
35
+ * Create a loop step — while-loop with a hard maxIterations safety cap.
36
+ *
37
+ * State mutations made inside the loop body carry forward to the next
38
+ * iteration, so condition variables can advance. The current iteration
39
+ * counter (0-based) is at `ctx.state[<id>Index]`.
40
+ *
41
+ * @example
42
+ * loop({
43
+ * id: "poll-job",
44
+ * while: '$.state["check-status"].status !== "done"',
45
+ * maxIterations: 60,
46
+ * do: [
47
+ * { id: "wait-tick", wait: { for: "2s" } },
48
+ * { id: "check-status", use: "@blokjs/api-call", inputs: { url: "..." } },
49
+ * ],
50
+ * })
51
+ */
52
+ export declare function loop(opts: LoopOpts): V2LoopStep;
@@ -0,0 +1,54 @@
1
+ import { unwrapProxies } from "../proxy/$";
2
+ /**
3
+ * Create a loop step — while-loop with a hard maxIterations safety cap.
4
+ *
5
+ * State mutations made inside the loop body carry forward to the next
6
+ * iteration, so condition variables can advance. The current iteration
7
+ * counter (0-based) is at `ctx.state[<id>Index]`.
8
+ *
9
+ * @example
10
+ * loop({
11
+ * id: "poll-job",
12
+ * while: '$.state["check-status"].status !== "done"',
13
+ * maxIterations: 60,
14
+ * do: [
15
+ * { id: "wait-tick", wait: { for: "2s" } },
16
+ * { id: "check-status", use: "@blokjs/api-call", inputs: { url: "..." } },
17
+ * ],
18
+ * })
19
+ */
20
+ export function loop(opts) {
21
+ if (!opts || typeof opts !== "object") {
22
+ throw new Error("loop() requires an options object.");
23
+ }
24
+ if (!opts.id || typeof opts.id !== "string") {
25
+ throw new Error("loop() requires a non-empty `id` string.");
26
+ }
27
+ const whileExpr = unwrapProxies(opts.while);
28
+ if (typeof whileExpr !== "string" || whileExpr.length === 0) {
29
+ throw new Error(`loop("${opts.id}") requires a non-empty \`while\` expression. Use a $ proxy path or a plain string expression.`);
30
+ }
31
+ if (!Array.isArray(opts.do) || opts.do.length === 0) {
32
+ throw new Error(`loop("${opts.id}") requires \`do\` to be a non-empty array of steps.`);
33
+ }
34
+ if (opts.maxIterations !== undefined) {
35
+ if (typeof opts.maxIterations !== "number" || opts.maxIterations < 1 || !Number.isInteger(opts.maxIterations)) {
36
+ throw new Error(`loop("${opts.id}") \`maxIterations\` must be a positive integer.`);
37
+ }
38
+ }
39
+ const innerSteps = unwrapProxies(opts.do);
40
+ const result = {
41
+ id: opts.id,
42
+ loop: {
43
+ while: whileExpr,
44
+ do: innerSteps,
45
+ ...(opts.maxIterations !== undefined ? { maxIterations: opts.maxIterations } : {}),
46
+ },
47
+ };
48
+ if (opts.active === false)
49
+ result.active = false;
50
+ if (opts.stop === true)
51
+ result.stop = true;
52
+ return result;
53
+ }
54
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/components/loop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAoC3C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,IAAI,CAAC,IAAc;IAClC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5C,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CACd,SAAS,IAAI,CAAC,EAAE,gGAAgG,CAChH,CAAC;IACH,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,EAAE,sDAAsD,CAAC,CAAC;IACzF,CAAC;IACD,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QACtC,IAAI,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ,IAAI,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YAC/G,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,EAAE,kDAAkD,CAAC,CAAC;QACrF,CAAC;IACF,CAAC;IAED,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,EAAE,CAAa,CAAC;IAEtD,MAAM,MAAM,GAAe;QAC1B,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,IAAI,EAAE;YACL,KAAK,EAAE,SAAS;YAChB,EAAE,EAAE,UAAU;YACd,GAAG,CAAC,IAAI,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAClF;KACD,CAAC;IACF,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK;QAAG,MAA2C,CAAC,MAAM,GAAG,KAAK,CAAC;IACvF,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;QAAG,MAAyC,CAAC,IAAI,GAAG,IAAI,CAAC;IAC/E,OAAO,MAAM,CAAC;AACf,CAAC"}
@@ -0,0 +1,68 @@
1
+ import type { V2Step, V2SwitchStep } from "../types/StepOpts";
2
+ /**
3
+ * Author-facing options for {@link switchOn}.
4
+ *
5
+ * `on` accepts either a `$` proxy expression (compiles to a `js/...`
6
+ * string at definition time) or a literal value. Whatever it resolves
7
+ * to at run time is matched against each `case.when`:
8
+ *
9
+ * - `when` is a literal scalar → match if `on === when`
10
+ * - `when` is an array → match if `array.includes(on)` (group related cases)
11
+ *
12
+ * First matching case wins. Subsequent cases are not evaluated. If no
13
+ * case matches and a `default` block is provided, those steps run instead.
14
+ */
15
+ export interface SwitchCase {
16
+ /**
17
+ * Match value. Literal scalar (number/string/boolean) for strict
18
+ * equality, or an array for any-of matching. Resolved by the
19
+ * blueprint mapper before comparison — `$` proxies and `js/...`
20
+ * strings are evaluated against the live ctx.
21
+ */
22
+ when: unknown;
23
+ /** Sub-pipeline run when this case matches. */
24
+ do: V2Step[];
25
+ }
26
+ export interface SwitchOpts {
27
+ /** Stable identifier — visible in traces, referenced as `$.state[id]`. */
28
+ id: string;
29
+ /**
30
+ * Value to match against. `$` proxy expression (`$.req.headers["x-tenant-id"]`),
31
+ * `js/...` string, or any literal. Resolved at run time before matching.
32
+ */
33
+ on: unknown;
34
+ /** Ordered list of cases. First match wins. */
35
+ cases: SwitchCase[];
36
+ /** Fallback sub-pipeline when no case matches. Optional. */
37
+ default?: V2Step[];
38
+ /** Skip this step at runtime. Default true (active). */
39
+ active?: boolean;
40
+ /** Halt the workflow after this step completes. */
41
+ stop?: boolean;
42
+ }
43
+ /**
44
+ * Create a switch step — N-way branch keyed on a value. First matching
45
+ * case wins; an optional `default` block runs when no case matches.
46
+ *
47
+ * Authoring note: the function is named `switchOn` because `switch` is
48
+ * a JavaScript reserved word. The resulting step object's discriminator
49
+ * field is `switch`, matching the JSON shape exactly.
50
+ *
51
+ * @example
52
+ * switchOn({
53
+ * id: "route-by-event",
54
+ * on: $.req.headers["x-github-event"],
55
+ * cases: [
56
+ * { when: "push", do: [{ id: "h", subworkflow: "handle-push" }] },
57
+ * {
58
+ * when: ["pull_request", "pull_request_review"],
59
+ * do: [{ id: "h", subworkflow: "handle-pr-event" }],
60
+ * },
61
+ * ],
62
+ * default: [
63
+ * { id: "log-unknown", use: "@blokjs/log",
64
+ * inputs: { level: "warn", message: "unknown github event" } },
65
+ * ],
66
+ * })
67
+ */
68
+ export declare function switchOn(opts: SwitchOpts): V2SwitchStep;
@@ -0,0 +1,76 @@
1
+ import { unwrapProxies } from "../proxy/$";
2
+ /**
3
+ * Create a switch step — N-way branch keyed on a value. First matching
4
+ * case wins; an optional `default` block runs when no case matches.
5
+ *
6
+ * Authoring note: the function is named `switchOn` because `switch` is
7
+ * a JavaScript reserved word. The resulting step object's discriminator
8
+ * field is `switch`, matching the JSON shape exactly.
9
+ *
10
+ * @example
11
+ * switchOn({
12
+ * id: "route-by-event",
13
+ * on: $.req.headers["x-github-event"],
14
+ * cases: [
15
+ * { when: "push", do: [{ id: "h", subworkflow: "handle-push" }] },
16
+ * {
17
+ * when: ["pull_request", "pull_request_review"],
18
+ * do: [{ id: "h", subworkflow: "handle-pr-event" }],
19
+ * },
20
+ * ],
21
+ * default: [
22
+ * { id: "log-unknown", use: "@blokjs/log",
23
+ * inputs: { level: "warn", message: "unknown github event" } },
24
+ * ],
25
+ * })
26
+ */
27
+ export function switchOn(opts) {
28
+ if (!opts || typeof opts !== "object") {
29
+ throw new Error("switchOn() requires an options object.");
30
+ }
31
+ if (!opts.id || typeof opts.id !== "string") {
32
+ throw new Error("switchOn() requires a non-empty `id` string.");
33
+ }
34
+ if (opts.on === undefined) {
35
+ throw new Error(`switchOn("${opts.id}") requires \`on\` (the value or expression to match against).`);
36
+ }
37
+ if (!Array.isArray(opts.cases) || opts.cases.length === 0) {
38
+ throw new Error(`switchOn("${opts.id}") requires \`cases\` to be a non-empty array.`);
39
+ }
40
+ for (let i = 0; i < opts.cases.length; i++) {
41
+ const c = opts.cases[i];
42
+ if (!c || typeof c !== "object") {
43
+ throw new Error(`switchOn("${opts.id}") cases[${i}] must be an object with \`when\` and \`do\`.`);
44
+ }
45
+ if (c.when === undefined) {
46
+ throw new Error(`switchOn("${opts.id}") cases[${i}] is missing \`when\` (the match value).`);
47
+ }
48
+ if (!Array.isArray(c.do) || c.do.length === 0) {
49
+ throw new Error(`switchOn("${opts.id}") cases[${i}] \`do\` must be a non-empty array of steps.`);
50
+ }
51
+ }
52
+ if (opts.default !== undefined) {
53
+ if (!Array.isArray(opts.default) || opts.default.length === 0) {
54
+ throw new Error(`switchOn("${opts.id}") \`default\` must be a non-empty array of steps when set.`);
55
+ }
56
+ }
57
+ const onExpr = unwrapProxies(opts.on);
58
+ const cases = opts.cases.map((c) => ({
59
+ when: unwrapProxies(c.when),
60
+ do: unwrapProxies(c.do),
61
+ }));
62
+ const result = {
63
+ id: opts.id,
64
+ switch: {
65
+ on: onExpr,
66
+ cases,
67
+ ...(opts.default !== undefined ? { default: unwrapProxies(opts.default) } : {}),
68
+ },
69
+ };
70
+ if (opts.active === false)
71
+ result.active = false;
72
+ if (opts.stop === true)
73
+ result.stop = true;
74
+ return result;
75
+ }
76
+ //# sourceMappingURL=switchOn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"switchOn.js","sourceRoot":"","sources":["../../src/components/switchOn.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import type { V2Step, V2TryCatchStep } from "../types/StepOpts";
2
+ /**
3
+ * Author-facing options for {@link tryCatch}.
4
+ *
5
+ * `try` and `catch` are required and non-empty; `finally` is optional.
6
+ *
7
+ * Inside the `catch` block, `$.error.message`, `$.error.name`, and
8
+ * `$.error.stack` resolve at run time to the captured error info. In
9
+ * `try` and `finally`, `$.error` is undefined (the JS-like contract).
10
+ */
11
+ export interface TryCatchOpts {
12
+ /** Stable identifier — visible in traces, referenced as `$.state[id]`. */
13
+ id: string;
14
+ /** Sub-pipeline run first. If any step throws, control jumps to `catch`. */
15
+ try: V2Step[];
16
+ /**
17
+ * Sub-pipeline run when `try` throws. Has access to `$.error.{message,name,stack}`.
18
+ * Errors thrown inside `catch` propagate — they DO NOT re-trigger catch.
19
+ */
20
+ catch: V2Step[];
21
+ /**
22
+ * Sub-pipeline run unconditionally after try/catch. Runs even if `catch`
23
+ * itself throws. Errors thrown inside `finally` propagate.
24
+ */
25
+ finally?: V2Step[];
26
+ /** Skip this step at runtime. Default true (active). */
27
+ active?: boolean;
28
+ /** Halt the workflow after this step completes. */
29
+ stop?: boolean;
30
+ }
31
+ /**
32
+ * Create a tryCatch step — JS-like exception handling for sub-pipelines.
33
+ *
34
+ * Semantics mirror JavaScript's `try/catch/finally`:
35
+ * - `try` runs first.
36
+ * - On throw, `ctx.error` is set and `catch` runs.
37
+ * - `finally` runs unconditionally (after try success, after caught error,
38
+ * and after an uncaught throw from inside `catch`).
39
+ * - State mutations from any block are visible to subsequent top-level steps.
40
+ *
41
+ * @example
42
+ * tryCatch({
43
+ * id: "signup-saga",
44
+ * try: [
45
+ * { id: "create", use: "user-create", inputs: { email: $.req.body.email } },
46
+ * { id: "notify", use: "email-send", inputs: { to: $.state.create.email } },
47
+ * ],
48
+ * catch: [
49
+ * branch({
50
+ * id: "rollback-if-needed",
51
+ * when: '$.state.create !== undefined',
52
+ * then: [{ id: "del", use: "user-delete", inputs: { userId: $.state.create.id } }],
53
+ * }),
54
+ * { id: "respond-fail", use: "@blokjs/respond",
55
+ * inputs: { status: 500, body: { error: $.error.message } } },
56
+ * ],
57
+ * finally: [
58
+ * { id: "metric", use: "@blokjs/metrics-emit",
59
+ * inputs: { event: "signup-attempt" } },
60
+ * ],
61
+ * })
62
+ */
63
+ export declare function tryCatch(opts: TryCatchOpts): V2TryCatchStep;
@@ -0,0 +1,68 @@
1
+ import { unwrapProxies } from "../proxy/$";
2
+ /**
3
+ * Create a tryCatch step — JS-like exception handling for sub-pipelines.
4
+ *
5
+ * Semantics mirror JavaScript's `try/catch/finally`:
6
+ * - `try` runs first.
7
+ * - On throw, `ctx.error` is set and `catch` runs.
8
+ * - `finally` runs unconditionally (after try success, after caught error,
9
+ * and after an uncaught throw from inside `catch`).
10
+ * - State mutations from any block are visible to subsequent top-level steps.
11
+ *
12
+ * @example
13
+ * tryCatch({
14
+ * id: "signup-saga",
15
+ * try: [
16
+ * { id: "create", use: "user-create", inputs: { email: $.req.body.email } },
17
+ * { id: "notify", use: "email-send", inputs: { to: $.state.create.email } },
18
+ * ],
19
+ * catch: [
20
+ * branch({
21
+ * id: "rollback-if-needed",
22
+ * when: '$.state.create !== undefined',
23
+ * then: [{ id: "del", use: "user-delete", inputs: { userId: $.state.create.id } }],
24
+ * }),
25
+ * { id: "respond-fail", use: "@blokjs/respond",
26
+ * inputs: { status: 500, body: { error: $.error.message } } },
27
+ * ],
28
+ * finally: [
29
+ * { id: "metric", use: "@blokjs/metrics-emit",
30
+ * inputs: { event: "signup-attempt" } },
31
+ * ],
32
+ * })
33
+ */
34
+ export function tryCatch(opts) {
35
+ if (!opts || typeof opts !== "object") {
36
+ throw new Error("tryCatch() requires an options object.");
37
+ }
38
+ if (!opts.id || typeof opts.id !== "string") {
39
+ throw new Error("tryCatch() requires a non-empty `id` string.");
40
+ }
41
+ if (!Array.isArray(opts.try) || opts.try.length === 0) {
42
+ throw new Error(`tryCatch("${opts.id}") requires \`try\` to be a non-empty array of steps.`);
43
+ }
44
+ if (!Array.isArray(opts.catch) || opts.catch.length === 0) {
45
+ throw new Error(`tryCatch("${opts.id}") requires \`catch\` to be a non-empty array of steps.`);
46
+ }
47
+ if (opts.finally !== undefined) {
48
+ if (!Array.isArray(opts.finally) || opts.finally.length === 0) {
49
+ throw new Error(`tryCatch("${opts.id}") \`finally\` must be a non-empty array of steps when set.`);
50
+ }
51
+ }
52
+ const tryBlock = unwrapProxies(opts.try);
53
+ const catchBlock = unwrapProxies(opts.catch);
54
+ const result = {
55
+ id: opts.id,
56
+ tryCatch: {
57
+ try: tryBlock,
58
+ catch: catchBlock,
59
+ ...(opts.finally !== undefined ? { finally: unwrapProxies(opts.finally) } : {}),
60
+ },
61
+ };
62
+ if (opts.active === false)
63
+ result.active = false;
64
+ if (opts.stop === true)
65
+ result.stop = true;
66
+ return result;
67
+ }
68
+ //# sourceMappingURL=tryCatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tryCatch.js","sourceRoot":"","sources":["../../src/components/tryCatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAiC3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAkB;IAC1C,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC,EAAE,uDAAuD,CAAC,CAAC;IAC9F,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC,EAAE,yDAAyD,CAAC,CAAC;IAChG,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/D,MAAM,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC,EAAE,6DAA6D,CAAC,CAAC;QACpG,CAAC;IACF,CAAC;IAED,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAa,CAAC;IACrD,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAa,CAAC;IACzD,MAAM,MAAM,GAAmB;QAC9B,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,QAAQ,EAAE;YACT,GAAG,EAAE,QAAQ;YACb,KAAK,EAAE,UAAU;YACjB,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,OAAO,CAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC3F;KACD,CAAC;IACF,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK;QAAG,MAA+C,CAAC,MAAM,GAAG,KAAK,CAAC;IAC3F,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI;QAAG,MAA6C,CAAC,IAAI,GAAG,IAAI,CAAC;IACnF,OAAO,MAAM,CAAC;AACf,CAAC"}
@@ -52,7 +52,7 @@ export interface WorkflowV2Builder {
52
52
  * - **No chaining.** The full workflow is a single object literal —
53
53
  * exactly what JSON workflows look like.
54
54
  * - **No separate `nodes{}` map.** `inputs` lives on each step.
55
- * - **No `set_var: true`** — every step's output auto-stores in `ctx.state`.
55
+ * - **Default-store** — every step's output auto-stores in `ctx.state`.
56
56
  * Opt out with `ephemeral: true`. Multi-output: `spread: true`. Rename:
57
57
  * `as: "<name>"`.
58
58
  * - **`branch({when, then, else})`** replaces `addCondition + AddIf + AddElse`.
@@ -11,7 +11,7 @@ import { TriggersSchema, validateTriggerConfig } from "../types/TriggerOpts";
11
11
  * - **No chaining.** The full workflow is a single object literal —
12
12
  * exactly what JSON workflows look like.
13
13
  * - **No separate `nodes{}` map.** `inputs` lives on each step.
14
- * - **No `set_var: true`** — every step's output auto-stores in `ctx.state`.
14
+ * - **Default-store** — every step's output auto-stores in `ctx.state`.
15
15
  * Opt out with `ephemeral: true`. Multi-output: `spread: true`. Rename:
16
16
  * `as: "<name>"`.
17
17
  * - **`branch({when, then, else})`** replaces `addCondition + AddIf + AddElse`.