@barnum/barnum 0.0.0-main-18fb14ce → 0.0.0-main-a589e69d

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.
Binary file
Binary file
Binary file
Binary file
Binary file
package/dist/all.d.ts CHANGED
@@ -1,12 +1,42 @@
1
1
  import { type Pipeable, type TypedAction } from "./ast.js";
2
2
  export declare function all(): TypedAction<any, []>;
3
- export declare function all<In, O1>(a1: Pipeable<In, O1>): TypedAction<In, [O1]>;
4
- export declare function all<In, O1, O2>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>): TypedAction<In, [O1, O2]>;
5
- export declare function all<In, O1, O2, O3>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>): TypedAction<In, [O1, O2, O3]>;
6
- export declare function all<In, O1, O2, O3, O4>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>, a4: Pipeable<In, O4>): TypedAction<In, [O1, O2, O3, O4]>;
7
- export declare function all<In, O1, O2, O3, O4, O5>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>, a4: Pipeable<In, O4>, a5: Pipeable<In, O5>): TypedAction<In, [O1, O2, O3, O4, O5]>;
8
- export declare function all<In, O1, O2, O3, O4, O5, O6>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>, a4: Pipeable<In, O4>, a5: Pipeable<In, O5>, a6: Pipeable<In, O6>): TypedAction<In, [O1, O2, O3, O4, O5, O6]>;
9
- export declare function all<In, O1, O2, O3, O4, O5, O6, O7>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>, a4: Pipeable<In, O4>, a5: Pipeable<In, O5>, a6: Pipeable<In, O6>, a7: Pipeable<In, O7>): TypedAction<In, [O1, O2, O3, O4, O5, O6, O7]>;
10
- export declare function all<In, O1, O2, O3, O4, O5, O6, O7, O8>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>, a4: Pipeable<In, O4>, a5: Pipeable<In, O5>, a6: Pipeable<In, O6>, a7: Pipeable<In, O7>, a8: Pipeable<In, O8>): TypedAction<In, [O1, O2, O3, O4, O5, O6, O7, O8]>;
11
- export declare function all<In, O1, O2, O3, O4, O5, O6, O7, O8, O9>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>, a4: Pipeable<In, O4>, a5: Pipeable<In, O5>, a6: Pipeable<In, O6>, a7: Pipeable<In, O7>, a8: Pipeable<In, O8>, a9: Pipeable<In, O9>): TypedAction<In, [O1, O2, O3, O4, O5, O6, O7, O8, O9]>;
12
- export declare function all<In, O1, O2, O3, O4, O5, O6, O7, O8, O9, O10>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>, a4: Pipeable<In, O4>, a5: Pipeable<In, O5>, a6: Pipeable<In, O6>, a7: Pipeable<In, O7>, a8: Pipeable<In, O8>, a9: Pipeable<In, O9>, a10: Pipeable<In, O10>): TypedAction<In, [O1, O2, O3, O4, O5, O6, O7, O8, O9, O10]>;
3
+ export declare function all<TInput, TOut1>(a1: Pipeable<TInput, TOut1>): TypedAction<TInput, [TOut1]>;
4
+ export declare function all<TInput, TOut1, TOut2>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>): TypedAction<TInput, [TOut1, TOut2]>;
5
+ export declare function all<TInput, TOut1, TOut2, TOut3>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>): TypedAction<TInput, [TOut1, TOut2, TOut3]>;
6
+ export declare function all<TInput, TOut1, TOut2, TOut3, TOut4>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>, a4: Pipeable<TInput, TOut4>): TypedAction<TInput, [TOut1, TOut2, TOut3, TOut4]>;
7
+ export declare function all<TInput, TOut1, TOut2, TOut3, TOut4, TOut5>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>, a4: Pipeable<TInput, TOut4>, a5: Pipeable<TInput, TOut5>): TypedAction<TInput, [TOut1, TOut2, TOut3, TOut4, TOut5]>;
8
+ export declare function all<TInput, TOut1, TOut2, TOut3, TOut4, TOut5, TOut6>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>, a4: Pipeable<TInput, TOut4>, a5: Pipeable<TInput, TOut5>, a6: Pipeable<TInput, TOut6>): TypedAction<TInput, [TOut1, TOut2, TOut3, TOut4, TOut5, TOut6]>;
9
+ export declare function all<TInput, TOut1, TOut2, TOut3, TOut4, TOut5, TOut6, TOut7>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>, a4: Pipeable<TInput, TOut4>, a5: Pipeable<TInput, TOut5>, a6: Pipeable<TInput, TOut6>, a7: Pipeable<TInput, TOut7>): TypedAction<TInput, [TOut1, TOut2, TOut3, TOut4, TOut5, TOut6, TOut7]>;
10
+ export declare function all<TInput, TOut1, TOut2, TOut3, TOut4, TOut5, TOut6, TOut7, TOut8>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>, a4: Pipeable<TInput, TOut4>, a5: Pipeable<TInput, TOut5>, a6: Pipeable<TInput, TOut6>, a7: Pipeable<TInput, TOut7>, a8: Pipeable<TInput, TOut8>): TypedAction<TInput, [
11
+ TOut1,
12
+ TOut2,
13
+ TOut3,
14
+ TOut4,
15
+ TOut5,
16
+ TOut6,
17
+ TOut7,
18
+ TOut8
19
+ ]>;
20
+ export declare function all<TInput, TOut1, TOut2, TOut3, TOut4, TOut5, TOut6, TOut7, TOut8, TOut9>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>, a4: Pipeable<TInput, TOut4>, a5: Pipeable<TInput, TOut5>, a6: Pipeable<TInput, TOut6>, a7: Pipeable<TInput, TOut7>, a8: Pipeable<TInput, TOut8>, a9: Pipeable<TInput, TOut9>): TypedAction<TInput, [
21
+ TOut1,
22
+ TOut2,
23
+ TOut3,
24
+ TOut4,
25
+ TOut5,
26
+ TOut6,
27
+ TOut7,
28
+ TOut8,
29
+ TOut9
30
+ ]>;
31
+ export declare function all<TInput, TOut1, TOut2, TOut3, TOut4, TOut5, TOut6, TOut7, TOut8, TOut9, TOut10>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>, a4: Pipeable<TInput, TOut4>, a5: Pipeable<TInput, TOut5>, a6: Pipeable<TInput, TOut6>, a7: Pipeable<TInput, TOut7>, a8: Pipeable<TInput, TOut8>, a9: Pipeable<TInput, TOut9>, a10: Pipeable<TInput, TOut10>): TypedAction<TInput, [
32
+ TOut1,
33
+ TOut2,
34
+ TOut3,
35
+ TOut4,
36
+ TOut5,
37
+ TOut6,
38
+ TOut7,
39
+ TOut8,
40
+ TOut9,
41
+ TOut10
42
+ ]>;
package/dist/ast.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { JSONSchema7 } from "json-schema";
2
+ import { type VarRef, type InferVarRefs } from "./bind.js";
2
3
  export type Action = InvokeAction | ChainAction | ForEachAction | AllAction | BranchAction | ResumeHandleAction | ResumePerformAction | RestartHandleAction | RestartPerformAction;
3
4
  export interface InvokeAction {
4
5
  kind: "Invoke";
@@ -60,22 +61,16 @@ export type BuiltinKind = {
60
61
  kind: "Identity";
61
62
  } | {
62
63
  kind: "Drop";
63
- } | {
64
- kind: "Tag";
65
- value: string;
66
64
  } | {
67
65
  kind: "Merge";
68
66
  } | {
69
67
  kind: "Flatten";
70
68
  } | {
71
69
  kind: "GetField";
72
- value: string;
70
+ field: string;
73
71
  } | {
74
72
  kind: "GetIndex";
75
- value: number;
76
- } | {
77
- kind: "Pick";
78
- value: string[];
73
+ index: number;
79
74
  } | {
80
75
  kind: "CollectSome";
81
76
  } | {
@@ -84,16 +79,20 @@ export type BuiltinKind = {
84
79
  kind: "SplitLast";
85
80
  } | {
86
81
  kind: "WrapInField";
87
- value: string;
82
+ field: string;
88
83
  } | {
89
84
  kind: "Sleep";
90
- value: number;
85
+ ms: number;
86
+ } | {
87
+ kind: "Panic";
88
+ message: string;
91
89
  };
92
90
  /**
93
- * When TIn is `never` (handler ignores input), produce `any` so the
94
- * combinator/pipe can sit in any pipeline position.
91
+ * When T is `never` or `void` (handler ignores input / recur doesn't
92
+ * thread state), produce `any` so the combinator can sit in any
93
+ * pipeline position.
95
94
  */
96
- export type PipeIn<T> = [T] extends [never] ? any : T;
95
+ export type PipeIn<T> = [T] extends [never] ? any : [T] extends [void] ? any : T;
97
96
  export interface Config {
98
97
  workflow: Action;
99
98
  }
@@ -101,96 +100,168 @@ type UnionToIntersection<TUnion> = (TUnion extends any ? (x: TUnion) => void : n
101
100
  /** Merge a tuple of objects into a single intersection type. */
102
101
  export type MergeTuple<TTuple> = TTuple extends unknown[] ? UnionToIntersection<TTuple[number]> : never;
103
102
  /**
104
- * An action with tracked input/output types. Phantom fields enforce invariance
103
+ * Runtime dispatch table for union postfix methods. Each method is optional —
104
+ * Option and Result provide different subsets. TypedAction type signatures
105
+ * gate availability at compile time; this table handles runtime dispatch.
106
+ */
107
+ export interface UnionMethods {
108
+ map?: (action: Action) => Action;
109
+ andThen?: (action: Action) => Action;
110
+ unwrap?: () => Action;
111
+ unwrapOr?: (action: Action) => Action;
112
+ flatten?: () => Action;
113
+ filter?: (predicate: Action) => Action;
114
+ collect?: () => Action;
115
+ isSome?: () => Action;
116
+ isNone?: () => Action;
117
+ mapErr?: (action: Action) => Action;
118
+ and?: (other: Action) => Action;
119
+ or?: (fallback: Action) => Action;
120
+ toOption?: () => Action;
121
+ toOptionErr?: () => Action;
122
+ transpose?: () => Action;
123
+ isOk?: () => Action;
124
+ isErr?: () => Action;
125
+ }
126
+ /**
127
+ * Runtime dispatch info attached to every TypedAction. Non-null when the
128
+ * output is a union type (Option, Result). `name` identifies the type for
129
+ * error messages; `methods` is the dispatch table.
130
+ */
131
+ export interface UnionDispatch {
132
+ name: string;
133
+ methods: UnionMethods;
134
+ }
135
+ /**
136
+ * Attach a union dispatch table to a TypedAction. Used by constructors
137
+ * and family-preserving combinators so postfix methods can dispatch
138
+ * to the correct implementation.
139
+ */
140
+ export declare function withUnion<In, Out>(action: TypedAction<In, Out>, name: string, methods: UnionMethods): TypedAction<In, Out>;
141
+ /**
142
+ * An action with tracked input/output types. Phantom fields enforce variance
105
143
  * and are never set at runtime — they exist only for the TypeScript compiler.
106
144
  *
107
- * Each type variable gets a contravariant + covariant field pair:
108
145
  * In: __in (contravariant) + __in_co (covariant) → invariant
109
- * Out: __out (covariant) + __out_contra (contravariant) → invariant
146
+ * Out: __out (covariant only)
110
147
  *
111
- * This ensures exact type matching at every pipeline connection point.
148
+ * Input invariance ensures exact type matching at pipeline connection points.
112
149
  * Data crosses serialization boundaries to handlers in arbitrary languages
113
150
  * (Rust, Python, etc.), so extra/missing fields are runtime errors.
151
+ *
152
+ * Output covariance is safe — a step producing Dog where Animal is expected
153
+ * downstream works. `never` (throwError, recur, done) is assignable to any
154
+ * output slot via standard subtyping.
114
155
  */
115
- export type TypedAction<In = unknown, Out = unknown, Refs extends string = never> = Action & {
156
+ export type TypedAction<In = unknown, Out = unknown> = Action & {
116
157
  __in?: (input: In) => void;
117
158
  __in_co?: In;
118
159
  __out?: () => Out;
119
- __out_contra?: (output: Out) => void;
120
- __refs?: {
121
- _brand: Refs;
122
- };
160
+ /** Runtime dispatch info for union postfix methods (Option/Result). Null for non-union outputs. */
161
+ __union: UnionDispatch | null;
123
162
  /** Chain this action with another. `a.then(b)` ≡ `chain(a, b)`. */
124
- then<TNext>(next: Pipeable<Out, TNext>): TypedAction<In, TNext, Refs>;
163
+ then<TNext>(next: Pipeable<Out, TNext>): TypedAction<In, TNext>;
125
164
  /** Apply an action to each element of an array output. `a.forEach(b)` ≡ `a.then(forEach(b))`. */
126
- forEach<TIn, TElement, TNext, TRefs extends string>(this: TypedAction<TIn, TElement[], TRefs>, action: Pipeable<TElement, TNext>): TypedAction<TIn, TNext[], TRefs>;
165
+ forEach<TIn, TElement, TNext>(this: TypedAction<TIn, TElement[]>, action: Pipeable<TElement, TNext>): TypedAction<TIn, TNext[]>;
127
166
  /** Dispatch on a tagged union output. Auto-unwraps `value` before each case handler. */
128
167
  branch<TCases extends {
129
168
  [K in BranchKeys<Out>]: CaseHandler<BranchPayload<Out, K>, unknown>;
130
- }>(cases: [BranchKeys<Out>] extends [never] ? never : TCases): TypedAction<In, ExtractOutput<TCases[keyof TCases & string]>, Refs>;
131
- /** Flatten a nested array output. `a.flatten()` `pipe(a, flatten())`. */
132
- flatten(): TypedAction<In, Out extends (infer TElement)[][] ? TElement[] : Out, Refs>;
169
+ }>(cases: [BranchKeys<Out>] extends [never] ? never : TCases): TypedAction<In, ExtractOutput<TCases[keyof TCases & string]>>;
170
+ /** Flatten one level of nesting. Dispatches: Array, Option, Result. */
171
+ flatten<TIn, TElement>(this: TypedAction<TIn, TElement[][]>): TypedAction<TIn, TElement[]>;
172
+ flatten<TIn, TValue>(this: TypedAction<TIn, Option<Option<TValue>>>): TypedAction<TIn, Option<TValue>>;
173
+ flatten<TIn, TValue, TError>(this: TypedAction<TIn, Result<Result<TValue, TError>, TError>>): TypedAction<TIn, Result<TValue, TError>>;
174
+ flatten(): TypedAction<In, unknown>;
133
175
  /** Discard output. `a.drop()` ≡ `pipe(a, drop)`. */
134
- drop(): TypedAction<In, never, Refs>;
176
+ drop(): TypedAction<In, void>;
135
177
  /** Wrap output as a tagged union member. Requires full variant map TDef so __def is carried. */
136
- tag<TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(kind: TKind): TypedAction<In, TaggedUnion<TDef>, Refs>;
178
+ tag<TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(kind: TKind): TypedAction<In, TaggedUnion<TDef>>;
137
179
  /** Extract a field from the output object. `a.getField("name")` ≡ `pipe(a, getField("name"))`. */
138
- getField<TField extends keyof Out & string>(field: TField): TypedAction<In, Out[TField], Refs>;
180
+ getField<TField extends keyof Out & string>(field: TField): TypedAction<In, Out[TField]>;
139
181
  /** Extract an element from the output tuple by index. `a.getIndex(0)` ≡ `pipe(a, getIndex(0))`. */
140
- getIndex<TIn, TTuple extends unknown[], TIndex extends number, TRefs extends string>(this: TypedAction<TIn, TTuple, TRefs>, index: TIndex): TypedAction<TIn, TTuple[TIndex], TRefs>;
182
+ getIndex<TIn, TTuple extends unknown[], TIndex extends number>(this: TypedAction<TIn, TTuple>, index: TIndex): TypedAction<TIn, TTuple[TIndex]>;
141
183
  /** Wrap output in an object under a field name. `a.wrapInField("foo")` ≡ `pipe(a, wrapInField("foo"))`. */
142
- wrapInField<TField extends string>(field: TField): TypedAction<In, Record<TField, Out>, Refs>;
184
+ wrapInField<TField extends string>(field: TField): TypedAction<In, Record<TField, Out>>;
143
185
  /** Merge a tuple of objects into a single object. `a.merge()` ≡ `pipe(a, merge())`. */
144
- merge(): TypedAction<In, MergeTuple<Out>, Refs>;
186
+ merge(): TypedAction<In, MergeTuple<Out>>;
145
187
  /** Select fields from the output. `a.pick("x", "y")` ≡ `pipe(a, pick("x", "y"))`. */
146
- pick<TKeys extends (keyof Out & string)[]>(...keys: TKeys): TypedAction<In, Pick<Out, TKeys[number]>, Refs>;
188
+ pick<TKeys extends (keyof Out & string)[]>(...keys: TKeys): TypedAction<In, Pick<Out, TKeys[number]>>;
147
189
  /** Head/tail decomposition. Only callable when Out is TElement[]. */
148
- splitFirst<TIn, TElement, TRefs extends string>(this: TypedAction<TIn, TElement[], TRefs>): TypedAction<TIn, Option<[TElement, TElement[]]>, TRefs>;
190
+ splitFirst<TIn, TElement>(this: TypedAction<TIn, TElement[]>): TypedAction<TIn, Option<[TElement, TElement[]]>>;
149
191
  /** Init/last decomposition. Only callable when Out is TElement[]. */
150
- splitLast<TIn, TElement, TRefs extends string>(this: TypedAction<TIn, TElement[], TRefs>): TypedAction<TIn, Option<[TElement[], TElement]>, TRefs>;
192
+ splitLast<TIn, TElement>(this: TypedAction<TIn, TElement[]>): TypedAction<TIn, Option<[TElement[], TElement]>>;
151
193
  /**
152
- * Transform the Some value inside an Option output. Only callable when
153
- * Out is Option<T>. Uses `this` parameter constraint to gate availability.
194
+ * Transform the inner value. Dispatches: Option.map, Result.map.
154
195
  */
155
- mapOption<TIn, T, U, TRefs extends string>(this: TypedAction<TIn, Option<T>, TRefs>, action: Pipeable<T, U>): TypedAction<TIn, Option<U>, TRefs>;
196
+ map<TIn, T, U>(this: TypedAction<TIn, Option<T>>, action: Pipeable<T, U>): TypedAction<TIn, Option<U>>;
197
+ map<TIn, TValue, TOut, TError>(this: TypedAction<TIn, Result<TValue, TError>>, action: Pipeable<TValue, TOut>): TypedAction<TIn, Result<TOut, TError>>;
156
198
  /**
157
199
  * Transform the Err value of a Result output.
158
200
  * `Result<TValue, TError> → Result<TValue, TErrorOut>`
159
- *
160
- * Only callable when Out is Result<TValue, TError>.
161
201
  */
162
- mapErr<TIn, TValue, TError, TErrorOut>(this: TypedAction<TIn, Result<TValue, TError>, any>, action: Pipeable<TError, TErrorOut>): TypedAction<TIn, Result<TValue, TErrorOut>, Refs>;
202
+ mapErr<TIn, TValue, TError, TErrorOut>(this: TypedAction<TIn, Result<TValue, TError>>, action: Pipeable<TError, TErrorOut>): TypedAction<TIn, Result<TValue, TErrorOut>>;
163
203
  /**
164
- * Unwrap a Result output. If Ok, pass through the value. If Err, apply
165
- * the default action. Only callable when Out is Result<TValue, TError>.
204
+ * Unwrap or panic. Dispatches: Option.unwrap, Result.unwrap.
166
205
  *
167
- * The `this` constraint provides TValue from context, so throw tokens
168
- * (Out=never) work without explicit type parameters:
169
- * `handler.unwrapOr(throwError)`
206
+ * Option: If Some, pass through value. If None, panic.
207
+ * Result: If Ok, pass through value. If Err, panic.
208
+ */
209
+ unwrap<TIn, TValue>(this: TypedAction<TIn, Option<TValue>>): TypedAction<TIn, TValue>;
210
+ unwrap<TIn, TValue, TError>(this: TypedAction<TIn, Result<TValue, TError>>): TypedAction<TIn, TValue>;
211
+ /**
212
+ * Unwrap a union output. Dispatches: Option.unwrapOr, Result.unwrapOr.
170
213
  *
171
- * Uses CaseHandler for defaultAction (covariant output only) so that
172
- * `TypedAction<TError, never>` is assignable to `CaseHandler<TError, TValue>`.
214
+ * Option: If Some, pass through value. If None, apply default.
215
+ * Result: If Ok, pass through value. If Err, apply default.
173
216
  *
174
- * Refs position uses `any` in the `this` constraint to avoid TS
175
- * falling back to the constraint bound `string` when Refs = never.
176
- * The return type uses the enclosing TypedAction's `Refs` directly.
217
+ * Covariant output makes throw tokens (Out=never) work:
218
+ * `handler.unwrapOr(throwError)`
177
219
  */
178
- unwrapOr<TIn, TValue, TError>(this: TypedAction<TIn, Result<TValue, TError>, any>, defaultAction: CaseHandler<TError, TValue>): TypedAction<TIn, TValue, Refs>;
220
+ unwrapOr<TIn, TValue>(this: TypedAction<TIn, Option<TValue>>, defaultAction: Pipeable<void, TValue>): TypedAction<TIn, TValue>;
221
+ unwrapOr<TIn, TValue, TError>(this: TypedAction<TIn, Result<TValue, TError>>, defaultAction: Pipeable<TError, TValue>): TypedAction<TIn, TValue>;
222
+ /** Monadic bind. Option: `Option<T> → Option<U>`. Result: `Result<T,E> → Result<U,E>`. */
223
+ andThen<TIn, TValue, TOut>(this: TypedAction<TIn, Option<TValue>>, action: Pipeable<TValue, Option<TOut>>): TypedAction<TIn, Option<TOut>>;
224
+ andThen<TIn, TValue, TOut, TError>(this: TypedAction<TIn, Result<TValue, TError>>, action: Pipeable<TValue, Result<TOut, TError>>): TypedAction<TIn, Result<TOut, TError>>;
225
+ /** Conditional keep. If Some, apply predicate. If None, stay None. */
226
+ filter<TIn, TValue>(this: TypedAction<TIn, Option<TValue>>, predicate: Pipeable<TValue, Option<TValue>>): TypedAction<TIn, Option<TValue>>;
227
+ /** Test if the value is Some. `Option<T> → boolean` */
228
+ isSome<TIn, TValue>(this: TypedAction<TIn, Option<TValue>>): TypedAction<TIn, boolean>;
229
+ /** Test if the value is None. `Option<T> → boolean` */
230
+ isNone<TIn, TValue>(this: TypedAction<TIn, Option<TValue>>): TypedAction<TIn, boolean>;
231
+ /** Collect Some values from an array, discarding Nones. `Option<T>[] → T[]` */
232
+ collect<TIn, TValue>(this: TypedAction<TIn, Option<TValue>[]>): TypedAction<TIn, TValue[]>;
233
+ /** Fallback on Err. `Result<T,E> → Result<T,F>` */
234
+ or<TIn, TValue, TError, TErrorOut>(this: TypedAction<TIn, Result<TValue, TError>>, fallback: Pipeable<TError, Result<TValue, TErrorOut>>): TypedAction<TIn, Result<TValue, TErrorOut>>;
235
+ /** Replace Ok value with another Result. `Result<T,E> → Result<U,E>` */
236
+ and<TIn, TValue, TOut, TError>(this: TypedAction<TIn, Result<TValue, TError>>, other: Pipeable<void, Result<TOut, TError>>): TypedAction<TIn, Result<TOut, TError>>;
237
+ /** Convert Ok to Some, Err to None. `Result<T,E> → Option<T>` */
238
+ toOption<TIn, TValue, TError>(this: TypedAction<TIn, Result<TValue, TError>>): TypedAction<TIn, Option<TValue>>;
239
+ /** Convert Err to Some, Ok to None. `Result<T,E> → Option<E>` */
240
+ toOptionErr<TIn, TValue, TError>(this: TypedAction<TIn, Result<TValue, TError>>): TypedAction<TIn, Option<TError>>;
241
+ /** Test if the value is Ok. `Result<T,E> → boolean` */
242
+ isOk<TIn, TValue, TError>(this: TypedAction<TIn, Result<TValue, TError>>): TypedAction<TIn, boolean>;
243
+ /** Test if the value is Err. `Result<T,E> → boolean` */
244
+ isErr<TIn, TValue, TError>(this: TypedAction<TIn, Result<TValue, TError>>): TypedAction<TIn, boolean>;
245
+ /** Swap nesting. `Option<Result<T,E>> → Result<Option<T>,E>` or `Result<Option<T>,E> → Option<Result<T,E>>`. */
246
+ transpose<TIn, TValue, TError>(this: TypedAction<TIn, Option<Result<TValue, TError>>>): TypedAction<TIn, Result<Option<TValue>, TError>>;
247
+ transpose<TIn, TValue, TError>(this: TypedAction<TIn, Result<Option<TValue>, TError>>): TypedAction<TIn, Option<Result<TValue, TError>>>;
248
+ /** Bind concurrent values as VarRefs available throughout the body. */
249
+ bind<TBindings extends Action[], TOut>(bindings: [...TBindings], body: (vars: InferVarRefs<TBindings>) => Action & {
250
+ __out?: () => TOut;
251
+ }): TypedAction<In, TOut>;
252
+ /** Capture the pipeline input as a VarRef. */
253
+ bindInput<TOut>(body: (input: VarRef<Out>) => Action & {
254
+ __out?: () => TOut;
255
+ }): TypedAction<In, TOut>;
179
256
  };
180
257
  /**
181
- * Parameter type for pipe and combinators. Contains the same phantom fields
182
- * as TypedAction but without methods.
183
- *
184
- * Invariance: Both In and Out are invariant, matching TypedAction:
185
- * In: __in (contravariant) + __in_co (covariant) → invariant
186
- * Out: __out (covariant) + __out_contra (contravariant) → invariant
258
+ * Parameter type for pipe and combinators. Same phantom fields as TypedAction
259
+ * but without methods.
187
260
  *
188
261
  * Why no methods: TypedAction's methods (then, branch, etc.) participate in
189
262
  * TS assignability checks in complex, recursive ways that interfere with
190
263
  * generic inference in pipe overloads. Pipeable strips methods so that only
191
- * phantom fields drive inference — predictable covariant/contravariant
192
- * resolution, with invariance enforced when TS checks candidates from
193
- * both sides of a connection.
264
+ * phantom fields drive inference.
194
265
  *
195
266
  * TypedAction (with methods) is assignable to Pipeable because Pipeable
196
267
  * only requires a subset of properties.
@@ -199,24 +270,18 @@ export type Pipeable<In = unknown, Out = unknown> = Action & {
199
270
  __in?: (input: In) => void;
200
271
  __in_co?: In;
201
272
  __out?: () => Out;
202
- __out_contra?: (output: Out) => void;
203
273
  };
204
274
  /**
205
- * Contravariant-only input checking for branch case handler positions.
275
+ * Contravariant input + covariant output for branch case handler positions.
206
276
  *
207
- * Omits __in_co (covariant input) and __out_contra (contravariant output)
208
- * compared to TypedAction/Pipeable. This gives:
277
+ * Omits __in_co (covariant input) compared to Pipeable. This gives:
209
278
  * In: contravariant only (via __in)
210
279
  * Out: covariant only (via __out)
211
280
  *
212
281
  * Why contravariant input: a handler that accepts `unknown` (like drop)
213
282
  * can handle any variant. (input: unknown) => void is assignable to
214
283
  * (input: HasErrors) => void because HasErrors extends unknown.
215
- *
216
- * Why covariant output: the constraint doesn't restrict output types —
217
- * they're inferred from the actual case handlers via ExtractOutput.
218
- * TypedAction's invariant __out_contra with Out=unknown would
219
- * reject any handler with a specific output type, so we omit it.
284
+ * Pipeable's invariant input (__in_co) would reject this.
220
285
  *
221
286
  * TypedAction is assignable to CaseHandler because CaseHandler only
222
287
  * requires a subset of TypedAction's phantom fields.
@@ -231,6 +296,11 @@ type CaseHandler<TIn = unknown, TOut = unknown> = Action & {
231
296
  * field enables `.branch()` to decompose the union via simple indexing
232
297
  * (`keyof ExtractDef<Out>` and `ExtractDef<Out>[K]`) instead of
233
298
  * conditional types (`KindOf<Out>` and `Extract<Out, { kind: K }>`).
299
+ *
300
+ * **Void → null mapping:** Variants with `void` payload (e.g. `{ None: void }`)
301
+ * become `{ kind: "None"; value: null }` at runtime. This is handled by
302
+ * `VoidToNull` below — `void` has no runtime representation in JSON, so it
303
+ * serializes as `null`. Use `z.null()` in Zod schemas for void variants.
234
304
  */
235
305
  type VoidToNull<T> = 0 extends 1 & T ? T : [T] extends [never] ? never : [T] extends [void] ? null : T;
236
306
  export type TaggedUnion<TDef extends Record<string, unknown>> = {
@@ -279,12 +349,12 @@ type BranchPayload<Out, K extends string> = [ExtractDef<Out>] extends [never] ?
279
349
  * Attach `.then()` and `.forEach()` methods to a plain Action object.
280
350
  * Methods are non-enumerable: invisible to JSON.stringify and toEqual.
281
351
  */
282
- export declare function typedAction<In = unknown, Out = unknown, Refs extends string = never>(action: Action): TypedAction<In, Out, Refs>;
352
+ export declare function typedAction<In = unknown, Out = unknown>(action: Action): TypedAction<In, Out>;
283
353
  /**
284
354
  * Extract the input type from a TypedAction.
285
355
  *
286
356
  * Uses direct phantom field extraction (not full TypedAction matching) to
287
- * avoid the `TypedAction<any, any, any>` constraint which fails for In=never
357
+ * avoid a full `TypedAction<any, any>` constraint which fails for In=never
288
358
  * due to __in contravariance.
289
359
  */
290
360
  export type ExtractInput<T> = T extends {
@@ -332,8 +402,6 @@ type LoopResultDef<TContinue, TBreak> = {
332
402
  Break: TBreak;
333
403
  };
334
404
  export type LoopResult<TContinue, TBreak> = TaggedUnion<LoopResultDef<TContinue, TBreak>>;
335
- export declare const TAG_BREAK: Action;
336
- export declare const IDENTITY: Action;
337
405
  /**
338
406
  * Restartable scope. The body callback receives `restart`, a TypedAction that
339
407
  * re-executes the body from the beginning with a new input value.
@@ -343,7 +411,7 @@ export declare const IDENTITY: Action;
343
411
  *
344
412
  * Compiled form: `RestartHandle(id, GetIndex(0), body)`
345
413
  */
346
- export declare function recur<TIn = never, TOut = any>(bodyFn: (restart: TypedAction<TIn, never>) => Pipeable<TIn, TOut>): TypedAction<PipeIn<TIn>, TOut>;
414
+ export declare function recur<TIn = void, TOut = any>(bodyFn: (restart: TypedAction<TIn, never>) => Pipeable<TIn, TOut>): TypedAction<PipeIn<TIn>, TOut>;
347
415
  /**
348
416
  * Early return scope. The body callback receives `earlyReturn`, a TypedAction
349
417
  * that exits the scope immediately with the returned value.
@@ -356,7 +424,7 @@ export declare function recur<TIn = never, TOut = any>(bodyFn: (restart: TypedAc
356
424
  * a Branch. earlyReturn tags with Break and performs — the handler restarts
357
425
  * the body, Branch takes the Break path, and the value exits.
358
426
  */
359
- export declare function earlyReturn<TEarlyReturn = never, TIn = any, TOut = any>(bodyFn: (earlyReturn: TypedAction<TEarlyReturn, never>) => Pipeable<TIn, TOut>): TypedAction<TIn, TEarlyReturn | TOut>;
427
+ export declare function earlyReturn<TEarlyReturn = void, TIn = any, TOut = any>(bodyFn: (earlyReturn: TypedAction<TEarlyReturn, never>) => Pipeable<TIn, TOut>): TypedAction<TIn, TEarlyReturn | TOut>;
360
428
  /**
361
429
  * Build the restart+branch compiled form:
362
430
  * `Chain(Tag("Continue"), RestartHandle(id, GetIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
@@ -376,6 +444,6 @@ export declare function buildRestartBranchAction(restartHandlerId: RestartHandle
376
444
  *
377
445
  * Compiles to `RestartHandle`/`RestartPerform`/Branch — same effect substrate as tryCatch and earlyReturn.
378
446
  */
379
- export declare function loop<TBreak = never, TIn = never>(bodyFn: (recur: TypedAction<TIn, never>, done: TypedAction<VoidToNull<TBreak>, never>) => Pipeable<TIn, never>): TypedAction<PipeIn<TIn>, VoidToNull<TBreak>>;
447
+ export declare function loop<TBreak = void, TRecur = void>(bodyFn: (recur: TypedAction<TRecur, never>, done: TypedAction<VoidToNull<TBreak>, never>) => Pipeable<TRecur, never>): TypedAction<PipeIn<TRecur>, VoidToNull<TBreak>>;
380
448
  /** Simple config factory. */
381
449
  export declare function config(workflow: Action): Config;