@barnum/barnum 0.2.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/cli.cjs +33 -0
- package/dist/all.d.ts +43 -0
- package/dist/all.d.ts.map +1 -0
- package/dist/all.js +8 -0
- package/dist/ast.d.ts +476 -0
- package/dist/ast.d.ts.map +1 -0
- package/dist/ast.js +419 -0
- package/dist/bind.d.ts +59 -0
- package/dist/bind.d.ts.map +1 -0
- package/dist/bind.js +69 -0
- package/dist/builtins/array.d.ts +36 -0
- package/dist/builtins/array.d.ts.map +1 -0
- package/dist/builtins/array.js +93 -0
- package/dist/builtins/index.d.ts +6 -0
- package/dist/builtins/index.d.ts.map +1 -0
- package/dist/builtins/index.js +5 -0
- package/dist/builtins/scalar.d.ts +12 -0
- package/dist/builtins/scalar.d.ts.map +1 -0
- package/dist/builtins/scalar.js +41 -0
- package/dist/builtins/struct.d.ts +25 -0
- package/dist/builtins/struct.d.ts.map +1 -0
- package/dist/builtins/struct.js +67 -0
- package/dist/builtins/tagged-union.d.ts +54 -0
- package/dist/builtins/tagged-union.d.ts.map +1 -0
- package/dist/builtins/tagged-union.js +81 -0
- package/dist/builtins/with-resource.d.ts +23 -0
- package/dist/builtins/with-resource.d.ts.map +1 -0
- package/dist/builtins/with-resource.js +35 -0
- package/dist/chain.d.ts +3 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +8 -0
- package/dist/effect-id.d.ts +15 -0
- package/dist/effect-id.d.ts.map +1 -0
- package/dist/effect-id.js +16 -0
- package/dist/handler.d.ts +51 -0
- package/dist/handler.d.ts.map +1 -0
- package/dist/handler.js +130 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/iterator.d.ts +32 -0
- package/dist/iterator.d.ts.map +1 -0
- package/dist/iterator.js +123 -0
- package/dist/option.d.ts +74 -0
- package/dist/option.d.ts.map +1 -0
- package/dist/option.js +141 -0
- package/dist/pipe.d.ts +12 -0
- package/dist/pipe.d.ts.map +1 -0
- package/dist/pipe.js +12 -0
- package/dist/race.d.ts +54 -0
- package/dist/race.d.ts.map +1 -0
- package/dist/race.js +116 -0
- package/dist/recursive.d.ts +40 -0
- package/dist/recursive.d.ts.map +1 -0
- package/dist/recursive.js +58 -0
- package/dist/result.d.ts +50 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +117 -0
- package/dist/run.d.ts +14 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +160 -0
- package/dist/runtime.d.ts +6 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +7 -0
- package/dist/schema.d.ts +9 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +95 -0
- package/dist/schemas.d.ts +5 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +13 -0
- package/dist/try-catch.d.ts +24 -0
- package/dist/try-catch.d.ts.map +1 -0
- package/dist/try-catch.js +37 -0
- package/dist/values.d.ts +6 -0
- package/dist/values.d.ts.map +1 -0
- package/dist/values.js +12 -0
- package/dist/worker.d.ts +15 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +58 -0
- package/package.json +42 -16
- package/src/all.ts +133 -0
- package/src/ast.ts +1301 -0
- package/src/bind.ts +162 -0
- package/src/builtins/array.ts +121 -0
- package/src/builtins/index.ts +17 -0
- package/src/builtins/scalar.ts +49 -0
- package/src/builtins/struct.ts +111 -0
- package/src/builtins/tagged-union.ts +142 -0
- package/src/builtins/with-resource.ts +69 -0
- package/src/chain.ts +17 -0
- package/src/effect-id.ts +30 -0
- package/src/handler.ts +263 -0
- package/src/index.ts +37 -0
- package/src/iterator.ts +243 -0
- package/src/option.ts +199 -0
- package/src/pipe.ts +138 -0
- package/src/race.ts +173 -0
- package/src/recursive.ts +129 -0
- package/src/result.ts +168 -0
- package/src/run.ts +209 -0
- package/src/runtime.ts +16 -0
- package/src/schema.ts +118 -0
- package/src/schemas.ts +21 -0
- package/src/try-catch.ts +57 -0
- package/src/values.ts +21 -0
- package/src/worker.ts +71 -0
- package/README.md +0 -19
- package/barnum-config-schema.json +0 -408
- package/cli.js +0 -20
- package/index.js +0 -23
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { constant, identity, drop, panic } from "./scalar.js";
|
|
2
|
+
export { getField, wrapInField, merge, pick, allObject } from "./struct.js";
|
|
3
|
+
export { getIndex, flatten, splitFirst, splitLast, slice, range, } from "./array.js";
|
|
4
|
+
export { tag, extractPrefix, asOption, taggedUnionSchema, } from "./tagged-union.js";
|
|
5
|
+
export { withResource } from "./with-resource.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builtins/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EACL,QAAQ,EACR,OAAO,EACP,UAAU,EACV,SAAS,EACT,KAAK,EACL,KAAK,GACN,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,GAAG,EACH,aAAa,EACb,QAAQ,EACR,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { constant, identity, drop, panic } from "./scalar.js";
|
|
2
|
+
export { getField, wrapInField, merge, pick, allObject } from "./struct.js";
|
|
3
|
+
export { getIndex, flatten, splitFirst, splitLast, slice, range, } from "./array.js";
|
|
4
|
+
export { tag, extractPrefix, asOption, taggedUnionSchema, } from "./tagged-union.js";
|
|
5
|
+
export { withResource } from "./with-resource.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type TypedAction } from "../ast.js";
|
|
2
|
+
export declare function constant<TValue>(value: TValue): TypedAction<any, TValue>;
|
|
3
|
+
export declare function identity<TValue = any>(): TypedAction<TValue, TValue>;
|
|
4
|
+
export declare const drop: TypedAction<any, void>;
|
|
5
|
+
/**
|
|
6
|
+
* Halt execution with a fatal error. Not caught by tryCatch.
|
|
7
|
+
* Analogous to Rust's `panic!`.
|
|
8
|
+
*
|
|
9
|
+
* Output type is `never` — a panic never produces a value.
|
|
10
|
+
*/
|
|
11
|
+
export declare function panic(message: string): TypedAction<any, never>;
|
|
12
|
+
//# sourceMappingURL=scalar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scalar.d.ts","sourceRoot":"","sources":["../../src/builtins/scalar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAe,MAAM,WAAW,CAAC;AAM1D,wBAAgB,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,CAKxE;AAMD,wBAAgB,QAAQ,CAAC,MAAM,GAAG,GAAG,KAAK,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAKpE;AAMD,eAAO,MAAM,IAAI,EAAE,WAAW,CAAC,GAAG,EAAE,IAAI,CAGtC,CAAC;AAMH;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC,CAK9D"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { typedAction } from "../ast.js";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// Constant — produce a fixed value (takes no pipeline input)
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
export function constant(value) {
|
|
6
|
+
return typedAction({
|
|
7
|
+
kind: "Invoke",
|
|
8
|
+
handler: { kind: "Builtin", builtin: { kind: "Constant", value } },
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Identity — pass input through unchanged
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
export function identity() {
|
|
15
|
+
return typedAction({
|
|
16
|
+
kind: "Invoke",
|
|
17
|
+
handler: { kind: "Builtin", builtin: { kind: "Identity" } },
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Drop — discard pipeline value
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
export const drop = typedAction({
|
|
24
|
+
kind: "Invoke",
|
|
25
|
+
handler: { kind: "Builtin", builtin: { kind: "Drop" } },
|
|
26
|
+
});
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Panic — halt execution with an error message
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
/**
|
|
31
|
+
* Halt execution with a fatal error. Not caught by tryCatch.
|
|
32
|
+
* Analogous to Rust's `panic!`.
|
|
33
|
+
*
|
|
34
|
+
* Output type is `never` — a panic never produces a value.
|
|
35
|
+
*/
|
|
36
|
+
export function panic(message) {
|
|
37
|
+
return typedAction({
|
|
38
|
+
kind: "Invoke",
|
|
39
|
+
handler: { kind: "Builtin", builtin: { kind: "Panic", message } },
|
|
40
|
+
});
|
|
41
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ExtractOutput, type MergeTuple, type Pipeable, type TypedAction } from "../ast.js";
|
|
2
|
+
export declare function getField<TObj extends Record<string, unknown>, TField extends keyof TObj & string>(field: TField): TypedAction<TObj, TObj[TField]>;
|
|
3
|
+
export declare function wrapInField<TField extends string, TValue>(field: TField): TypedAction<TValue, Record<TField, TValue>>;
|
|
4
|
+
export declare function merge<TTuple extends Record<string, unknown>[]>(): TypedAction<TTuple, MergeTuple<TTuple>>;
|
|
5
|
+
export declare function pick<TObj extends Record<string, unknown>, TKeys extends (keyof TObj & string)[]>(...keys: TKeys): TypedAction<TObj, Pick<TObj, TKeys[number]>>;
|
|
6
|
+
/**
|
|
7
|
+
* Run named actions concurrently on the same input, collecting results
|
|
8
|
+
* into an object with matching keys.
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* allObject({
|
|
12
|
+
* files: listFiles,
|
|
13
|
+
* config: loadConfig,
|
|
14
|
+
* })
|
|
15
|
+
* // TIn → { files: string[], config: Config }
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* Each action receives the pipeline input. Results are wrapped in
|
|
19
|
+
* `{ key: value }` via `wrapInField`, run concurrently via `All`,
|
|
20
|
+
* then merged into a single object.
|
|
21
|
+
*/
|
|
22
|
+
export declare function allObject<TActions extends Record<string, Pipeable<any, any>>>(actions: TActions): TypedAction<any, {
|
|
23
|
+
[K in keyof TActions & string]: ExtractOutput<TActions[K]>;
|
|
24
|
+
}>;
|
|
25
|
+
//# sourceMappingURL=struct.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"struct.d.ts","sourceRoot":"","sources":["../../src/builtins/struct.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,WAAW,EAGjB,MAAM,WAAW,CAAC;AAOnB,wBAAgB,QAAQ,CACtB,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,MAAM,SAAS,MAAM,IAAI,GAAG,MAAM,EAClC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAQhD;AAMD,wBAAgB,WAAW,CAAC,MAAM,SAAS,MAAM,EAAE,MAAM,EACvD,KAAK,EAAE,MAAM,GACZ,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAQ7C;AAMD,wBAAgB,KAAK,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,WAAW,CAC5E,MAAM,EACN,UAAU,CAAC,MAAM,CAAC,CACnB,CAKA;AAMD,wBAAgB,IAAI,CAClB,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,KAAK,SAAS,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,EACrC,GAAG,IAAI,EAAE,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAS9D;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,EAC3E,OAAO,EAAE,QAAQ,GAChB,WAAW,CACZ,GAAG,EACH;KAAG,CAAC,IAAI,MAAM,QAAQ,GAAG,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;CAAE,CAC/D,CASA"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { toAction, typedAction, } from "../ast.js";
|
|
2
|
+
import { chain } from "../chain.js";
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// GetField — extract a single field from an object
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
export function getField(field) {
|
|
7
|
+
return typedAction({
|
|
8
|
+
kind: "Invoke",
|
|
9
|
+
handler: {
|
|
10
|
+
kind: "Builtin",
|
|
11
|
+
builtin: { kind: "GetField", field },
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// WrapInField — wrap input as { <field>: <input> }
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
export function wrapInField(field) {
|
|
19
|
+
return typedAction({
|
|
20
|
+
kind: "Invoke",
|
|
21
|
+
handler: {
|
|
22
|
+
kind: "Builtin",
|
|
23
|
+
builtin: { kind: "WrapInField", field },
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Merge — merge a tuple of objects into a single object
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
export function merge() {
|
|
31
|
+
return typedAction({
|
|
32
|
+
kind: "Invoke",
|
|
33
|
+
handler: { kind: "Builtin", builtin: { kind: "Merge" } },
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Pick — select named fields from an object
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
export function pick(...keys) {
|
|
40
|
+
const actions = keys.map((key) => toAction(chain(toAction(getField(key)), toAction(wrapInField(key)))));
|
|
41
|
+
const allAction = { kind: "All", actions };
|
|
42
|
+
return chain(toAction(allAction), toAction(merge()));
|
|
43
|
+
}
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
// AllObject — run named actions concurrently, collect into an object
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
/**
|
|
48
|
+
* Run named actions concurrently on the same input, collecting results
|
|
49
|
+
* into an object with matching keys.
|
|
50
|
+
*
|
|
51
|
+
* ```ts
|
|
52
|
+
* allObject({
|
|
53
|
+
* files: listFiles,
|
|
54
|
+
* config: loadConfig,
|
|
55
|
+
* })
|
|
56
|
+
* // TIn → { files: string[], config: Config }
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* Each action receives the pipeline input. Results are wrapped in
|
|
60
|
+
* `{ key: value }` via `wrapInField`, run concurrently via `All`,
|
|
61
|
+
* then merged into a single object.
|
|
62
|
+
*/
|
|
63
|
+
export function allObject(actions) {
|
|
64
|
+
const wrapped = Object.entries(actions).map(([key, action]) => toAction(chain(action, wrapInField(key))));
|
|
65
|
+
const allAction = { kind: "All", actions: wrapped };
|
|
66
|
+
return chain(toAction(allAction), toAction(merge()));
|
|
67
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type Option, type TaggedUnion, type TypedAction } from "../ast.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
/**
|
|
4
|
+
* Wrap input as a tagged union member. Requires the full variant map TDef
|
|
5
|
+
* so the output type carries __def for branch decomposition.
|
|
6
|
+
*
|
|
7
|
+
* Usage: tag<{ Ok: string; Err: number }, "Ok">("Ok")
|
|
8
|
+
* input: string → output: TaggedUnion<{ Ok: string; Err: number }>
|
|
9
|
+
*/
|
|
10
|
+
export declare function tag<TEnumName extends string, TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(kind: TKind, enumName: TEnumName): TypedAction<TDef[TKind], TaggedUnion<TEnumName, TDef>>;
|
|
11
|
+
/**
|
|
12
|
+
* Extract the enum prefix from a tagged value's `kind` field.
|
|
13
|
+
*
|
|
14
|
+
* Input: `{ kind: "Result.Ok", value: 42 }`
|
|
15
|
+
* Output: `{ kind: "Result", value: { kind: "Result.Ok", value: 42 } }`
|
|
16
|
+
*
|
|
17
|
+
* If `kind` contains no `'.'`, the entire kind string becomes the prefix.
|
|
18
|
+
* Used internally by `branchFamily` for two-level dispatch.
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractPrefix(): TypedAction;
|
|
21
|
+
/**
|
|
22
|
+
* Convert a boolean to `Option<void>`.
|
|
23
|
+
*
|
|
24
|
+
* `true` → `{ kind: "Option.Some", value: null }`
|
|
25
|
+
* `false` → `{ kind: "Option.None", value: null }`
|
|
26
|
+
*/
|
|
27
|
+
export declare function asOption(): TypedAction<boolean, Option<void>>;
|
|
28
|
+
/**
|
|
29
|
+
* Reverse of VoidToNull: maps `null` back to `void` in the def so that
|
|
30
|
+
* `taggedUnionSchema({ Clean: z.null() })` produces the same phantom __def
|
|
31
|
+
* as `TaggedUnion<{ Clean: void }>`.
|
|
32
|
+
*/
|
|
33
|
+
type NullToVoid<TDef> = {
|
|
34
|
+
[K in keyof TDef]: TDef[K] extends null ? void : TDef[K];
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Build a Zod schema for a `TaggedUnion<TEnumName, TDef>` — a discriminated
|
|
38
|
+
* union of `{ kind: "EnumName.Variant"; value: V }` objects.
|
|
39
|
+
*
|
|
40
|
+
* Each key in `cases` becomes a variant with a namespaced kind string.
|
|
41
|
+
* Use `z.null()` for void variants.
|
|
42
|
+
*
|
|
43
|
+
* ```ts
|
|
44
|
+
* const schema = taggedUnionSchema("ClassifyResult", {
|
|
45
|
+
* HasErrors: z.array(TypeErrorValidator),
|
|
46
|
+
* Clean: z.null(),
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function taggedUnionSchema<TEnumName extends string, TDef extends Record<string, z.ZodTypeAny>>(enumName: TEnumName, cases: TDef): z.ZodType<TaggedUnion<TEnumName, NullToVoid<{
|
|
51
|
+
[K in keyof TDef & string]: z.infer<TDef[K]>;
|
|
52
|
+
}>>>;
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=tagged-union.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tagged-union.d.ts","sourceRoot":"","sources":["../../src/builtins/tagged-union.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,WAAW,EAChB,KAAK,WAAW,EAGjB,MAAM,WAAW,CAAC;AAKnB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;;;;;GAMG;AACH,wBAAgB,GAAG,CACjB,SAAS,SAAS,MAAM,EACxB,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,KAAK,SAAS,MAAM,IAAI,GAAG,MAAM,EAEjC,IAAI,EAAE,KAAK,EACX,QAAQ,EAAE,SAAS,GAClB,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAcxD;AAMD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,IAAI,WAAW,CAK3C;AAMD;;;;;GAKG;AACH,wBAAgB,QAAQ,IAAI,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAK7D;AAMD;;;;GAIG;AACH,KAAK,UAAU,CAAC,IAAI,IAAI;KACrB,CAAC,IAAI,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC;CACzD,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,SAAS,MAAM,EACxB,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,EAEzC,QAAQ,EAAE,SAAS,EACnB,KAAK,EAAE,IAAI,GACV,CAAC,CAAC,OAAO,CACV,WAAW,CACT,SAAS,EACT,UAAU,CAAC;KAAG,CAAC,IAAI,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC,CAC7D,CACF,CAmBA"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { toAction, typedAction, } from "../ast.js";
|
|
2
|
+
import { chain } from "../chain.js";
|
|
3
|
+
import { all } from "../all.js";
|
|
4
|
+
import { constant } from "./scalar.js";
|
|
5
|
+
import { wrapInField, merge } from "./struct.js";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Tag — wrap input as a tagged union variant
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
/**
|
|
11
|
+
* Wrap input as a tagged union member. Requires the full variant map TDef
|
|
12
|
+
* so the output type carries __def for branch decomposition.
|
|
13
|
+
*
|
|
14
|
+
* Usage: tag<{ Ok: string; Err: number }, "Ok">("Ok")
|
|
15
|
+
* input: string → output: TaggedUnion<{ Ok: string; Err: number }>
|
|
16
|
+
*/
|
|
17
|
+
export function tag(kind, enumName) {
|
|
18
|
+
const namespacedKind = `${enumName}.${kind}`;
|
|
19
|
+
return chain(toAction(all(chain(toAction(constant(namespacedKind)), toAction(wrapInField("kind"))), wrapInField("value"))), toAction(merge()));
|
|
20
|
+
}
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// ExtractPrefix — extract enum prefix from tagged value kind
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
/**
|
|
25
|
+
* Extract the enum prefix from a tagged value's `kind` field.
|
|
26
|
+
*
|
|
27
|
+
* Input: `{ kind: "Result.Ok", value: 42 }`
|
|
28
|
+
* Output: `{ kind: "Result", value: { kind: "Result.Ok", value: 42 } }`
|
|
29
|
+
*
|
|
30
|
+
* If `kind` contains no `'.'`, the entire kind string becomes the prefix.
|
|
31
|
+
* Used internally by `branchFamily` for two-level dispatch.
|
|
32
|
+
*/
|
|
33
|
+
export function extractPrefix() {
|
|
34
|
+
return typedAction({
|
|
35
|
+
kind: "Invoke",
|
|
36
|
+
handler: { kind: "Builtin", builtin: { kind: "ExtractPrefix" } },
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// AsOption — convert boolean to Option<void>
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
/**
|
|
43
|
+
* Convert a boolean to `Option<void>`.
|
|
44
|
+
*
|
|
45
|
+
* `true` → `{ kind: "Option.Some", value: null }`
|
|
46
|
+
* `false` → `{ kind: "Option.None", value: null }`
|
|
47
|
+
*/
|
|
48
|
+
export function asOption() {
|
|
49
|
+
return typedAction({
|
|
50
|
+
kind: "Invoke",
|
|
51
|
+
handler: { kind: "Builtin", builtin: { kind: "AsOption" } },
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build a Zod schema for a `TaggedUnion<TEnumName, TDef>` — a discriminated
|
|
56
|
+
* union of `{ kind: "EnumName.Variant"; value: V }` objects.
|
|
57
|
+
*
|
|
58
|
+
* Each key in `cases` becomes a variant with a namespaced kind string.
|
|
59
|
+
* Use `z.null()` for void variants.
|
|
60
|
+
*
|
|
61
|
+
* ```ts
|
|
62
|
+
* const schema = taggedUnionSchema("ClassifyResult", {
|
|
63
|
+
* HasErrors: z.array(TypeErrorValidator),
|
|
64
|
+
* Clean: z.null(),
|
|
65
|
+
* });
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export function taggedUnionSchema(enumName, cases) {
|
|
69
|
+
const variants = Object.entries(cases).map(([kind, valueSchema]) => z.object({ kind: z.literal(`${enumName}.${kind}`), value: valueSchema }));
|
|
70
|
+
if (variants.length === 0) {
|
|
71
|
+
return z.never();
|
|
72
|
+
}
|
|
73
|
+
if (variants.length === 1) {
|
|
74
|
+
return variants[0];
|
|
75
|
+
}
|
|
76
|
+
return z.discriminatedUnion("kind", [
|
|
77
|
+
variants[0],
|
|
78
|
+
variants[1],
|
|
79
|
+
...variants.slice(2),
|
|
80
|
+
]);
|
|
81
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type Pipeable, type TypedAction } from "../ast.js";
|
|
2
|
+
/**
|
|
3
|
+
* RAII-style resource management combinator.
|
|
4
|
+
*
|
|
5
|
+
* Runs `create` to acquire a resource, then merges the resource with the
|
|
6
|
+
* original input into a flat object (`TResource & TIn`) for the action.
|
|
7
|
+
* After the action completes, `dispose` receives the resource for cleanup.
|
|
8
|
+
* The overall combinator returns the action's output.
|
|
9
|
+
*
|
|
10
|
+
* ```
|
|
11
|
+
* TIn → create → TResource
|
|
12
|
+
* → merge(TResource, TIn) → TResource & TIn
|
|
13
|
+
* → action(TResource & TIn) → TOut
|
|
14
|
+
* → dispose(TResource) → (discarded)
|
|
15
|
+
* → TOut
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function withResource<TIn extends Record<string, unknown>, TResource extends Record<string, unknown>, TOut, TDisposeOut = unknown>({ create, action, dispose, }: {
|
|
19
|
+
create: Pipeable<TIn, TResource>;
|
|
20
|
+
action: Pipeable<TResource & TIn, TOut>;
|
|
21
|
+
dispose: Pipeable<TResource, TDisposeOut>;
|
|
22
|
+
}): TypedAction<TIn, TOut>;
|
|
23
|
+
//# sourceMappingURL=with-resource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-resource.d.ts","sourceRoot":"","sources":["../../src/builtins/with-resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAY,MAAM,WAAW,CAAC;AAWtE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAC1B,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzC,IAAI,EACJ,WAAW,GAAG,OAAO,EACrB,EACA,MAAM,EACN,MAAM,EACN,OAAO,GACR,EAAE;IACD,MAAM,EAAE,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACjC,MAAM,EAAE,QAAQ,CAAC,SAAS,GAAG,GAAG,EAAE,IAAI,CAAC,CAAC;IACxC,OAAO,EAAE,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;CAC3C,GAAG,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CA4BzB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { toAction } from "../ast.js";
|
|
2
|
+
import { chain } from "../chain.js";
|
|
3
|
+
import { all } from "../all.js";
|
|
4
|
+
import { identity } from "./scalar.js";
|
|
5
|
+
import { merge } from "./struct.js";
|
|
6
|
+
import { getIndex } from "./array.js";
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// WithResource — RAII-style create/action/dispose
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
/**
|
|
11
|
+
* RAII-style resource management combinator.
|
|
12
|
+
*
|
|
13
|
+
* Runs `create` to acquire a resource, then merges the resource with the
|
|
14
|
+
* original input into a flat object (`TResource & TIn`) for the action.
|
|
15
|
+
* After the action completes, `dispose` receives the resource for cleanup.
|
|
16
|
+
* The overall combinator returns the action's output.
|
|
17
|
+
*
|
|
18
|
+
* ```
|
|
19
|
+
* TIn → create → TResource
|
|
20
|
+
* → merge(TResource, TIn) → TResource & TIn
|
|
21
|
+
* → action(TResource & TIn) → TOut
|
|
22
|
+
* → dispose(TResource) → (discarded)
|
|
23
|
+
* → TOut
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function withResource({ create, action, dispose, }) {
|
|
27
|
+
// Step 1: all(create, identity) → [TResource, TIn] → merge → TResource & TIn
|
|
28
|
+
const acquireAndMerge = chain(toAction(all(create, identity())), toAction(merge()));
|
|
29
|
+
// Step 2: all(action, identity) → [TOut, TResource & TIn]
|
|
30
|
+
const actionAndKeepMerged = all(toAction(action), toAction(identity()));
|
|
31
|
+
// Step 3: all(getIndex(0).unwrap(), chain(getIndex(1).unwrap(), dispose)) → [TOut, unknown]
|
|
32
|
+
const disposeAndKeepResult = all(toAction(getIndex(0).unwrap()), chain(toAction(getIndex(1).unwrap()), toAction(dispose)));
|
|
33
|
+
// Step 4: getIndex(0).unwrap() → TOut
|
|
34
|
+
return chain(toAction(chain(toAction(chain(toAction(acquireAndMerge), toAction(actionAndKeepMerged))), toAction(disposeAndKeepResult))), toAction(getIndex(0).unwrap()));
|
|
35
|
+
}
|
package/dist/chain.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain.d.ts","sourceRoot":"","sources":["../src/chain.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,WAAW,EAGjB,MAAM,UAAU,CAAC;AAElB,wBAAgB,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAC9B,KAAK,EAAE,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,EACvB,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,GACrB,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,CAMrB"}
|
package/dist/chain.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Branded ID for resume-style effect handlers. */
|
|
2
|
+
export type ResumeHandlerId = number & {
|
|
3
|
+
readonly __resumeHandlerBrand: unique symbol;
|
|
4
|
+
};
|
|
5
|
+
/** Branded ID for restart-style effect handlers. */
|
|
6
|
+
export type RestartHandlerId = number & {
|
|
7
|
+
readonly __restartHandlerBrand: unique symbol;
|
|
8
|
+
};
|
|
9
|
+
/** Allocate a fresh, unique resume handler ID. */
|
|
10
|
+
export declare function allocateResumeHandlerId(): ResumeHandlerId;
|
|
11
|
+
/** Allocate a fresh, unique restart handler ID. */
|
|
12
|
+
export declare function allocateRestartHandlerId(): RestartHandlerId;
|
|
13
|
+
/** Reset the ID counter. For test isolation only. */
|
|
14
|
+
export declare function resetEffectIdCounter(): void;
|
|
15
|
+
//# sourceMappingURL=effect-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effect-id.d.ts","sourceRoot":"","sources":["../src/effect-id.ts"],"names":[],"mappings":"AAIA,mDAAmD;AACnD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG;IACrC,QAAQ,CAAC,oBAAoB,EAAE,OAAO,MAAM,CAAC;CAC9C,CAAC;AAEF,oDAAoD;AACpD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG;IACtC,QAAQ,CAAC,qBAAqB,EAAE,OAAO,MAAM,CAAC;CAC/C,CAAC;AAIF,kDAAkD;AAClD,wBAAgB,uBAAuB,IAAI,eAAe,CAEzD;AAED,mDAAmD;AACnD,wBAAgB,wBAAwB,IAAI,gBAAgB,CAE3D;AAED,qDAAqD;AACrD,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Shared effect ID counter for gensym'd effect identifiers
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
let nextId = 0;
|
|
5
|
+
/** Allocate a fresh, unique resume handler ID. */
|
|
6
|
+
export function allocateResumeHandlerId() {
|
|
7
|
+
return nextId++;
|
|
8
|
+
}
|
|
9
|
+
/** Allocate a fresh, unique restart handler ID. */
|
|
10
|
+
export function allocateRestartHandlerId() {
|
|
11
|
+
return nextId++;
|
|
12
|
+
}
|
|
13
|
+
/** Reset the ID counter. For test isolation only. */
|
|
14
|
+
export function resetEffectIdCounter() {
|
|
15
|
+
nextId = 0;
|
|
16
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import { type TypedAction } from "./ast.js";
|
|
3
|
+
export interface HandlerDefinition<TValue = unknown, TOutput = unknown, TStepConfig = unknown> {
|
|
4
|
+
inputValidator?: z.ZodType<TValue>;
|
|
5
|
+
outputValidator?: z.ZodType<TOutput>;
|
|
6
|
+
stepConfigValidator?: z.ZodType<TStepConfig>;
|
|
7
|
+
handle: (context: {
|
|
8
|
+
value: TValue;
|
|
9
|
+
stepConfig: TStepConfig;
|
|
10
|
+
}) => Promise<TOutput>;
|
|
11
|
+
}
|
|
12
|
+
/** Runtime-only handler definition shape — erases generic type info. */
|
|
13
|
+
interface UntypedHandlerDefinition {
|
|
14
|
+
inputValidator?: z.ZodType;
|
|
15
|
+
outputValidator?: z.ZodType;
|
|
16
|
+
stepConfigValidator?: z.ZodType;
|
|
17
|
+
handle: (...args: any[]) => Promise<unknown>;
|
|
18
|
+
}
|
|
19
|
+
declare const HANDLER_BRAND: unique symbol;
|
|
20
|
+
/**
|
|
21
|
+
* Opaque handler reference with typed metadata. The `__definition` property
|
|
22
|
+
* is non-enumerable — invisible to `JSON.stringify`, visible to the worker.
|
|
23
|
+
*/
|
|
24
|
+
export type Handler<TValue = unknown, TOutput = unknown> = TypedAction<TValue, TOutput> & {
|
|
25
|
+
readonly [HANDLER_BRAND]: true;
|
|
26
|
+
readonly __definition: UntypedHandlerDefinition;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Handlers that return `Promise<void>` produce `void` output (null at
|
|
30
|
+
* runtime). This is honest — the handler completes and returns nothing
|
|
31
|
+
* useful, but execution continues.
|
|
32
|
+
*/
|
|
33
|
+
type HandlerOutput<TOutput> = [TOutput] extends [void] ? void : TOutput;
|
|
34
|
+
export declare function createHandler<TValue = void, TOutput = unknown>(definition: {
|
|
35
|
+
inputValidator?: z.ZodType<TValue>;
|
|
36
|
+
outputValidator?: z.ZodType<NoInfer<TOutput>>;
|
|
37
|
+
handle: (context: {
|
|
38
|
+
value: TValue;
|
|
39
|
+
}) => Promise<TOutput>;
|
|
40
|
+
}, exportName?: string): Handler<TValue, HandlerOutput<TOutput>>;
|
|
41
|
+
export declare function createHandlerWithConfig<TValue = void, TOutput = unknown, TStepConfig = unknown>(definition: {
|
|
42
|
+
inputValidator?: z.ZodType<TValue>;
|
|
43
|
+
outputValidator?: z.ZodType<NoInfer<TOutput>>;
|
|
44
|
+
stepConfigValidator?: z.ZodType<TStepConfig>;
|
|
45
|
+
handle: (context: {
|
|
46
|
+
value: TValue;
|
|
47
|
+
stepConfig: TStepConfig;
|
|
48
|
+
}) => Promise<TOutput>;
|
|
49
|
+
}, exportName?: string): (config: TStepConfig) => TypedAction<TValue, HandlerOutput<TOutput>>;
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../src/handler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,KAAK,WAAW,EAAyB,MAAM,UAAU,CAAC;AAUnE,MAAM,WAAW,iBAAiB,CAChC,MAAM,GAAG,OAAO,EAChB,OAAO,GAAG,OAAO,EACjB,WAAW,GAAG,OAAO;IAErB,cAAc,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,eAAe,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,mBAAmB,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,EAAE,CAAC,OAAO,EAAE;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,WAAW,CAAC;KACzB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxB;AAED,wEAAwE;AACxE,UAAU,wBAAwB;IAChC,cAAc,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;IAC3B,eAAe,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;IAEhC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9C;AAMD,QAAA,MAAM,aAAa,eAA+B,CAAC;AAEnD;;;GAGG;AACH,MAAM,MAAM,OAAO,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,WAAW,CACpE,MAAM,EACN,OAAO,CACR,GAAG;IACF,QAAQ,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,wBAAwB,CAAC;CACjD,CAAC;AAwCF;;;;GAIG;AACH,KAAK,aAAa,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC;AAMxE,wBAAgB,aAAa,CAAC,MAAM,GAAG,IAAI,EAAE,OAAO,GAAG,OAAO,EAC5D,UAAU,EAAE;IACV,cAAc,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,eAAe,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9C,MAAM,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1D,EACD,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;AAoD3C,wBAAgB,uBAAuB,CACrC,MAAM,GAAG,IAAI,EACb,OAAO,GAAG,OAAO,EACjB,WAAW,GAAG,OAAO,EAErB,UAAU,EAAE;IACV,cAAc,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,eAAe,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9C,mBAAmB,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,EAAE,CAAC,OAAO,EAAE;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,WAAW,CAAC;KACzB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxB,EACD,UAAU,CAAC,EAAE,MAAM,GAClB,CAAC,MAAM,EAAE,WAAW,KAAK,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC"}
|
package/dist/handler.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { toAction, typedAction } from "./ast.js";
|
|
3
|
+
import { chain } from "./chain.js";
|
|
4
|
+
import { all } from "./all.js";
|
|
5
|
+
import { constant, identity } from "./builtins/index.js";
|
|
6
|
+
import { zodToCheckedJsonSchema } from "./schema.js";
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Handler — opaque typed handler reference
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
const HANDLER_BRAND = Symbol.for("barnum:handler");
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// getCallerFilePath
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
/**
|
|
15
|
+
* Deduces the caller's file path from the V8 stack trace API.
|
|
16
|
+
* Frame 0 = getCallerFilePath, Frame 1 = createHandler, Frame 2 = the caller.
|
|
17
|
+
*/
|
|
18
|
+
function getCallerFilePath() {
|
|
19
|
+
const original = Error.prepareStackTrace;
|
|
20
|
+
let callerFile;
|
|
21
|
+
Error.prepareStackTrace = (_err, stack) => {
|
|
22
|
+
const frame = stack[2];
|
|
23
|
+
callerFile = frame?.getFileName() ?? undefined;
|
|
24
|
+
return "";
|
|
25
|
+
};
|
|
26
|
+
const err = new Error("stack trace capture");
|
|
27
|
+
void err.stack;
|
|
28
|
+
Error.prepareStackTrace = original;
|
|
29
|
+
if (!callerFile) {
|
|
30
|
+
throw new Error("createHandler: could not determine caller file path from stack trace.");
|
|
31
|
+
}
|
|
32
|
+
if (callerFile.startsWith("file://")) {
|
|
33
|
+
return fileURLToPath(callerFile);
|
|
34
|
+
}
|
|
35
|
+
return callerFile;
|
|
36
|
+
}
|
|
37
|
+
// Implementation
|
|
38
|
+
export function createHandler(definition, exportName) {
|
|
39
|
+
const filePath = getCallerFilePath();
|
|
40
|
+
const funcName = exportName ?? "default";
|
|
41
|
+
const inputSchema = definition.inputValidator
|
|
42
|
+
? zodToCheckedJsonSchema(definition.inputValidator, `${filePath}:${funcName} input`)
|
|
43
|
+
: undefined;
|
|
44
|
+
const outputSchema = definition.outputValidator
|
|
45
|
+
? zodToCheckedJsonSchema(definition.outputValidator, `${filePath}:${funcName} output`)
|
|
46
|
+
: undefined;
|
|
47
|
+
const action = typedAction({
|
|
48
|
+
kind: "Invoke",
|
|
49
|
+
handler: {
|
|
50
|
+
kind: "TypeScript",
|
|
51
|
+
module: filePath,
|
|
52
|
+
func: funcName,
|
|
53
|
+
...(inputSchema && { input_schema: inputSchema }),
|
|
54
|
+
...(outputSchema && { output_schema: outputSchema }),
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
// Non-enumerable: invisible to JSON.stringify, visible to the worker
|
|
58
|
+
Object.defineProperty(action, HANDLER_BRAND, {
|
|
59
|
+
value: true,
|
|
60
|
+
enumerable: false,
|
|
61
|
+
});
|
|
62
|
+
Object.defineProperty(action, "__definition", {
|
|
63
|
+
value: definition,
|
|
64
|
+
enumerable: false,
|
|
65
|
+
});
|
|
66
|
+
return action;
|
|
67
|
+
}
|
|
68
|
+
// Implementation
|
|
69
|
+
export function createHandlerWithConfig(definition, exportName) {
|
|
70
|
+
const filePath = getCallerFilePath();
|
|
71
|
+
const funcName = exportName ?? "default";
|
|
72
|
+
// The invoke receives [value, config] from All(Identity, Constant(config)).
|
|
73
|
+
// Build a tuple schema manually — the Rust engine doesn't support draft-07
|
|
74
|
+
// array-form `items` for tuples, so use `prefixItems` (2020-12 style).
|
|
75
|
+
const valueSchema = definition.inputValidator
|
|
76
|
+
? zodToCheckedJsonSchema(definition.inputValidator, `${filePath}:${funcName} input`)
|
|
77
|
+
: {};
|
|
78
|
+
const configSchema = definition.stepConfigValidator
|
|
79
|
+
? zodToCheckedJsonSchema(definition.stepConfigValidator, `${filePath}:${funcName} stepConfig`)
|
|
80
|
+
: {};
|
|
81
|
+
const inputSchema = {
|
|
82
|
+
type: "array",
|
|
83
|
+
prefixItems: [valueSchema, configSchema],
|
|
84
|
+
items: false,
|
|
85
|
+
minItems: 2,
|
|
86
|
+
maxItems: 2,
|
|
87
|
+
};
|
|
88
|
+
const outputSchema = definition.outputValidator
|
|
89
|
+
? zodToCheckedJsonSchema(definition.outputValidator, `${filePath}:${funcName} output`)
|
|
90
|
+
: undefined;
|
|
91
|
+
// Internal handle that unpacks the [value, config] tuple from All
|
|
92
|
+
const internalDefinition = {
|
|
93
|
+
handle: ({ value }) => {
|
|
94
|
+
const [pipelineValue, config] = value;
|
|
95
|
+
return definition.handle({ value: pipelineValue, stepConfig: config });
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
const invokeAction = typedAction({
|
|
99
|
+
kind: "Invoke",
|
|
100
|
+
handler: {
|
|
101
|
+
kind: "TypeScript",
|
|
102
|
+
module: filePath,
|
|
103
|
+
func: funcName,
|
|
104
|
+
input_schema: inputSchema,
|
|
105
|
+
...(outputSchema && { output_schema: outputSchema }),
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
// Non-enumerable: invisible to JSON.stringify, visible to the worker
|
|
109
|
+
Object.defineProperty(invokeAction, HANDLER_BRAND, {
|
|
110
|
+
value: true,
|
|
111
|
+
enumerable: false,
|
|
112
|
+
});
|
|
113
|
+
Object.defineProperty(invokeAction, "__definition", {
|
|
114
|
+
value: internalDefinition,
|
|
115
|
+
enumerable: false,
|
|
116
|
+
});
|
|
117
|
+
// The factory function is the module export, so it must also carry
|
|
118
|
+
// __definition for the worker to find (the worker imports the module
|
|
119
|
+
// and accesses the named export, which is this function).
|
|
120
|
+
const factory = (config) => chain(toAction(all(identity(), constant(config))), toAction(invokeAction));
|
|
121
|
+
Object.defineProperty(factory, HANDLER_BRAND, {
|
|
122
|
+
value: true,
|
|
123
|
+
enumerable: false,
|
|
124
|
+
});
|
|
125
|
+
Object.defineProperty(factory, "__definition", {
|
|
126
|
+
value: internalDefinition,
|
|
127
|
+
enumerable: false,
|
|
128
|
+
});
|
|
129
|
+
return factory;
|
|
130
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TaggedUnion, OptionDef, ResultDef, IteratorDef } from "./ast.js";
|
|
2
|
+
export * from "./ast.js";
|
|
3
|
+
export { allObject, asOption, constant, drop, flatten, getField, getIndex, identity, panic, pick, range, splitFirst, splitLast, tag, taggedUnionSchema, withResource, wrapInField, } from "./builtins/index.js";
|
|
4
|
+
export { Option, first, last } from "./option.js";
|
|
5
|
+
export { Result } from "./result.js";
|
|
6
|
+
export { Iterator } from "./iterator.js";
|
|
7
|
+
export { runPipeline, type RunPipelineOptions, type LogLevel } from "./run.js";
|
|
8
|
+
export { zodToCheckedJsonSchema } from "./schema.js";
|
|
9
|
+
export type Option<T> = TaggedUnion<"Option", OptionDef<T>>;
|
|
10
|
+
export type Result<TValue, TError> = TaggedUnion<"Result", ResultDef<TValue, TError>>;
|
|
11
|
+
export type Iterator<TElement> = TaggedUnion<"Iterator", IteratorDef<TElement>>;
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE/E,cAAc,UAAU,CAAC;AACzB,OAAO,EACL,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,IAAI,EACJ,KAAK,EACL,UAAU,EACV,SAAS,EACT,GAAG,EACH,iBAAiB,EACjB,YAAY,EACZ,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAKrD,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5D,MAAM,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,WAAW,CAC9C,QAAQ,EACR,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAC1B,CAAC;AACF,MAAM,MAAM,QAAQ,CAAC,QAAQ,IAAI,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC"}
|