@barnum/barnum 0.0.0-main-50effdfd → 0.0.0-main-3c07d795

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/ast.d.ts CHANGED
@@ -68,10 +68,10 @@ export type BuiltinKind = {
68
68
  } | {
69
69
  kind: "Flatten";
70
70
  } | {
71
- kind: "ExtractField";
71
+ kind: "GetField";
72
72
  value: string;
73
73
  } | {
74
- kind: "ExtractIndex";
74
+ kind: "GetIndex";
75
75
  value: number;
76
76
  } | {
77
77
  kind: "Pick";
@@ -134,8 +134,10 @@ export type TypedAction<In = unknown, Out = unknown, Refs extends string = never
134
134
  drop(): TypedAction<In, never, Refs>;
135
135
  /** Wrap output as a tagged union member. Requires full variant map TDef so __def is carried. */
136
136
  tag<TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(kind: TKind): TypedAction<In, TaggedUnion<TDef>, Refs>;
137
- /** Extract a field from the output object. `a.get("name")` ≡ `pipe(a, extractField("name"))`. */
138
- get<TField extends keyof Out & string>(field: TField): TypedAction<In, Out[TField], Refs>;
137
+ /** 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>;
139
+ /** 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>;
139
141
  /** Wrap output in an object under a field name. `a.wrapInField("foo")` ≡ `pipe(a, wrapInField("foo"))`. */
140
142
  wrapInField<TField extends string>(field: TField): TypedAction<In, Record<TField, Out>, Refs>;
141
143
  /** Merge a tuple of objects into a single object. `a.merge()` ≡ `pipe(a, merge())`. */
@@ -339,7 +341,7 @@ export declare const IDENTITY: Action;
339
341
  * If the body completes normally → output is TOut.
340
342
  * If restart fires → body re-executes with the restarted value.
341
343
  *
342
- * Compiled form: `RestartHandle(id, ExtractIndex(0), body)`
344
+ * Compiled form: `RestartHandle(id, GetIndex(0), body)`
343
345
  */
344
346
  export declare function recur<TIn = never, TOut = any>(bodyFn: (restart: TypedAction<TIn, never>) => Pipeable<TIn, TOut>): TypedAction<PipeIn<TIn>, TOut>;
345
347
  /**
@@ -357,7 +359,7 @@ export declare function recur<TIn = never, TOut = any>(bodyFn: (restart: TypedAc
357
359
  export declare function earlyReturn<TEarlyReturn = never, TIn = any, TOut = any>(bodyFn: (earlyReturn: TypedAction<TEarlyReturn, never>) => Pipeable<TIn, TOut>): TypedAction<TIn, TEarlyReturn | TOut>;
358
360
  /**
359
361
  * Build the restart+branch compiled form:
360
- * `Chain(Tag("Continue"), RestartHandle(id, ExtractIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
362
+ * `Chain(Tag("Continue"), RestartHandle(id, GetIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
361
363
  *
362
364
  * Input is tagged Continue so the Branch enters the continueArm on first execution.
363
365
  * Continue tag → restart → re-enters continueArm. Break tag → restart → runs breakArm, exits `RestartHandle`.
package/dist/ast.js CHANGED
@@ -49,7 +49,7 @@ function tagMethod(kind) {
49
49
  },
50
50
  });
51
51
  }
52
- function getMethod(field) {
52
+ function getFieldMethod(field) {
53
53
  return typedAction({
54
54
  kind: "Chain",
55
55
  first: this,
@@ -57,7 +57,20 @@ function getMethod(field) {
57
57
  kind: "Invoke",
58
58
  handler: {
59
59
  kind: "Builtin",
60
- builtin: { kind: "ExtractField", value: field },
60
+ builtin: { kind: "GetField", value: field },
61
+ },
62
+ },
63
+ });
64
+ }
65
+ function getIndexMethod(index) {
66
+ return typedAction({
67
+ kind: "Chain",
68
+ first: this,
69
+ rest: {
70
+ kind: "Invoke",
71
+ handler: {
72
+ kind: "Builtin",
73
+ builtin: { kind: "GetIndex", value: index },
61
74
  },
62
75
  },
63
76
  });
@@ -202,7 +215,8 @@ export function typedAction(action) {
202
215
  flatten: { value: flattenMethod, configurable: true },
203
216
  drop: { value: dropMethod, configurable: true },
204
217
  tag: { value: tagMethod, configurable: true },
205
- get: { value: getMethod, configurable: true },
218
+ getField: { value: getFieldMethod, configurable: true },
219
+ getIndex: { value: getIndexMethod, configurable: true },
206
220
  wrapInField: { value: wrapInFieldMethod, configurable: true },
207
221
  merge: { value: mergeMethod, configurable: true },
208
222
  pick: { value: pickMethod, configurable: true },
@@ -231,7 +245,7 @@ export function forEach(action) {
231
245
  return typedAction({ kind: "ForEach", action: action });
232
246
  }
233
247
  /**
234
- * Insert ExtractField("value") before each case handler in a branch.
248
+ * Insert GetField("value") before each case handler in a branch.
235
249
  * This implements auto-unwrapping: the engine dispatches on `kind`, then
236
250
  * extracts `value` before passing to the handler. Case handlers receive
237
251
  * the payload directly, not the full `{ kind, value }` variant.
@@ -245,7 +259,7 @@ function unwrapBranchCases(cases) {
245
259
  kind: "Invoke",
246
260
  handler: {
247
261
  kind: "Builtin",
248
- builtin: { kind: "ExtractField", value: "value" },
262
+ builtin: { kind: "GetField", value: "value" },
249
263
  },
250
264
  },
251
265
  rest: cases[key],
@@ -262,7 +276,7 @@ export function branch(cases) {
262
276
  // ---------------------------------------------------------------------------
263
277
  const EXTRACT_PAYLOAD = {
264
278
  kind: "Invoke",
265
- handler: { kind: "Builtin", builtin: { kind: "ExtractIndex", value: 0 } },
279
+ handler: { kind: "Builtin", builtin: { kind: "GetIndex", value: 0 } },
266
280
  };
267
281
  const TAG_CONTINUE = {
268
282
  kind: "Invoke",
@@ -286,7 +300,7 @@ export const IDENTITY = {
286
300
  * If the body completes normally → output is TOut.
287
301
  * If restart fires → body re-executes with the restarted value.
288
302
  *
289
- * Compiled form: `RestartHandle(id, ExtractIndex(0), body)`
303
+ * Compiled form: `RestartHandle(id, GetIndex(0), body)`
290
304
  */
291
305
  export function recur(bodyFn) {
292
306
  const restartHandlerId = allocateRestartHandlerId();
@@ -332,7 +346,7 @@ export function earlyReturn(bodyFn) {
332
346
  // ---------------------------------------------------------------------------
333
347
  /**
334
348
  * Build the restart+branch compiled form:
335
- * `Chain(Tag("Continue"), RestartHandle(id, ExtractIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
349
+ * `Chain(Tag("Continue"), RestartHandle(id, GetIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
336
350
  *
337
351
  * Input is tagged Continue so the Branch enters the continueArm on first execution.
338
352
  * Continue tag → restart → re-enters continueArm. Break tag → restart → runs breakArm, exits `RestartHandle`.
package/dist/bind.d.ts CHANGED
@@ -3,7 +3,7 @@ import { type Action, type ExtractInput, type ExtractOutput, type TypedAction }
3
3
  * A typed reference to a bound value. Output is `TValue`.
4
4
  *
5
5
  * Use `.then()` (not `pipe()`) when chaining a VarRef into a generic
6
- * action like `pick` or `extractField` — pipe overloads can't infer
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
9
  export type VarRef<TValue> = TypedAction<never, TValue>;
@@ -33,7 +33,7 @@ export type InferVarRefs<TBindings extends Action[]> = {
33
33
  * All(...bindings, Identity),
34
34
  * ResumeHandle(r0, readVar(0),
35
35
  * ResumeHandle(r1, readVar(1),
36
- * Chain(ExtractIndex(N), body)
36
+ * Chain(GetIndex(N), body)
37
37
  * )
38
38
  * )
39
39
  * )
package/dist/bind.js CHANGED
@@ -18,7 +18,7 @@ function createVarRef(resumeHandlerId) {
18
18
  * `state` (index 1) is the full All output tuple. The handler produces
19
19
  * `[state[n], state]` — value is state[n], new_state is state (unchanged).
20
20
  *
21
- * Expanded AST: All(Chain(ExtractIndex(1), ExtractIndex(n)), ExtractIndex(1))
21
+ * Expanded AST: All(Chain(GetIndex(1), GetIndex(n)), GetIndex(1))
22
22
  */
23
23
  function readVar(n) {
24
24
  return {
@@ -30,14 +30,14 @@ function readVar(n) {
30
30
  kind: "Invoke",
31
31
  handler: {
32
32
  kind: "Builtin",
33
- builtin: { kind: "ExtractIndex", value: 1 },
33
+ builtin: { kind: "GetIndex", value: 1 },
34
34
  },
35
35
  },
36
36
  rest: {
37
37
  kind: "Invoke",
38
38
  handler: {
39
39
  kind: "Builtin",
40
- builtin: { kind: "ExtractIndex", value: n },
40
+ builtin: { kind: "GetIndex", value: n },
41
41
  },
42
42
  },
43
43
  },
@@ -45,7 +45,7 @@ function readVar(n) {
45
45
  kind: "Invoke",
46
46
  handler: {
47
47
  kind: "Builtin",
48
- builtin: { kind: "ExtractIndex", value: 1 },
48
+ builtin: { kind: "GetIndex", value: 1 },
49
49
  },
50
50
  },
51
51
  ],
@@ -67,7 +67,7 @@ export function bind(bindings, body) {
67
67
  kind: "Invoke",
68
68
  handler: {
69
69
  kind: "Builtin",
70
- builtin: { kind: "ExtractIndex", value: pipelineInputIndex },
70
+ builtin: { kind: "GetIndex", value: pipelineInputIndex },
71
71
  },
72
72
  },
73
73
  rest: bodyAction,
@@ -81,7 +81,10 @@ export function bind(bindings, body) {
81
81
  };
82
82
  }
83
83
  // 5. All(...bindings, identity()) → nested Handles
84
- const allActions = [...bindings.map((b) => b), identity];
84
+ const allActions = [
85
+ ...bindings.map((b) => b),
86
+ identity(),
87
+ ];
85
88
  return typedAction({
86
89
  kind: "Chain",
87
90
  first: { kind: "All", actions: allActions },
@@ -102,5 +105,5 @@ export function bind(bindings, body) {
102
105
  * bindInput<FileEntry>((entry) => ...)
103
106
  */
104
107
  export function bindInput(body) {
105
- return bind([identity], ([input]) => pipe(drop, body(input)));
108
+ return bind([identity()], ([input]) => pipe(drop, body(input)));
106
109
  }
@@ -6,7 +6,7 @@ import { type Action, type MergeTuple, type Option as OptionT, type Pipeable, ty
6
6
  * kinds. The Rust scheduler executes them inline (no subprocess).
7
7
  */
8
8
  export declare function constant<TValue>(value: TValue): TypedAction<any, TValue>;
9
- export declare const identity: TypedAction<any, any>;
9
+ export declare function identity<TValue = any>(): TypedAction<TValue, TValue>;
10
10
  export declare const drop: TypedAction<any, never>;
11
11
  /**
12
12
  * Wrap input as a tagged union member. Requires the full variant map TDef
@@ -18,8 +18,8 @@ export declare const drop: TypedAction<any, never>;
18
18
  export declare function tag<TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(kind: TKind): TypedAction<TDef[TKind], TaggedUnion<TDef>>;
19
19
  export declare function merge<TTuple extends Record<string, unknown>[]>(): TypedAction<TTuple, MergeTuple<TTuple>>;
20
20
  export declare function flatten<TElement>(): TypedAction<TElement[][], TElement[]>;
21
- export declare function extractField<TObj extends Record<string, unknown>, TField extends keyof TObj & string>(field: TField): TypedAction<TObj, TObj[TField]>;
22
- export declare function extractIndex<TTuple extends unknown[], TIndex extends number>(index: TIndex): TypedAction<TTuple, TTuple[TIndex]>;
21
+ export declare function getField<TObj extends Record<string, unknown>, TField extends keyof TObj & string>(field: TField): TypedAction<TObj, TObj[TField]>;
22
+ export declare function getIndex<TTuple extends unknown[], TIndex extends number>(index: TIndex): TypedAction<TTuple, TTuple[TIndex]>;
23
23
  export declare function pick<TObj extends Record<string, unknown>, TKeys extends (keyof TObj & string)[]>(...keys: TKeys): TypedAction<TObj, Pick<TObj, TKeys[number]>>;
24
24
  export declare function dropResult<TInput, TOutput>(action: Pipeable<TInput, TOutput>): TypedAction<TInput, never>;
25
25
  /**
package/dist/builtins.js CHANGED
@@ -18,10 +18,12 @@ export function constant(value) {
18
18
  // ---------------------------------------------------------------------------
19
19
  // Identity — pass input through unchanged
20
20
  // ---------------------------------------------------------------------------
21
- export const identity = typedAction({
22
- kind: "Invoke",
23
- handler: { kind: "Builtin", builtin: { kind: "Identity" } },
24
- });
21
+ export function identity() {
22
+ return typedAction({
23
+ kind: "Invoke",
24
+ handler: { kind: "Builtin", builtin: { kind: "Identity" } },
25
+ });
26
+ }
25
27
  // ---------------------------------------------------------------------------
26
28
  // Drop — discard pipeline value
27
29
  // ---------------------------------------------------------------------------
@@ -64,26 +66,26 @@ export function flatten() {
64
66
  });
65
67
  }
66
68
  // ---------------------------------------------------------------------------
67
- // ExtractField — extract a single field from an object
69
+ // GetField — extract a single field from an object
68
70
  // ---------------------------------------------------------------------------
69
- export function extractField(field) {
71
+ export function getField(field) {
70
72
  return typedAction({
71
73
  kind: "Invoke",
72
74
  handler: {
73
75
  kind: "Builtin",
74
- builtin: { kind: "ExtractField", value: field },
76
+ builtin: { kind: "GetField", value: field },
75
77
  },
76
78
  });
77
79
  }
78
80
  // ---------------------------------------------------------------------------
79
- // ExtractIndex — extract a single element from an array by index
81
+ // GetIndex — extract a single element from an array by index
80
82
  // ---------------------------------------------------------------------------
81
- export function extractIndex(index) {
83
+ export function getIndex(index) {
82
84
  return typedAction({
83
85
  kind: "Invoke",
84
86
  handler: {
85
87
  kind: "Builtin",
86
- builtin: { kind: "ExtractIndex", value: index },
88
+ builtin: { kind: "GetIndex", value: index },
87
89
  },
88
90
  });
89
91
  }
@@ -138,24 +140,24 @@ export function withResource({ create, action, dispose, }) {
138
140
  // Step 1: all(create, identity) → [TResource, TIn] → merge → TResource & TIn
139
141
  const acquireAndMerge = chain(typedAction({
140
142
  kind: "All",
141
- actions: [create, identity],
143
+ actions: [create, identity()],
142
144
  }), typedAction(mergeBuiltin));
143
145
  // Step 2: all(action, identity) → [TOut, TResource & TIn]
144
146
  // Keep merged object so dispose can access resource fields.
145
147
  const actionAndKeepMerged = typedAction({
146
148
  kind: "All",
147
- actions: [action, identity],
149
+ actions: [action, identity()],
148
150
  });
149
- // Step 3: all(extractIndex(0), chain(extractIndex(1), dispose)) → [TOut, unknown]
151
+ // Step 3: all(getIndex(0), chain(getIndex(1), dispose)) → [TOut, unknown]
150
152
  const disposeAndKeepResult = typedAction({
151
153
  kind: "All",
152
154
  actions: [
153
- extractIndex(0),
154
- chain(extractIndex(1), dispose),
155
+ getIndex(0),
156
+ chain(getIndex(1), dispose),
155
157
  ],
156
158
  });
157
- // Step 4: extractIndex(0) → TOut
158
- return chain(chain(chain(acquireAndMerge, actionAndKeepMerged), disposeAndKeepResult), extractIndex(0));
159
+ // Step 4: getIndex(0) → TOut
160
+ return chain(chain(chain(acquireAndMerge, actionAndKeepMerged), disposeAndKeepResult), getIndex(0));
159
161
  }
160
162
  // ---------------------------------------------------------------------------
161
163
  // Tap — run an action for side effects, preserve original input
@@ -281,7 +283,7 @@ const EXTRACT_VALUE = {
281
283
  kind: "Invoke",
282
284
  handler: {
283
285
  kind: "Builtin",
284
- builtin: { kind: "ExtractField", value: "value" },
286
+ builtin: { kind: "GetField", value: "value" },
285
287
  },
286
288
  };
287
289
  const DROP = {
@@ -292,7 +294,7 @@ const IDENTITY = {
292
294
  kind: "Invoke",
293
295
  handler: { kind: "Builtin", builtin: { kind: "Identity" } },
294
296
  };
295
- /** Wrap branch cases with ExtractField("value") auto-unwrapping. */
297
+ /** Wrap branch cases with GetField("value") auto-unwrapping. */
296
298
  function optionBranch(someCaseBody, noneCaseBody) {
297
299
  return {
298
300
  kind: "Branch",
@@ -455,7 +457,7 @@ const TAG_ERR = {
455
457
  kind: "Invoke",
456
458
  handler: { kind: "Builtin", builtin: { kind: "Tag", value: "Err" } },
457
459
  };
458
- /** Wrap branch cases with ExtractField("value") auto-unwrapping. */
460
+ /** Wrap branch cases with GetField("value") auto-unwrapping. */
459
461
  function resultBranch(okCaseBody, errCaseBody) {
460
462
  return {
461
463
  kind: "Branch",
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { TaggedUnion, OptionDef, ResultDef } from "./ast.js";
2
2
  export * from "./ast.js";
3
- export { constant, identity, drop, tag, merge, flatten, extractField, extractIndex, pick, dropResult, withResource, tap, range, splitFirst, splitLast, wrapInField, Option, Result, } from "./builtins.js";
3
+ export { constant, identity, drop, tag, merge, flatten, getField, getIndex, pick, dropResult, withResource, tap, range, splitFirst, splitLast, wrapInField, Option, Result, } from "./builtins.js";
4
4
  export * from "./handler.js";
5
5
  export { runPipeline, type RunPipelineOptions, type LogLevel } from "./run.js";
6
6
  export { zodToCheckedJsonSchema } from "./schema.js";
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export * from "./ast.js";
2
- export { constant, identity, drop, tag, merge, flatten, extractField, extractIndex, pick, dropResult, withResource, tap, range, splitFirst, splitLast, wrapInField, Option, Result, } from "./builtins.js";
2
+ export { constant, identity, drop, tag, merge, flatten, getField, getIndex, pick, dropResult, withResource, tap, range, splitFirst, splitLast, wrapInField, Option, Result, } from "./builtins.js";
3
3
  export * from "./handler.js";
4
4
  export { runPipeline } from "./run.js";
5
5
  export { zodToCheckedJsonSchema } from "./schema.js";
package/dist/pipe.js CHANGED
@@ -2,7 +2,7 @@ import { typedAction, } from "./ast.js";
2
2
  import { identity } from "./builtins.js";
3
3
  export function pipe(...actions) {
4
4
  if (actions.length === 0) {
5
- return identity;
5
+ return identity();
6
6
  }
7
7
  if (actions.length === 1) {
8
8
  return actions[0];
package/dist/race.d.ts CHANGED
@@ -8,7 +8,7 @@ import { type Pipeable, type Result, type TypedAction } from "./ast.js";
8
8
  *
9
9
  * Compiled form (restart+Branch, same substrate as loop/earlyReturn):
10
10
  * `Chain(Tag("Continue"),`
11
- * `RestartHandle(id, ExtractIndex(0),`
11
+ * `RestartHandle(id, GetIndex(0),`
12
12
  * `Branch({`
13
13
  * `Continue: All(Chain(a, breakPerform), Chain(b, breakPerform), ...),`
14
14
  * `Break: identity,`
package/dist/race.js CHANGED
@@ -35,7 +35,7 @@ function breakPerform(restartHandlerId) {
35
35
  *
36
36
  * Compiled form (restart+Branch, same substrate as loop/earlyReturn):
37
37
  * `Chain(Tag("Continue"),`
38
- * `RestartHandle(id, ExtractIndex(0),`
38
+ * `RestartHandle(id, GetIndex(0),`
39
39
  * `Branch({`
40
40
  * `Continue: All(Chain(a, breakPerform), Chain(b, breakPerform), ...),`
41
41
  * `Break: identity,`
package/dist/recursive.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { typedAction, branch, } from "./ast.js";
2
2
  import { all } from "./all.js";
3
3
  import { chain } from "./chain.js";
4
- import { constant, identity, extractField, extractIndex, tag, } from "./builtins.js";
4
+ import { constant, identity, getField, getIndex, tag } from "./builtins.js";
5
5
  import { allocateResumeHandlerId } from "./effect-id.js";
6
6
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
7
  const UNUSED_STATE = undefined;
@@ -35,19 +35,19 @@ export function defineRecursiveFunctions(bodiesFn) {
35
35
  const callTokens = Array.from({ length: fnCount }, (_, i) => typedAction(chain(tag(`Call${i}`), resumePerform)));
36
36
  // Get function body ASTs
37
37
  const bodyActions = bodiesFn(...callTokens);
38
- // Branch cases: CallN → ExtractField("value") → bodyN
38
+ // Branch cases: CallN → GetField("value") → bodyN
39
39
  const cases = {};
40
40
  for (let i = 0; i < bodyActions.length; i++) {
41
- cases[`Call${i}`] = chain(extractField("value"), bodyActions[i]);
41
+ cases[`Call${i}`] = chain(getField("value"), bodyActions[i]);
42
42
  }
43
43
  // Return curried entry-point combinator
44
44
  return (entryFn) => {
45
45
  const userBody = entryFn(...callTokens);
46
- return typedAction(chain(all(identity, constant(UNUSED_STATE)), {
46
+ return typedAction(chain(all(identity(), constant(UNUSED_STATE)), {
47
47
  kind: "ResumeHandle",
48
48
  resume_handler_id: resumeHandlerId,
49
- body: chain(extractIndex(0), userBody),
50
- handler: all(chain(extractIndex(0), branch(cases)), constant(UNUSED_STATE)),
49
+ body: chain(getIndex(0), userBody),
50
+ handler: all(chain(getIndex(0), branch(cases)), constant(UNUSED_STATE)),
51
51
  }));
52
52
  };
53
53
  }
@@ -12,7 +12,7 @@ import { type Pipeable, type TypedAction } from "./ast.js";
12
12
  *
13
13
  * Compiled form (restart+Branch, same substrate as loop/earlyReturn):
14
14
  * `Chain(Tag("Continue"),`
15
- * `RestartHandle(id, ExtractIndex(0),`
15
+ * `RestartHandle(id, GetIndex(0),`
16
16
  * `Branch({ Continue: body, Break: recovery })))`
17
17
  *
18
18
  * throwError = `Chain(Tag("Break"), RestartPerform(id))`
package/dist/try-catch.js CHANGED
@@ -16,7 +16,7 @@ import { allocateRestartHandlerId } from "./effect-id.js";
16
16
  *
17
17
  * Compiled form (restart+Branch, same substrate as loop/earlyReturn):
18
18
  * `Chain(Tag("Continue"),`
19
- * `RestartHandle(id, ExtractIndex(0),`
19
+ * `RestartHandle(id, GetIndex(0),`
20
20
  * `Branch({ Continue: body, Break: recovery })))`
21
21
  *
22
22
  * throwError = `Chain(Tag("Break"), RestartPerform(id))`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barnum/barnum",
3
- "version": "0.0.0-main-50effdfd",
3
+ "version": "0.0.0-main-3c07d795",
4
4
  "description": "Barnum workflow engine",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/ast.ts CHANGED
@@ -91,8 +91,8 @@ export type BuiltinKind =
91
91
  | { kind: "Tag"; value: string }
92
92
  | { kind: "Merge" }
93
93
  | { kind: "Flatten" }
94
- | { kind: "ExtractField"; value: string }
95
- | { kind: "ExtractIndex"; value: number }
94
+ | { kind: "GetField"; value: string }
95
+ | { kind: "GetIndex"; value: number }
96
96
  | { kind: "Pick"; value: string[] }
97
97
  | { kind: "CollectSome" }
98
98
  | { kind: "SplitFirst" }
@@ -183,10 +183,20 @@ export type TypedAction<
183
183
  tag<TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(
184
184
  kind: TKind,
185
185
  ): TypedAction<In, TaggedUnion<TDef>, Refs>;
186
- /** Extract a field from the output object. `a.get("name")` ≡ `pipe(a, extractField("name"))`. */
187
- get<TField extends keyof Out & string>(
186
+ /** Extract a field from the output object. `a.getField("name")` ≡ `pipe(a, getField("name"))`. */
187
+ getField<TField extends keyof Out & string>(
188
188
  field: TField,
189
189
  ): TypedAction<In, Out[TField], Refs>;
190
+ /** Extract an element from the output tuple by index. `a.getIndex(0)` ≡ `pipe(a, getIndex(0))`. */
191
+ getIndex<
192
+ TIn,
193
+ TTuple extends unknown[],
194
+ TIndex extends number,
195
+ TRefs extends string,
196
+ >(
197
+ this: TypedAction<TIn, TTuple, TRefs>,
198
+ index: TIndex,
199
+ ): TypedAction<TIn, TTuple[TIndex], TRefs>;
190
200
  /** Wrap output in an object under a field name. `a.wrapInField("foo")` ≡ `pipe(a, wrapInField("foo"))`. */
191
201
  wrapInField<TField extends string>(
192
202
  field: TField,
@@ -428,7 +438,21 @@ function tagMethod(this: TypedAction, kind: string): TypedAction {
428
438
  });
429
439
  }
430
440
 
431
- function getMethod(this: TypedAction, field: string): TypedAction {
441
+ function getFieldMethod(this: TypedAction, field: string): TypedAction {
442
+ return typedAction({
443
+ kind: "Chain",
444
+ first: this,
445
+ rest: {
446
+ kind: "Invoke",
447
+ handler: {
448
+ kind: "Builtin",
449
+ builtin: { kind: "GetField", value: field },
450
+ },
451
+ },
452
+ });
453
+ }
454
+
455
+ function getIndexMethod(this: TypedAction, index: number): TypedAction {
432
456
  return typedAction({
433
457
  kind: "Chain",
434
458
  first: this,
@@ -436,7 +460,7 @@ function getMethod(this: TypedAction, field: string): TypedAction {
436
460
  kind: "Invoke",
437
461
  handler: {
438
462
  kind: "Builtin",
439
- builtin: { kind: "ExtractField", value: field },
463
+ builtin: { kind: "GetIndex", value: index },
440
464
  },
441
465
  },
442
466
  });
@@ -594,7 +618,8 @@ export function typedAction<
594
618
  flatten: { value: flattenMethod, configurable: true },
595
619
  drop: { value: dropMethod, configurable: true },
596
620
  tag: { value: tagMethod, configurable: true },
597
- get: { value: getMethod, configurable: true },
621
+ getField: { value: getFieldMethod, configurable: true },
622
+ getIndex: { value: getIndexMethod, configurable: true },
598
623
  wrapInField: { value: wrapInFieldMethod, configurable: true },
599
624
  merge: { value: mergeMethod, configurable: true },
600
625
  pick: { value: pickMethod, configurable: true },
@@ -659,7 +684,7 @@ export function forEach<In, Out>(
659
684
  }
660
685
 
661
686
  /**
662
- * Insert ExtractField("value") before each case handler in a branch.
687
+ * Insert GetField("value") before each case handler in a branch.
663
688
  * This implements auto-unwrapping: the engine dispatches on `kind`, then
664
689
  * extracts `value` before passing to the handler. Case handlers receive
665
690
  * the payload directly, not the full `{ kind, value }` variant.
@@ -675,7 +700,7 @@ function unwrapBranchCases(
675
700
  kind: "Invoke",
676
701
  handler: {
677
702
  kind: "Builtin",
678
- builtin: { kind: "ExtractField", value: "value" },
703
+ builtin: { kind: "GetField", value: "value" },
679
704
  },
680
705
  },
681
706
  rest: cases[key],
@@ -725,7 +750,7 @@ export type LoopResult<TContinue, TBreak> = TaggedUnion<
725
750
 
726
751
  const EXTRACT_PAYLOAD: Action = {
727
752
  kind: "Invoke",
728
- handler: { kind: "Builtin", builtin: { kind: "ExtractIndex", value: 0 } },
753
+ handler: { kind: "Builtin", builtin: { kind: "GetIndex", value: 0 } },
729
754
  };
730
755
 
731
756
  const TAG_CONTINUE: Action = {
@@ -754,7 +779,7 @@ export const IDENTITY: Action = {
754
779
  * If the body completes normally → output is TOut.
755
780
  * If restart fires → body re-executes with the restarted value.
756
781
  *
757
- * Compiled form: `RestartHandle(id, ExtractIndex(0), body)`
782
+ * Compiled form: `RestartHandle(id, GetIndex(0), body)`
758
783
  */
759
784
  export function recur<TIn = never, TOut = any>(
760
785
  bodyFn: (restart: TypedAction<TIn, never>) => Pipeable<TIn, TOut>,
@@ -818,7 +843,7 @@ export function earlyReturn<TEarlyReturn = never, TIn = any, TOut = any>(
818
843
 
819
844
  /**
820
845
  * Build the restart+branch compiled form:
821
- * `Chain(Tag("Continue"), RestartHandle(id, ExtractIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
846
+ * `Chain(Tag("Continue"), RestartHandle(id, GetIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
822
847
  *
823
848
  * Input is tagged Continue so the Branch enters the continueArm on first execution.
824
849
  * Continue tag → restart → re-enters continueArm. Break tag → restart → runs breakArm, exits `RestartHandle`.
package/src/bind.ts CHANGED
@@ -17,7 +17,7 @@ import { pipe } from "./pipe.js";
17
17
  * A typed reference to a bound value. Output is `TValue`.
18
18
  *
19
19
  * Use `.then()` (not `pipe()`) when chaining a VarRef into a generic
20
- * action like `pick` or `extractField` — pipe overloads can't infer
20
+ * action like `pick` or `getField` — pipe overloads can't infer
21
21
  * the generic's type parameter from the VarRef's output.
22
22
  */
23
23
  export type VarRef<TValue> = TypedAction<never, TValue>;
@@ -61,7 +61,7 @@ export type InferVarRefs<TBindings extends Action[]> = {
61
61
  * `state` (index 1) is the full All output tuple. The handler produces
62
62
  * `[state[n], state]` — value is state[n], new_state is state (unchanged).
63
63
  *
64
- * Expanded AST: All(Chain(ExtractIndex(1), ExtractIndex(n)), ExtractIndex(1))
64
+ * Expanded AST: All(Chain(GetIndex(1), GetIndex(n)), GetIndex(1))
65
65
  */
66
66
  function readVar(n: number): Action {
67
67
  return {
@@ -73,14 +73,14 @@ function readVar(n: number): Action {
73
73
  kind: "Invoke",
74
74
  handler: {
75
75
  kind: "Builtin",
76
- builtin: { kind: "ExtractIndex", value: 1 },
76
+ builtin: { kind: "GetIndex", value: 1 },
77
77
  },
78
78
  },
79
79
  rest: {
80
80
  kind: "Invoke",
81
81
  handler: {
82
82
  kind: "Builtin",
83
- builtin: { kind: "ExtractIndex", value: n },
83
+ builtin: { kind: "GetIndex", value: n },
84
84
  },
85
85
  },
86
86
  },
@@ -88,7 +88,7 @@ function readVar(n: number): Action {
88
88
  kind: "Invoke",
89
89
  handler: {
90
90
  kind: "Builtin",
91
- builtin: { kind: "ExtractIndex", value: 1 },
91
+ builtin: { kind: "GetIndex", value: 1 },
92
92
  },
93
93
  },
94
94
  ],
@@ -111,7 +111,7 @@ function readVar(n: number): Action {
111
111
  * All(...bindings, Identity),
112
112
  * ResumeHandle(r0, readVar(0),
113
113
  * ResumeHandle(r1, readVar(1),
114
- * Chain(ExtractIndex(N), body)
114
+ * Chain(GetIndex(N), body)
115
115
  * )
116
116
  * )
117
117
  * )
@@ -148,7 +148,7 @@ export function bind<TBindings extends Action[], TOut>(
148
148
  kind: "Invoke",
149
149
  handler: {
150
150
  kind: "Builtin",
151
- builtin: { kind: "ExtractIndex", value: pipelineInputIndex },
151
+ builtin: { kind: "GetIndex", value: pipelineInputIndex },
152
152
  },
153
153
  },
154
154
  rest: bodyAction,
@@ -163,7 +163,10 @@ export function bind<TBindings extends Action[], TOut>(
163
163
  }
164
164
 
165
165
  // 5. All(...bindings, identity()) → nested Handles
166
- const allActions = [...bindings.map((b) => b as Action), identity as Action];
166
+ const allActions = [
167
+ ...bindings.map((b) => b as Action),
168
+ identity() as Action,
169
+ ];
167
170
  return typedAction({
168
171
  kind: "Chain",
169
172
  first: { kind: "All", actions: allActions },
@@ -188,5 +191,5 @@ export function bind<TBindings extends Action[], TOut>(
188
191
  export function bindInput<TIn, TOut = any>(
189
192
  body: (input: VarRef<TIn>) => BodyResult<TOut>,
190
193
  ): TypedAction<TIn, TOut> {
191
- return bind([identity], ([input]) => pipe(drop, body(input)));
194
+ return bind([identity()], ([input]) => pipe(drop, body(input)));
192
195
  }
package/src/builtins.ts CHANGED
@@ -32,10 +32,12 @@ export function constant<TValue>(value: TValue): TypedAction<any, TValue> {
32
32
  // Identity — pass input through unchanged
33
33
  // ---------------------------------------------------------------------------
34
34
 
35
- export const identity: TypedAction<any, any> = typedAction({
36
- kind: "Invoke",
37
- handler: { kind: "Builtin", builtin: { kind: "Identity" } },
38
- });
35
+ export function identity<TValue = any>(): TypedAction<TValue, TValue> {
36
+ return typedAction({
37
+ kind: "Invoke",
38
+ handler: { kind: "Builtin", builtin: { kind: "Identity" } },
39
+ });
40
+ }
39
41
 
40
42
  // ---------------------------------------------------------------------------
41
43
  // Drop — discard pipeline value
@@ -93,10 +95,10 @@ export function flatten<TElement>(): TypedAction<TElement[][], TElement[]> {
93
95
  }
94
96
 
95
97
  // ---------------------------------------------------------------------------
96
- // ExtractField — extract a single field from an object
98
+ // GetField — extract a single field from an object
97
99
  // ---------------------------------------------------------------------------
98
100
 
99
- export function extractField<
101
+ export function getField<
100
102
  TObj extends Record<string, unknown>,
101
103
  TField extends keyof TObj & string,
102
104
  >(field: TField): TypedAction<TObj, TObj[TField]> {
@@ -104,23 +106,23 @@ export function extractField<
104
106
  kind: "Invoke",
105
107
  handler: {
106
108
  kind: "Builtin",
107
- builtin: { kind: "ExtractField", value: field },
109
+ builtin: { kind: "GetField", value: field },
108
110
  },
109
111
  });
110
112
  }
111
113
 
112
114
  // ---------------------------------------------------------------------------
113
- // ExtractIndex — extract a single element from an array by index
115
+ // GetIndex — extract a single element from an array by index
114
116
  // ---------------------------------------------------------------------------
115
117
 
116
- export function extractIndex<TTuple extends unknown[], TIndex extends number>(
118
+ export function getIndex<TTuple extends unknown[], TIndex extends number>(
117
119
  index: TIndex,
118
120
  ): TypedAction<TTuple, TTuple[TIndex]> {
119
121
  return typedAction({
120
122
  kind: "Invoke",
121
123
  handler: {
122
124
  kind: "Builtin",
123
- builtin: { kind: "ExtractIndex", value: index },
125
+ builtin: { kind: "GetIndex", value: index },
124
126
  },
125
127
  });
126
128
  }
@@ -201,7 +203,7 @@ export function withResource<
201
203
  const acquireAndMerge = chain(
202
204
  typedAction<TIn, [TResource, TIn]>({
203
205
  kind: "All",
204
- actions: [create as Action, identity as Action],
206
+ actions: [create as Action, identity() as Action],
205
207
  }),
206
208
  typedAction<[TResource, TIn], TResource & TIn>(mergeBuiltin),
207
209
  );
@@ -213,28 +215,28 @@ export function withResource<
213
215
  [TOut, TResource & TIn]
214
216
  >({
215
217
  kind: "All",
216
- actions: [action as Action, identity as Action],
218
+ actions: [action as Action, identity() as Action],
217
219
  });
218
220
 
219
- // Step 3: all(extractIndex(0), chain(extractIndex(1), dispose)) → [TOut, unknown]
221
+ // Step 3: all(getIndex(0), chain(getIndex(1), dispose)) → [TOut, unknown]
220
222
  const disposeAndKeepResult = typedAction<
221
223
  [TOut, TResource & TIn],
222
224
  [TOut, unknown]
223
225
  >({
224
226
  kind: "All",
225
227
  actions: [
226
- extractIndex<[TOut, TResource & TIn], 0>(0) as Action,
228
+ getIndex<[TOut, TResource & TIn], 0>(0) as Action,
227
229
  chain(
228
- extractIndex<[TOut, TResource & TIn], 1>(1),
230
+ getIndex<[TOut, TResource & TIn], 1>(1),
229
231
  dispose as Pipeable<TResource & TIn, unknown>,
230
232
  ) as Action,
231
233
  ],
232
234
  });
233
235
 
234
- // Step 4: extractIndex(0) → TOut
236
+ // Step 4: getIndex(0) → TOut
235
237
  return chain(
236
238
  chain(chain(acquireAndMerge, actionAndKeepMerged), disposeAndKeepResult),
237
- extractIndex<[TOut, unknown], 0>(0),
239
+ getIndex<[TOut, unknown], 0>(0),
238
240
  ) as TypedAction<TIn, TOut>;
239
241
  }
240
242
 
@@ -383,7 +385,7 @@ const EXTRACT_VALUE: Action = {
383
385
  kind: "Invoke",
384
386
  handler: {
385
387
  kind: "Builtin",
386
- builtin: { kind: "ExtractField", value: "value" },
388
+ builtin: { kind: "GetField", value: "value" },
387
389
  },
388
390
  };
389
391
  const DROP: Action = {
@@ -395,7 +397,7 @@ const IDENTITY: Action = {
395
397
  handler: { kind: "Builtin", builtin: { kind: "Identity" } },
396
398
  };
397
399
 
398
- /** Wrap branch cases with ExtractField("value") auto-unwrapping. */
400
+ /** Wrap branch cases with GetField("value") auto-unwrapping. */
399
401
  function optionBranch(someCaseBody: Action, noneCaseBody: Action): Action {
400
402
  return {
401
403
  kind: "Branch",
@@ -590,7 +592,7 @@ const TAG_ERR: Action = {
590
592
  handler: { kind: "Builtin", builtin: { kind: "Tag", value: "Err" } },
591
593
  };
592
594
 
593
- /** Wrap branch cases with ExtractField("value") auto-unwrapping. */
595
+ /** Wrap branch cases with GetField("value") auto-unwrapping. */
594
596
  function resultBranch(okCaseBody: Action, errCaseBody: Action): Action {
595
597
  return {
596
598
  kind: "Branch",
package/src/index.ts CHANGED
@@ -8,8 +8,8 @@ export {
8
8
  tag,
9
9
  merge,
10
10
  flatten,
11
- extractField,
12
- extractIndex,
11
+ getField,
12
+ getIndex,
13
13
  pick,
14
14
  dropResult,
15
15
  withResource,
package/src/pipe.ts CHANGED
@@ -82,7 +82,7 @@ export function pipe<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(
82
82
  ): TypedAction<PipeIn<T1>, T11>;
83
83
  export function pipe(...actions: Action[]): Action {
84
84
  if (actions.length === 0) {
85
- return identity;
85
+ return identity();
86
86
  }
87
87
  if (actions.length === 1) {
88
88
  return actions[0];
package/src/race.ts CHANGED
@@ -53,7 +53,7 @@ function breakPerform(restartHandlerId: RestartHandlerId): Action {
53
53
  *
54
54
  * Compiled form (restart+Branch, same substrate as loop/earlyReturn):
55
55
  * `Chain(Tag("Continue"),`
56
- * `RestartHandle(id, ExtractIndex(0),`
56
+ * `RestartHandle(id, GetIndex(0),`
57
57
  * `Branch({`
58
58
  * `Continue: All(Chain(a, breakPerform), Chain(b, breakPerform), ...),`
59
59
  * `Break: identity,`
package/src/recursive.ts CHANGED
@@ -7,13 +7,7 @@ import {
7
7
  } from "./ast.js";
8
8
  import { all } from "./all.js";
9
9
  import { chain } from "./chain.js";
10
- import {
11
- constant,
12
- identity,
13
- extractField,
14
- extractIndex,
15
- tag,
16
- } from "./builtins.js";
10
+ import { constant, identity, getField, getIndex, tag } from "./builtins.js";
17
11
  import { allocateResumeHandlerId } from "./effect-id.js";
18
12
 
19
13
  // ---------------------------------------------------------------------------
@@ -84,11 +78,11 @@ export function defineRecursiveFunctions<TDefs extends FunctionDef[]>(
84
78
  ...(callTokens as FunctionRefs<TDefs>),
85
79
  ) as Action[];
86
80
 
87
- // Branch cases: CallN → ExtractField("value") → bodyN
81
+ // Branch cases: CallN → GetField("value") → bodyN
88
82
  const cases: Record<string, Action> = {};
89
83
  for (let i = 0; i < bodyActions.length; i++) {
90
84
  cases[`Call${i}`] = chain(
91
- extractField("value"),
85
+ getField("value"),
92
86
  bodyActions[i] as any,
93
87
  ) as Action;
94
88
  }
@@ -98,12 +92,12 @@ export function defineRecursiveFunctions<TDefs extends FunctionDef[]>(
98
92
  const userBody = entryFn(...(callTokens as FunctionRefs<TDefs>)) as Action;
99
93
 
100
94
  return typedAction<any, TOut>(
101
- chain(all(identity, constant(UNUSED_STATE)), {
95
+ chain(all(identity(), constant(UNUSED_STATE)), {
102
96
  kind: "ResumeHandle",
103
97
  resume_handler_id: resumeHandlerId,
104
- body: chain(extractIndex(0), userBody as any) as Action,
98
+ body: chain(getIndex(0), userBody as any) as Action,
105
99
  handler: all(
106
- chain(extractIndex(0), branch(cases) as any),
100
+ chain(getIndex(0), branch(cases) as any),
107
101
  constant(UNUSED_STATE),
108
102
  ) as Action,
109
103
  } as Action) as Action,
package/src/try-catch.ts CHANGED
@@ -25,7 +25,7 @@ import { allocateRestartHandlerId } from "./effect-id.js";
25
25
  *
26
26
  * Compiled form (restart+Branch, same substrate as loop/earlyReturn):
27
27
  * `Chain(Tag("Continue"),`
28
- * `RestartHandle(id, ExtractIndex(0),`
28
+ * `RestartHandle(id, GetIndex(0),`
29
29
  * `Branch({ Continue: body, Break: recovery })))`
30
30
  *
31
31
  * throwError = `Chain(Tag("Break"), RestartPerform(id))`