@barnum/barnum 0.0.0-main-54c41bbb → 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.
- package/artifacts/linux-arm64/barnum +0 -0
- package/artifacts/linux-x64/barnum +0 -0
- package/artifacts/macos-arm64/barnum +0 -0
- package/artifacts/macos-x64/barnum +0 -0
- package/artifacts/win-x64/barnum.exe +0 -0
- package/dist/ast.d.ts +123 -45
- package/dist/ast.js +120 -6
- package/dist/bind.d.ts +6 -10
- package/dist/builtins.d.ts +9 -135
- package/dist/builtins.js +22 -278
- package/dist/chain.js +8 -1
- package/dist/handler.d.ts +6 -6
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/option.d.ts +101 -0
- package/dist/option.js +194 -0
- package/dist/race.d.ts +1 -1
- package/dist/recursive.d.ts +2 -3
- package/dist/result.d.ts +77 -0
- package/dist/result.js +177 -0
- package/package.json +1 -1
- package/src/ast.ts +352 -63
- package/src/bind.ts +6 -10
- package/src/builtins.ts +37 -374
- package/src/chain.ts +8 -1
- package/src/handler.ts +7 -7
- package/src/index.ts +3 -5
- package/src/option.ts +272 -0
- package/src/race.ts +2 -2
- package/src/recursive.ts +2 -3
- package/src/result.ts +270 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
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";
|
|
@@ -82,12 +83,16 @@ export type BuiltinKind = {
|
|
|
82
83
|
} | {
|
|
83
84
|
kind: "Sleep";
|
|
84
85
|
ms: number;
|
|
86
|
+
} | {
|
|
87
|
+
kind: "Panic";
|
|
88
|
+
message: string;
|
|
85
89
|
};
|
|
86
90
|
/**
|
|
87
|
-
* When
|
|
88
|
-
* combinator
|
|
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.
|
|
89
94
|
*/
|
|
90
|
-
export type PipeIn<T> = [T] extends [never] ? any : T;
|
|
95
|
+
export type PipeIn<T> = [T] extends [never] ? any : [T] extends [void] ? any : T;
|
|
91
96
|
export interface Config {
|
|
92
97
|
workflow: Action;
|
|
93
98
|
}
|
|
@@ -95,22 +100,65 @@ type UnionToIntersection<TUnion> = (TUnion extends any ? (x: TUnion) => void : n
|
|
|
95
100
|
/** Merge a tuple of objects into a single intersection type. */
|
|
96
101
|
export type MergeTuple<TTuple> = TTuple extends unknown[] ? UnionToIntersection<TTuple[number]> : never;
|
|
97
102
|
/**
|
|
98
|
-
*
|
|
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
|
|
99
143
|
* and are never set at runtime — they exist only for the TypeScript compiler.
|
|
100
144
|
*
|
|
101
|
-
* Each type variable gets a contravariant + covariant field pair:
|
|
102
145
|
* In: __in (contravariant) + __in_co (covariant) → invariant
|
|
103
|
-
* Out: __out (covariant
|
|
146
|
+
* Out: __out (covariant only)
|
|
104
147
|
*
|
|
105
|
-
*
|
|
148
|
+
* Input invariance ensures exact type matching at pipeline connection points.
|
|
106
149
|
* Data crosses serialization boundaries to handlers in arbitrary languages
|
|
107
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.
|
|
108
155
|
*/
|
|
109
156
|
export type TypedAction<In = unknown, Out = unknown> = Action & {
|
|
110
157
|
__in?: (input: In) => void;
|
|
111
158
|
__in_co?: In;
|
|
112
159
|
__out?: () => Out;
|
|
113
|
-
|
|
160
|
+
/** Runtime dispatch info for union postfix methods (Option/Result). Null for non-union outputs. */
|
|
161
|
+
__union: UnionDispatch | null;
|
|
114
162
|
/** Chain this action with another. `a.then(b)` ≡ `chain(a, b)`. */
|
|
115
163
|
then<TNext>(next: Pipeable<Out, TNext>): TypedAction<In, TNext>;
|
|
116
164
|
/** Apply an action to each element of an array output. `a.forEach(b)` ≡ `a.then(forEach(b))`. */
|
|
@@ -119,10 +167,13 @@ export type TypedAction<In = unknown, Out = unknown> = Action & {
|
|
|
119
167
|
branch<TCases extends {
|
|
120
168
|
[K in BranchKeys<Out>]: CaseHandler<BranchPayload<Out, K>, unknown>;
|
|
121
169
|
}>(cases: [BranchKeys<Out>] extends [never] ? never : TCases): TypedAction<In, ExtractOutput<TCases[keyof TCases & string]>>;
|
|
122
|
-
/** Flatten
|
|
123
|
-
flatten(
|
|
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>;
|
|
124
175
|
/** Discard output. `a.drop()` ≡ `pipe(a, drop)`. */
|
|
125
|
-
drop(): TypedAction<In,
|
|
176
|
+
drop(): TypedAction<In, void>;
|
|
126
177
|
/** Wrap output as a tagged union member. Requires full variant map TDef so __def is carried. */
|
|
127
178
|
tag<TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(kind: TKind): TypedAction<In, TaggedUnion<TDef>>;
|
|
128
179
|
/** Extract a field from the output object. `a.getField("name")` ≡ `pipe(a, getField("name"))`. */
|
|
@@ -140,44 +191,77 @@ export type TypedAction<In = unknown, Out = unknown> = Action & {
|
|
|
140
191
|
/** Init/last decomposition. Only callable when Out is TElement[]. */
|
|
141
192
|
splitLast<TIn, TElement>(this: TypedAction<TIn, TElement[]>): TypedAction<TIn, Option<[TElement[], TElement]>>;
|
|
142
193
|
/**
|
|
143
|
-
* Transform the
|
|
144
|
-
* Out is Option<T>. Uses `this` parameter constraint to gate availability.
|
|
194
|
+
* Transform the inner value. Dispatches: Option.map, Result.map.
|
|
145
195
|
*/
|
|
146
|
-
|
|
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>>;
|
|
147
198
|
/**
|
|
148
199
|
* Transform the Err value of a Result output.
|
|
149
200
|
* `Result<TValue, TError> → Result<TValue, TErrorOut>`
|
|
150
|
-
*
|
|
151
|
-
* Only callable when Out is Result<TValue, TError>.
|
|
152
201
|
*/
|
|
153
202
|
mapErr<TIn, TValue, TError, TErrorOut>(this: TypedAction<TIn, Result<TValue, TError>>, action: Pipeable<TError, TErrorOut>): TypedAction<TIn, Result<TValue, TErrorOut>>;
|
|
154
203
|
/**
|
|
155
|
-
* Unwrap
|
|
156
|
-
* the default action. Only callable when Out is Result<TValue, TError>.
|
|
204
|
+
* Unwrap or panic. Dispatches: Option.unwrap, Result.unwrap.
|
|
157
205
|
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
|
|
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.
|
|
213
|
+
*
|
|
214
|
+
* Option: If Some, pass through value. If None, apply default.
|
|
215
|
+
* Result: If Ok, pass through value. If Err, apply default.
|
|
161
216
|
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
217
|
+
* Covariant output makes throw tokens (Out=never) work:
|
|
218
|
+
* `handler.unwrapOr(throwError)`
|
|
164
219
|
*/
|
|
165
|
-
unwrapOr<TIn, TValue
|
|
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>;
|
|
166
256
|
};
|
|
167
257
|
/**
|
|
168
|
-
* Parameter type for pipe and combinators.
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
* Invariance: Both In and Out are invariant, matching TypedAction:
|
|
172
|
-
* In: __in (contravariant) + __in_co (covariant) → invariant
|
|
173
|
-
* Out: __out (covariant) + __out_contra (contravariant) → invariant
|
|
258
|
+
* Parameter type for pipe and combinators. Same phantom fields as TypedAction
|
|
259
|
+
* but without methods.
|
|
174
260
|
*
|
|
175
261
|
* Why no methods: TypedAction's methods (then, branch, etc.) participate in
|
|
176
262
|
* TS assignability checks in complex, recursive ways that interfere with
|
|
177
263
|
* generic inference in pipe overloads. Pipeable strips methods so that only
|
|
178
|
-
* phantom fields drive inference
|
|
179
|
-
* resolution, with invariance enforced when TS checks candidates from
|
|
180
|
-
* both sides of a connection.
|
|
264
|
+
* phantom fields drive inference.
|
|
181
265
|
*
|
|
182
266
|
* TypedAction (with methods) is assignable to Pipeable because Pipeable
|
|
183
267
|
* only requires a subset of properties.
|
|
@@ -186,24 +270,18 @@ export type Pipeable<In = unknown, Out = unknown> = Action & {
|
|
|
186
270
|
__in?: (input: In) => void;
|
|
187
271
|
__in_co?: In;
|
|
188
272
|
__out?: () => Out;
|
|
189
|
-
__out_contra?: (output: Out) => void;
|
|
190
273
|
};
|
|
191
274
|
/**
|
|
192
|
-
* Contravariant
|
|
275
|
+
* Contravariant input + covariant output for branch case handler positions.
|
|
193
276
|
*
|
|
194
|
-
* Omits __in_co (covariant input)
|
|
195
|
-
* compared to TypedAction/Pipeable. This gives:
|
|
277
|
+
* Omits __in_co (covariant input) compared to Pipeable. This gives:
|
|
196
278
|
* In: contravariant only (via __in)
|
|
197
279
|
* Out: covariant only (via __out)
|
|
198
280
|
*
|
|
199
281
|
* Why contravariant input: a handler that accepts `unknown` (like drop)
|
|
200
282
|
* can handle any variant. (input: unknown) => void is assignable to
|
|
201
283
|
* (input: HasErrors) => void because HasErrors extends unknown.
|
|
202
|
-
*
|
|
203
|
-
* Why covariant output: the constraint doesn't restrict output types —
|
|
204
|
-
* they're inferred from the actual case handlers via ExtractOutput.
|
|
205
|
-
* TypedAction's invariant __out_contra with Out=unknown would
|
|
206
|
-
* reject any handler with a specific output type, so we omit it.
|
|
284
|
+
* Pipeable's invariant input (__in_co) would reject this.
|
|
207
285
|
*
|
|
208
286
|
* TypedAction is assignable to CaseHandler because CaseHandler only
|
|
209
287
|
* requires a subset of TypedAction's phantom fields.
|
|
@@ -333,7 +411,7 @@ export type LoopResult<TContinue, TBreak> = TaggedUnion<LoopResultDef<TContinue,
|
|
|
333
411
|
*
|
|
334
412
|
* Compiled form: `RestartHandle(id, GetIndex(0), body)`
|
|
335
413
|
*/
|
|
336
|
-
export declare function recur<TIn =
|
|
414
|
+
export declare function recur<TIn = void, TOut = any>(bodyFn: (restart: TypedAction<TIn, never>) => Pipeable<TIn, TOut>): TypedAction<PipeIn<TIn>, TOut>;
|
|
337
415
|
/**
|
|
338
416
|
* Early return scope. The body callback receives `earlyReturn`, a TypedAction
|
|
339
417
|
* that exits the scope immediately with the returned value.
|
|
@@ -346,7 +424,7 @@ export declare function recur<TIn = never, TOut = any>(bodyFn: (restart: TypedAc
|
|
|
346
424
|
* a Branch. earlyReturn tags with Break and performs — the handler restarts
|
|
347
425
|
* the body, Branch takes the Break path, and the value exits.
|
|
348
426
|
*/
|
|
349
|
-
export declare function earlyReturn<TEarlyReturn =
|
|
427
|
+
export declare function earlyReturn<TEarlyReturn = void, TIn = any, TOut = any>(bodyFn: (earlyReturn: TypedAction<TEarlyReturn, never>) => Pipeable<TIn, TOut>): TypedAction<TIn, TEarlyReturn | TOut>;
|
|
350
428
|
/**
|
|
351
429
|
* Build the restart+branch compiled form:
|
|
352
430
|
* `Chain(Tag("Continue"), RestartHandle(id, GetIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
|
|
@@ -366,6 +444,6 @@ export declare function buildRestartBranchAction(restartHandlerId: RestartHandle
|
|
|
366
444
|
*
|
|
367
445
|
* Compiles to `RestartHandle`/`RestartPerform`/Branch — same effect substrate as tryCatch and earlyReturn.
|
|
368
446
|
*/
|
|
369
|
-
export declare function loop<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>>;
|
|
370
448
|
/** Simple config factory. */
|
|
371
449
|
export declare function config(workflow: Action): Config;
|
package/dist/ast.js
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import { chain } from "./chain.js";
|
|
2
|
-
import { drop, flatten as flattenBuiltin, getField, getIndex, identity, merge,
|
|
2
|
+
import { drop, flatten as flattenBuiltin, getField, getIndex, identity, merge, pick, splitFirst, splitLast, tag, wrapInField, } from "./builtins.js";
|
|
3
|
+
import { Option } from "./option.js";
|
|
4
|
+
// Lazy import — bind.ts imports from ast.ts, but these are only called inside
|
|
5
|
+
// methods (after all modules load), so the circular reference is safe at runtime.
|
|
6
|
+
import { bind as bindStandalone, bindInput as bindInputStandalone, } from "./bind.js";
|
|
7
|
+
/**
|
|
8
|
+
* Attach a union dispatch table to a TypedAction. Used by constructors
|
|
9
|
+
* and family-preserving combinators so postfix methods can dispatch
|
|
10
|
+
* to the correct implementation.
|
|
11
|
+
*/
|
|
12
|
+
export function withUnion(action, name, methods) {
|
|
13
|
+
Object.defineProperty(action, "__union", {
|
|
14
|
+
value: { name, methods },
|
|
15
|
+
configurable: true,
|
|
16
|
+
enumerable: false,
|
|
17
|
+
writable: true,
|
|
18
|
+
});
|
|
19
|
+
return action;
|
|
20
|
+
}
|
|
3
21
|
// ---------------------------------------------------------------------------
|
|
4
22
|
// typedAction — attach .then() and .forEach() as non-enumerable methods
|
|
5
23
|
// ---------------------------------------------------------------------------
|
|
@@ -14,6 +32,11 @@ function branchMethod(cases) {
|
|
|
14
32
|
return chain(this, branch(cases));
|
|
15
33
|
}
|
|
16
34
|
function flattenMethod() {
|
|
35
|
+
const dispatch = this.__union;
|
|
36
|
+
if (dispatch?.methods.flatten) {
|
|
37
|
+
return chain(this, dispatch.methods.flatten());
|
|
38
|
+
}
|
|
39
|
+
// Fall back to array flatten
|
|
17
40
|
return chain(this, flattenBuiltin());
|
|
18
41
|
}
|
|
19
42
|
function dropMethod() {
|
|
@@ -43,14 +66,89 @@ function splitFirstMethod() {
|
|
|
43
66
|
function splitLastMethod() {
|
|
44
67
|
return chain(this, splitLast());
|
|
45
68
|
}
|
|
46
|
-
|
|
47
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Require a dispatch method, throwing a descriptive error if missing.
|
|
71
|
+
* Uses the union's type name for context.
|
|
72
|
+
*/
|
|
73
|
+
function requireDispatch(dispatch, methodName, accessor) {
|
|
74
|
+
if (!dispatch) {
|
|
75
|
+
throw new Error(`.${methodName}() requires a union type (Option or Result)`);
|
|
76
|
+
}
|
|
77
|
+
const method = accessor(dispatch.methods);
|
|
78
|
+
if (!method) {
|
|
79
|
+
throw new Error(`.${methodName}() is not available on ${dispatch.name}`);
|
|
80
|
+
}
|
|
81
|
+
return method;
|
|
82
|
+
}
|
|
83
|
+
function mapMethod(action) {
|
|
84
|
+
const map = requireDispatch(this.__union, "map", (m) => m.map);
|
|
85
|
+
return chain(this, map(action));
|
|
48
86
|
}
|
|
49
87
|
function mapErrMethod(action) {
|
|
50
|
-
|
|
88
|
+
const mapErr = requireDispatch(this.__union, "mapErr", (m) => m.mapErr);
|
|
89
|
+
return chain(this, mapErr(action));
|
|
90
|
+
}
|
|
91
|
+
function unwrapMethod() {
|
|
92
|
+
const unwrap = requireDispatch(this.__union, "unwrap", (m) => m.unwrap);
|
|
93
|
+
return chain(this, unwrap());
|
|
51
94
|
}
|
|
52
95
|
function unwrapOrMethod(defaultAction) {
|
|
53
|
-
|
|
96
|
+
const unwrapOr = requireDispatch(this.__union, "unwrapOr", (m) => m.unwrapOr);
|
|
97
|
+
return chain(this, unwrapOr(defaultAction));
|
|
98
|
+
}
|
|
99
|
+
// --- Dispatched postfix methods (via __union) ---
|
|
100
|
+
function andThenMethod(action) {
|
|
101
|
+
const andThen = requireDispatch(this.__union, "andThen", (m) => m.andThen);
|
|
102
|
+
return chain(this, andThen(action));
|
|
103
|
+
}
|
|
104
|
+
function filterMethod(predicate) {
|
|
105
|
+
const filter = requireDispatch(this.__union, "filter", (m) => m.filter);
|
|
106
|
+
return chain(this, filter(predicate));
|
|
107
|
+
}
|
|
108
|
+
function isSomeMethod() {
|
|
109
|
+
const isSome = requireDispatch(this.__union, "isSome", (m) => m.isSome);
|
|
110
|
+
return chain(this, isSome());
|
|
111
|
+
}
|
|
112
|
+
function isNoneMethod() {
|
|
113
|
+
const isNone = requireDispatch(this.__union, "isNone", (m) => m.isNone);
|
|
114
|
+
return chain(this, isNone());
|
|
115
|
+
}
|
|
116
|
+
function collectMethod() {
|
|
117
|
+
return chain(this, Option.collect());
|
|
118
|
+
}
|
|
119
|
+
function orMethod(fallback) {
|
|
120
|
+
const or = requireDispatch(this.__union, "or", (m) => m.or);
|
|
121
|
+
return chain(this, or(fallback));
|
|
122
|
+
}
|
|
123
|
+
function andPostfixMethod(other) {
|
|
124
|
+
const and = requireDispatch(this.__union, "and", (m) => m.and);
|
|
125
|
+
return chain(this, and(other));
|
|
126
|
+
}
|
|
127
|
+
function toOptionMethod() {
|
|
128
|
+
const toOption = requireDispatch(this.__union, "toOption", (m) => m.toOption);
|
|
129
|
+
return chain(this, toOption());
|
|
130
|
+
}
|
|
131
|
+
function toOptionErrMethod() {
|
|
132
|
+
const toOptionErr = requireDispatch(this.__union, "toOptionErr", (m) => m.toOptionErr);
|
|
133
|
+
return chain(this, toOptionErr());
|
|
134
|
+
}
|
|
135
|
+
function isOkMethod() {
|
|
136
|
+
const isOk = requireDispatch(this.__union, "isOk", (m) => m.isOk);
|
|
137
|
+
return chain(this, isOk());
|
|
138
|
+
}
|
|
139
|
+
function isErrMethod() {
|
|
140
|
+
const isErr = requireDispatch(this.__union, "isErr", (m) => m.isErr);
|
|
141
|
+
return chain(this, isErr());
|
|
142
|
+
}
|
|
143
|
+
function transposeMethod() {
|
|
144
|
+
const transpose = requireDispatch(this.__union, "transpose", (m) => m.transpose);
|
|
145
|
+
return chain(this, transpose());
|
|
146
|
+
}
|
|
147
|
+
function bindMethod(bindings, body) {
|
|
148
|
+
return chain(this, bindStandalone(bindings, body));
|
|
149
|
+
}
|
|
150
|
+
function bindInputMethod(body) {
|
|
151
|
+
return chain(this, bindInputStandalone(body));
|
|
54
152
|
}
|
|
55
153
|
/**
|
|
56
154
|
* Attach `.then()` and `.forEach()` methods to a plain Action object.
|
|
@@ -59,6 +157,7 @@ function unwrapOrMethod(defaultAction) {
|
|
|
59
157
|
export function typedAction(action) {
|
|
60
158
|
if (!("then" in action)) {
|
|
61
159
|
Object.defineProperties(action, {
|
|
160
|
+
__union: { value: null, configurable: true, enumerable: false, writable: true },
|
|
62
161
|
then: { value: thenMethod, configurable: true },
|
|
63
162
|
forEach: { value: forEachMethod, configurable: true },
|
|
64
163
|
branch: { value: branchMethod, configurable: true },
|
|
@@ -72,9 +171,24 @@ export function typedAction(action) {
|
|
|
72
171
|
pick: { value: pickMethod, configurable: true },
|
|
73
172
|
splitFirst: { value: splitFirstMethod, configurable: true },
|
|
74
173
|
splitLast: { value: splitLastMethod, configurable: true },
|
|
75
|
-
|
|
174
|
+
map: { value: mapMethod, configurable: true },
|
|
76
175
|
mapErr: { value: mapErrMethod, configurable: true },
|
|
176
|
+
unwrap: { value: unwrapMethod, configurable: true },
|
|
77
177
|
unwrapOr: { value: unwrapOrMethod, configurable: true },
|
|
178
|
+
andThen: { value: andThenMethod, configurable: true },
|
|
179
|
+
filter: { value: filterMethod, configurable: true },
|
|
180
|
+
isSome: { value: isSomeMethod, configurable: true },
|
|
181
|
+
isNone: { value: isNoneMethod, configurable: true },
|
|
182
|
+
collect: { value: collectMethod, configurable: true },
|
|
183
|
+
or: { value: orMethod, configurable: true },
|
|
184
|
+
and: { value: andPostfixMethod, configurable: true },
|
|
185
|
+
toOption: { value: toOptionMethod, configurable: true },
|
|
186
|
+
toOptionErr: { value: toOptionErrMethod, configurable: true },
|
|
187
|
+
isOk: { value: isOkMethod, configurable: true },
|
|
188
|
+
isErr: { value: isErrMethod, configurable: true },
|
|
189
|
+
transpose: { value: transposeMethod, configurable: true },
|
|
190
|
+
bind: { value: bindMethod, configurable: true },
|
|
191
|
+
bindInput: { value: bindInputMethod, configurable: true },
|
|
78
192
|
});
|
|
79
193
|
}
|
|
80
194
|
return action;
|
package/dist/bind.d.ts
CHANGED
|
@@ -6,17 +6,14 @@ import { type Action, type ExtractInput, type ExtractOutput, type TypedAction }
|
|
|
6
6
|
* action like `pick` or `getField` — pipe overloads can't infer
|
|
7
7
|
* the generic's type parameter from the VarRef's output.
|
|
8
8
|
*/
|
|
9
|
-
export type VarRef<TValue> = TypedAction<
|
|
9
|
+
export type VarRef<TValue> = TypedAction<any, TValue>;
|
|
10
10
|
/**
|
|
11
11
|
* Maps each binding's output type to a VarRef. TypeScript resolves
|
|
12
12
|
* ExtractOutput from each binding expression.
|
|
13
13
|
*
|
|
14
|
-
* Constraint is `Action[]` (not `Pipeable<any, any>[]`)
|
|
15
|
-
* `
|
|
16
|
-
*
|
|
17
|
-
* Action union. Using raw `Action[]` avoids the phantom field
|
|
18
|
-
* assignability issue while `ExtractOutput` still extracts the correct
|
|
19
|
-
* output type from the phantom fields on the concrete types.
|
|
14
|
+
* Constraint is `Action[]` (not `Pipeable<any, any>[]`) so that
|
|
15
|
+
* `ExtractOutput` extracts the correct output type from the phantom
|
|
16
|
+
* fields on the concrete types without fighting invariant `__in` checks.
|
|
20
17
|
*/
|
|
21
18
|
export type InferVarRefs<TBindings extends Action[]> = {
|
|
22
19
|
[K in keyof TBindings]: VarRef<ExtractOutput<TBindings[K]>>;
|
|
@@ -40,12 +37,11 @@ export type InferVarRefs<TBindings extends Action[]> = {
|
|
|
40
37
|
*/
|
|
41
38
|
/**
|
|
42
39
|
* Constraint for the body callback return type. Only requires the output
|
|
43
|
-
* phantom
|
|
44
|
-
*
|
|
40
|
+
* phantom field — omits `__in` and `__in_co` so that body actions with
|
|
41
|
+
* any input type (e.g. pipelines starting from a VarRef) are assignable.
|
|
45
42
|
*/
|
|
46
43
|
type BodyResult<TOut> = Action & {
|
|
47
44
|
__out?: () => TOut;
|
|
48
|
-
__out_contra?: (output: TOut) => void;
|
|
49
45
|
};
|
|
50
46
|
export declare function bind<TBindings extends Action[], TOut>(bindings: [...TBindings], body: (vars: InferVarRefs<TBindings>) => BodyResult<TOut>): TypedAction<ExtractInput<TBindings[number]>, TOut>;
|
|
51
47
|
/**
|
package/dist/builtins.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type MergeTuple, type Option as OptionT, type Pipeable, type TaggedUnion, type TypedAction } from "./ast.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
/**
|
|
4
4
|
* Typed combinators for structural data transformations.
|
|
@@ -33,7 +33,14 @@ export declare function taggedUnionSchema<TDef extends Record<string, z.ZodTypeA
|
|
|
33
33
|
}>>>;
|
|
34
34
|
export declare function constant<TValue>(value: TValue): TypedAction<any, TValue>;
|
|
35
35
|
export declare function identity<TValue = any>(): TypedAction<TValue, TValue>;
|
|
36
|
-
export declare const drop: TypedAction<any,
|
|
36
|
+
export declare const drop: TypedAction<any, void>;
|
|
37
|
+
/**
|
|
38
|
+
* Halt execution with a fatal error. Not caught by tryCatch.
|
|
39
|
+
* Analogous to Rust's `panic!`.
|
|
40
|
+
*
|
|
41
|
+
* Output type is `never` — a panic never produces a value.
|
|
42
|
+
*/
|
|
43
|
+
export declare function panic(message: string): TypedAction<any, never>;
|
|
37
44
|
/**
|
|
38
45
|
* Wrap input as a tagged union member. Requires the full variant map TDef
|
|
39
46
|
* so the output type carries __def for branch decomposition.
|
|
@@ -68,18 +75,6 @@ export declare function withResource<TIn extends Record<string, unknown>, TResou
|
|
|
68
75
|
action: Pipeable<TResource & TIn, TOut>;
|
|
69
76
|
dispose: Pipeable<TResource, TDisposeOut>;
|
|
70
77
|
}): TypedAction<TIn, TOut>;
|
|
71
|
-
/**
|
|
72
|
-
* Run `action` on the input for its side effects, then discard the action's
|
|
73
|
-
* output and return the original input unchanged. The action must accept
|
|
74
|
-
* exactly `TInput`. Use `pick` inside the action's pipe if the inner
|
|
75
|
-
* handler needs a subset.
|
|
76
|
-
*
|
|
77
|
-
* Constraint: input must be an object (uses all + merge internally).
|
|
78
|
-
*
|
|
79
|
-
* Example:
|
|
80
|
-
* pipe(tap(pipe(pick("worktreePath", "description"), implement)), createPR)
|
|
81
|
-
*/
|
|
82
|
-
export declare function tap<TInput extends Record<string, unknown>>(action: Pipeable<TInput, any>): TypedAction<TInput, TInput>;
|
|
83
78
|
export declare function wrapInField<TField extends string, TValue>(field: TField): TypedAction<TValue, Record<TField, TValue>>;
|
|
84
79
|
export declare function range(start: number, end: number): TypedAction<any, number[]>;
|
|
85
80
|
/**
|
|
@@ -105,125 +100,4 @@ export declare function splitFirst<TElement>(): TypedAction<TElement[], OptionT<
|
|
|
105
100
|
* that can't be composed from existing AST nodes.
|
|
106
101
|
*/
|
|
107
102
|
export declare function splitLast<TElement>(): TypedAction<TElement[], OptionT<[TElement[], TElement]>>;
|
|
108
|
-
/**
|
|
109
|
-
* Extract the first element of an array.
|
|
110
|
-
* `readonly TElement[] → Option<TElement>`
|
|
111
|
-
*
|
|
112
|
-
* Composes `splitFirst` (which returns `Option<[TElement, TElement[]]>`)
|
|
113
|
-
* with `Option.map(getIndex(0))` to extract just the element.
|
|
114
|
-
*/
|
|
115
|
-
export declare function first<TElement>(): TypedAction<readonly TElement[], OptionT<TElement>>;
|
|
116
|
-
/**
|
|
117
|
-
* Extract the last element of an array.
|
|
118
|
-
* `readonly TElement[] → Option<TElement>`
|
|
119
|
-
*
|
|
120
|
-
* Composes `splitLast` (which returns `Option<[TElement[], TElement]>`)
|
|
121
|
-
* with `Option.map(getIndex(1))` to extract just the element.
|
|
122
|
-
*/
|
|
123
|
-
export declare function last<TElement>(): TypedAction<readonly TElement[], OptionT<TElement>>;
|
|
124
|
-
/**
|
|
125
|
-
* Option namespace. All combinators produce TypedAction AST nodes that
|
|
126
|
-
* desugar to branch + existing builtins, except collect which uses the
|
|
127
|
-
* CollectSome builtin.
|
|
128
|
-
*/
|
|
129
|
-
export declare const Option: {
|
|
130
|
-
/** Wrap a value as Some. `T → Option<T>` */
|
|
131
|
-
readonly some: <T>() => TypedAction<T, OptionT<T>>;
|
|
132
|
-
/** Produce a None. `never → Option<T>` */
|
|
133
|
-
readonly none: <T>() => TypedAction<never, OptionT<T>>;
|
|
134
|
-
/** Transform the Some value. `Option<T> → Option<U>` */
|
|
135
|
-
readonly map: <T, U>(action: Pipeable<T, U>) => TypedAction<OptionT<T>, OptionT<U>>;
|
|
136
|
-
/**
|
|
137
|
-
* Monadic bind (flatMap). If Some, pass the value to action which
|
|
138
|
-
* returns Option<U>. If None, stay None. `Option<T> → Option<U>`
|
|
139
|
-
*/
|
|
140
|
-
readonly andThen: <T, U>(action: Pipeable<T, OptionT<U>>) => TypedAction<OptionT<T>, OptionT<U>>;
|
|
141
|
-
/**
|
|
142
|
-
* Extract the Some value or produce a default from an action.
|
|
143
|
-
* `Option<T> → T`
|
|
144
|
-
*
|
|
145
|
-
* The None branch drops its void payload before calling defaultAction,
|
|
146
|
-
* matching Rust's `unwrap_or_else(|| default)`.
|
|
147
|
-
*/
|
|
148
|
-
readonly unwrapOr: <T>(defaultAction: Pipeable<never, T>) => TypedAction<OptionT<T>, T>;
|
|
149
|
-
/** Unwrap a nested Option. `Option<Option<T>> → Option<T>` */
|
|
150
|
-
readonly flatten: <T>() => TypedAction<OptionT<OptionT<T>>, OptionT<T>>;
|
|
151
|
-
/**
|
|
152
|
-
* Conditional keep. If Some, pass value to predicate which returns
|
|
153
|
-
* Option<T>. If None, stay None. `Option<T> → Option<T>`
|
|
154
|
-
*/
|
|
155
|
-
readonly filter: <T>(predicate: Pipeable<T, OptionT<T>>) => TypedAction<OptionT<T>, OptionT<T>>;
|
|
156
|
-
/**
|
|
157
|
-
* Collect Some values from an array, discarding Nones.
|
|
158
|
-
* `Option<T>[] → T[]`
|
|
159
|
-
*/
|
|
160
|
-
readonly collect: <T = any>() => TypedAction<OptionT<T>[], T[]>;
|
|
161
|
-
/** Test if the value is Some. `Option<T> → boolean` */
|
|
162
|
-
readonly isSome: <T>() => TypedAction<OptionT<T>, boolean>;
|
|
163
|
-
/** Test if the value is None. `Option<T> → boolean` */
|
|
164
|
-
readonly isNone: <T>() => TypedAction<OptionT<T>, boolean>;
|
|
165
|
-
/**
|
|
166
|
-
* Build a Zod schema for `Option<T>`.
|
|
167
|
-
*
|
|
168
|
-
* ```ts
|
|
169
|
-
* const schema = Option.schema(z.string());
|
|
170
|
-
* // validates: { kind: "Some", value: "hello" } or { kind: "None", value: null }
|
|
171
|
-
* ```
|
|
172
|
-
*/
|
|
173
|
-
readonly schema: <TValue>(valueSchema: z.ZodType<TValue>) => z.ZodType<OptionT<TValue>>;
|
|
174
|
-
};
|
|
175
|
-
export declare const Result: {
|
|
176
|
-
/** Wrap a value as Ok. `TValue → Result<TValue, TError>` */
|
|
177
|
-
readonly ok: <TValue, TError>() => TypedAction<TValue, ResultT<TValue, TError>>;
|
|
178
|
-
/** Wrap a value as Err. `TError → Result<TValue, TError>` */
|
|
179
|
-
readonly err: <TValue, TError>() => TypedAction<TError, ResultT<TValue, TError>>;
|
|
180
|
-
/** Transform the Ok value. `Result<TValue, TError> → Result<TOut, TError>` */
|
|
181
|
-
readonly map: <TValue, TOut, TError>(action: Pipeable<TValue, TOut>) => TypedAction<ResultT<TValue, TError>, ResultT<TOut, TError>>;
|
|
182
|
-
/** Transform the Err value. `Result<TValue, TError> → Result<TValue, TErrorOut>` */
|
|
183
|
-
readonly mapErr: <TValue, TError, TErrorOut>(action: Pipeable<TError, TErrorOut>) => TypedAction<ResultT<TValue, TError>, ResultT<TValue, TErrorOut>>;
|
|
184
|
-
/**
|
|
185
|
-
* Monadic bind (flatMap) for Ok. If Ok, pass value to action which
|
|
186
|
-
* returns Result<TOut, TError>. If Err, propagate.
|
|
187
|
-
*/
|
|
188
|
-
readonly andThen: <TValue, TOut, TError>(action: Pipeable<TValue, ResultT<TOut, TError>>) => TypedAction<ResultT<TValue, TError>, ResultT<TOut, TError>>;
|
|
189
|
-
/** Fallback on Err. If Ok, keep it. If Err, pass error to fallback. */
|
|
190
|
-
readonly or: <TValue, TError, TErrorOut>(fallback: Pipeable<TError, ResultT<TValue, TErrorOut>>) => TypedAction<ResultT<TValue, TError>, ResultT<TValue, TErrorOut>>;
|
|
191
|
-
/** Replace Ok value with another Result. If Ok, discard value and return other. */
|
|
192
|
-
readonly and: <TValue, TOut, TError>(other: Pipeable<never, ResultT<TOut, TError>>) => TypedAction<ResultT<TValue, TError>, ResultT<TOut, TError>>;
|
|
193
|
-
/**
|
|
194
|
-
* Extract Ok or compute default from Err. `Result<TValue, TError> → TValue`
|
|
195
|
-
*
|
|
196
|
-
* Uses covariant output checking so throw tokens (Out=never) are assignable.
|
|
197
|
-
* For inference-free usage with throw tokens, prefer the postfix method:
|
|
198
|
-
* `handler.unwrapOr(throwError)`.
|
|
199
|
-
*/
|
|
200
|
-
readonly unwrapOr: <TValue, TError>(defaultAction: Action & {
|
|
201
|
-
__in?: (input: TError) => void;
|
|
202
|
-
__out?: () => TValue;
|
|
203
|
-
}) => TypedAction<ResultT<TValue, TError>, TValue>;
|
|
204
|
-
/** Unwrap nested Result. `Result<Result<TValue, TError>, TError> → Result<TValue, TError>` */
|
|
205
|
-
readonly flatten: <TValue, TError>() => TypedAction<ResultT<ResultT<TValue, TError>, TError>, ResultT<TValue, TError>>;
|
|
206
|
-
/** Convert Ok to Some, Err to None. `Result<TValue, TError> → Option<TValue>` */
|
|
207
|
-
readonly toOption: <TValue, TError>() => TypedAction<ResultT<TValue, TError>, OptionT<TValue>>;
|
|
208
|
-
/** Convert Err to Some, Ok to None. `Result<TValue, TError> → Option<TError>` */
|
|
209
|
-
readonly toOptionErr: <TValue, TError>() => TypedAction<ResultT<TValue, TError>, OptionT<TError>>;
|
|
210
|
-
/**
|
|
211
|
-
* Swap Result/Option nesting.
|
|
212
|
-
* `Result<Option<TValue>, TError> → Option<Result<TValue, TError>>`
|
|
213
|
-
*/
|
|
214
|
-
readonly transpose: <TValue, TError>() => TypedAction<ResultT<OptionT<TValue>, TError>, OptionT<ResultT<TValue, TError>>>;
|
|
215
|
-
/** Test if the value is Ok. `Result<TValue, TError> → boolean` */
|
|
216
|
-
readonly isOk: <TValue, TError>() => TypedAction<ResultT<TValue, TError>, boolean>;
|
|
217
|
-
/** Test if the value is Err. `Result<TValue, TError> → boolean` */
|
|
218
|
-
readonly isErr: <TValue, TError>() => TypedAction<ResultT<TValue, TError>, boolean>;
|
|
219
|
-
/**
|
|
220
|
-
* Build a Zod schema for `Result<TValue, TError>`.
|
|
221
|
-
*
|
|
222
|
-
* ```ts
|
|
223
|
-
* const schema = Result.schema(z.string(), z.number());
|
|
224
|
-
* // validates: { kind: "Ok", value: "hello" } or { kind: "Err", value: 42 }
|
|
225
|
-
* ```
|
|
226
|
-
*/
|
|
227
|
-
readonly schema: <TValue, TError>(okSchema: z.ZodType<TValue>, errSchema: z.ZodType<TError>) => z.ZodType<ResultT<TValue, TError>>;
|
|
228
|
-
};
|
|
229
103
|
export {};
|