@barnum/barnum 0.3.0 → 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/dist/all.d.ts +41 -10
- package/dist/all.d.ts.map +1 -0
- package/dist/all.js +1 -1
- package/dist/ast.d.ts +199 -98
- package/dist/ast.d.ts.map +1 -0
- package/dist/ast.js +271 -233
- package/dist/bind.d.ts +9 -12
- package/dist/bind.d.ts.map +1 -0
- package/dist/bind.js +14 -51
- 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 +1 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +3 -3
- package/dist/effect-id.d.ts +1 -0
- package/dist/effect-id.d.ts.map +1 -0
- package/dist/handler.d.ts +7 -6
- package/dist/handler.d.ts.map +1 -0
- package/dist/handler.js +5 -21
- package/dist/index.d.ts +10 -6
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -2
- 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 +11 -10
- package/dist/pipe.d.ts.map +1 -0
- package/dist/pipe.js +5 -4
- package/dist/race.d.ts +5 -4
- package/dist/race.d.ts.map +1 -0
- package/dist/race.js +17 -42
- package/dist/recursive.d.ts +9 -3
- package/dist/recursive.d.ts.map +1 -0
- package/dist/recursive.js +18 -13
- 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 +9 -2
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +37 -20
- 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 +1 -0
- package/dist/schema.d.ts.map +1 -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 +2 -1
- package/dist/try-catch.d.ts.map +1 -0
- package/dist/try-catch.js +10 -9
- 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 +5 -1
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +15 -3
- package/package.json +8 -6
- package/src/all.ts +118 -74
- package/src/ast.ts +773 -350
- package/src/bind.ts +32 -62
- 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 +4 -4
- package/src/handler.ts +12 -28
- package/src/index.ts +24 -17
- package/src/iterator.ts +243 -0
- package/src/option.ts +199 -0
- package/src/pipe.ts +123 -78
- package/src/race.ts +41 -51
- package/src/recursive.ts +44 -27
- package/src/result.ts +168 -0
- package/src/run.ts +53 -25
- package/src/runtime.ts +16 -0
- package/src/schemas.ts +21 -0
- package/src/try-catch.ts +14 -10
- package/src/values.ts +21 -0
- package/src/worker.ts +17 -2
- package/dist/builtins.d.ts +0 -257
- package/dist/builtins.js +0 -600
- package/src/builtins.ts +0 -804
package/src/run.ts
CHANGED
|
@@ -8,9 +8,22 @@ import { createRequire } from "node:module";
|
|
|
8
8
|
import { existsSync } from "node:fs";
|
|
9
9
|
import os from "node:os";
|
|
10
10
|
import path from "node:path";
|
|
11
|
-
import
|
|
11
|
+
import {
|
|
12
|
+
type Action,
|
|
13
|
+
type Config,
|
|
14
|
+
type ExtractOutput,
|
|
15
|
+
toAction,
|
|
16
|
+
} from "./ast.js";
|
|
12
17
|
import { chain } from "./chain.js";
|
|
13
|
-
import { constant } from "./builtins.js";
|
|
18
|
+
import { constant } from "./builtins/index.js";
|
|
19
|
+
|
|
20
|
+
/** Log verbosity for the barnum engine runtime. Passed to the CLI's `--log-level`. */
|
|
21
|
+
export type LogLevel = "off" | "error" | "warn" | "info" | "debug" | "trace";
|
|
22
|
+
|
|
23
|
+
export interface RunPipelineOptions {
|
|
24
|
+
/** Engine log verbosity. Default: "off" (only handler stderr is visible). */
|
|
25
|
+
logLevel?: LogLevel;
|
|
26
|
+
}
|
|
14
27
|
|
|
15
28
|
const __dirname = import.meta.dirname;
|
|
16
29
|
|
|
@@ -101,12 +114,17 @@ function resolveWorker(): string {
|
|
|
101
114
|
return path.resolve(__dirname, "../src/worker.ts");
|
|
102
115
|
}
|
|
103
116
|
|
|
104
|
-
/** Build the barnum binary if using the local dev path. */
|
|
105
|
-
function
|
|
117
|
+
/** Build the barnum binary if using the local dev path. Skips if binary already exists. */
|
|
118
|
+
function buildBinaryIfNeeded(binaryPath: string): void {
|
|
119
|
+
if (existsSync(binaryPath)) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
106
122
|
const repoRoot = path.resolve(__dirname, "../../..");
|
|
123
|
+
// eslint-disable-next-line no-console
|
|
124
|
+
console.error("[barnum] building CLI binary (cargo build -p barnum_cli)...");
|
|
107
125
|
execFileSync("cargo", ["build", "-p", "barnum_cli"], {
|
|
108
126
|
cwd: repoRoot,
|
|
109
|
-
stdio: "
|
|
127
|
+
stdio: "inherit",
|
|
110
128
|
});
|
|
111
129
|
}
|
|
112
130
|
|
|
@@ -114,54 +132,64 @@ function buildBinary(): void {
|
|
|
114
132
|
export function runPipeline<TPipeline extends Action>(
|
|
115
133
|
pipeline: TPipeline,
|
|
116
134
|
input?: unknown,
|
|
135
|
+
options?: RunPipelineOptions,
|
|
117
136
|
): Promise<ExtractOutput<TPipeline>> {
|
|
118
137
|
const workflow =
|
|
119
138
|
input === undefined
|
|
120
139
|
? pipeline
|
|
121
|
-
: (chain(constant(input)
|
|
122
|
-
return spawnBarnum({ workflow });
|
|
140
|
+
: toAction(chain(toAction(constant(input)), toAction(pipeline)));
|
|
141
|
+
return spawnBarnum({ workflow }, options?.logLevel);
|
|
123
142
|
}
|
|
124
143
|
|
|
125
144
|
/** Spawn the barnum CLI with the given config. Returns the parsed final value from stdout. */
|
|
126
|
-
function spawnBarnum<TOut>(config: Config): Promise<TOut> {
|
|
145
|
+
function spawnBarnum<TOut>(config: Config, logLevel?: LogLevel): Promise<TOut> {
|
|
127
146
|
const binaryResolution = resolveBinary();
|
|
128
147
|
if (binaryResolution.kind === "Local") {
|
|
129
|
-
|
|
148
|
+
buildBinaryIfNeeded(binaryResolution.path);
|
|
130
149
|
}
|
|
131
150
|
const executor = resolveExecutor();
|
|
132
151
|
const worker = resolveWorker();
|
|
133
152
|
const configJson = JSON.stringify(config);
|
|
134
153
|
|
|
154
|
+
const cliArgs = [
|
|
155
|
+
"run",
|
|
156
|
+
"--config",
|
|
157
|
+
configJson,
|
|
158
|
+
"--executor",
|
|
159
|
+
executor,
|
|
160
|
+
"--worker",
|
|
161
|
+
worker,
|
|
162
|
+
];
|
|
163
|
+
if (logLevel) {
|
|
164
|
+
cliArgs.push("--log-level", logLevel);
|
|
165
|
+
}
|
|
166
|
+
|
|
135
167
|
return new Promise<TOut>((resolve, reject) => {
|
|
136
|
-
const child = nodeSpawn(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
"run",
|
|
140
|
-
"--config",
|
|
141
|
-
configJson,
|
|
142
|
-
"--executor",
|
|
143
|
-
executor,
|
|
144
|
-
"--worker",
|
|
145
|
-
worker,
|
|
146
|
-
],
|
|
147
|
-
{
|
|
148
|
-
stdio: ["inherit", "pipe", "inherit"],
|
|
149
|
-
},
|
|
150
|
-
);
|
|
168
|
+
const child = nodeSpawn(binaryResolution.path, cliArgs, {
|
|
169
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
170
|
+
});
|
|
151
171
|
|
|
152
172
|
const stdoutChunks: Buffer[] = [];
|
|
173
|
+
const stderrChunks: Buffer[] = [];
|
|
153
174
|
|
|
154
175
|
child.stdout?.on("data", (chunk: Buffer) => {
|
|
155
176
|
stdoutChunks.push(chunk);
|
|
156
177
|
});
|
|
157
178
|
|
|
179
|
+
child.stderr?.on("data", (chunk: Buffer) => {
|
|
180
|
+
stderrChunks.push(chunk);
|
|
181
|
+
process.stderr.write(chunk);
|
|
182
|
+
});
|
|
183
|
+
|
|
158
184
|
child.on("error", (error) => {
|
|
159
185
|
reject(new Error(`Failed to spawn barnum: ${error.message}`));
|
|
160
186
|
});
|
|
161
187
|
|
|
162
188
|
child.on("close", (code) => {
|
|
163
189
|
if (code !== 0) {
|
|
164
|
-
|
|
190
|
+
const stderr = Buffer.concat(stderrChunks).toString("utf8").trim();
|
|
191
|
+
const detail = stderr ? `\n${stderr}` : "";
|
|
192
|
+
reject(new Error(`barnum exited with code ${code}${detail}`));
|
|
165
193
|
return;
|
|
166
194
|
}
|
|
167
195
|
const stdout = Buffer.concat(stdoutChunks).toString("utf8").trim();
|
package/src/runtime.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Runtime value constructors
|
|
2
|
+
export { ok, err, some, none } from "./values.js";
|
|
3
|
+
|
|
4
|
+
// Handler creation
|
|
5
|
+
export {
|
|
6
|
+
createHandler,
|
|
7
|
+
createHandlerWithConfig,
|
|
8
|
+
type Handler,
|
|
9
|
+
} from "./handler.js";
|
|
10
|
+
|
|
11
|
+
// Schema builders
|
|
12
|
+
export { resultSchema, optionSchema } from "./schemas.js";
|
|
13
|
+
export { taggedUnionSchema } from "./builtins/index.js";
|
|
14
|
+
|
|
15
|
+
// Types only
|
|
16
|
+
export type { Result, Option, TaggedUnion } from "./ast.js";
|
package/src/schemas.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { Result, Option } from "./ast.js";
|
|
3
|
+
|
|
4
|
+
export function resultSchema<TValue, TError>(
|
|
5
|
+
okSchema: z.ZodType<TValue>,
|
|
6
|
+
errSchema: z.ZodType<TError>,
|
|
7
|
+
): z.ZodType<Result<TValue, TError>> {
|
|
8
|
+
return z.discriminatedUnion("kind", [
|
|
9
|
+
z.object({ kind: z.literal("Result.Ok"), value: okSchema }),
|
|
10
|
+
z.object({ kind: z.literal("Result.Err"), value: errSchema }),
|
|
11
|
+
]) as z.ZodType<Result<TValue, TError>>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function optionSchema<TValue>(
|
|
15
|
+
valueSchema: z.ZodType<TValue>,
|
|
16
|
+
): z.ZodType<Option<TValue>> {
|
|
17
|
+
return z.discriminatedUnion("kind", [
|
|
18
|
+
z.object({ kind: z.literal("Option.Some"), value: valueSchema }),
|
|
19
|
+
z.object({ kind: z.literal("Option.None"), value: z.null() }),
|
|
20
|
+
]) as z.ZodType<Option<TValue>>;
|
|
21
|
+
}
|
package/src/try-catch.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type Action,
|
|
3
2
|
type Pipeable,
|
|
4
3
|
type TypedAction,
|
|
4
|
+
toAction,
|
|
5
5
|
typedAction,
|
|
6
6
|
buildRestartBranchAction,
|
|
7
|
-
TAG_BREAK,
|
|
8
7
|
} from "./ast.js";
|
|
8
|
+
import { chain } from "./chain.js";
|
|
9
|
+
import { tag } from "./builtins/index.js";
|
|
9
10
|
import { allocateRestartHandlerId } from "./effect-id.js";
|
|
10
11
|
|
|
11
12
|
// ---------------------------------------------------------------------------
|
|
@@ -25,7 +26,7 @@ import { allocateRestartHandlerId } from "./effect-id.js";
|
|
|
25
26
|
*
|
|
26
27
|
* Compiled form (restart+Branch, same substrate as loop/earlyReturn):
|
|
27
28
|
* `Chain(Tag("Continue"),`
|
|
28
|
-
* `RestartHandle(id,
|
|
29
|
+
* `RestartHandle(id, GetIndex(0),`
|
|
29
30
|
* `Branch({ Continue: body, Break: recovery })))`
|
|
30
31
|
*
|
|
31
32
|
* throwError = `Chain(Tag("Break"), RestartPerform(id))`
|
|
@@ -39,15 +40,18 @@ export function tryCatch<TIn, TOut, TError>(
|
|
|
39
40
|
): TypedAction<TIn, TOut> {
|
|
40
41
|
const restartHandlerId = allocateRestartHandlerId();
|
|
41
42
|
|
|
42
|
-
const throwError = typedAction<TError, never>(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
const throwError = typedAction<TError, never>(
|
|
44
|
+
toAction(
|
|
45
|
+
chain(toAction(tag("Break", "LoopResult")), {
|
|
46
|
+
kind: "RestartPerform",
|
|
47
|
+
restart_handler_id: restartHandlerId,
|
|
48
|
+
}),
|
|
49
|
+
),
|
|
50
|
+
);
|
|
47
51
|
|
|
48
|
-
const bodyAction = body(throwError)
|
|
52
|
+
const bodyAction = toAction(body(throwError));
|
|
49
53
|
|
|
50
54
|
return typedAction(
|
|
51
|
-
buildRestartBranchAction(restartHandlerId, bodyAction, recovery
|
|
55
|
+
buildRestartBranchAction(restartHandlerId, bodyAction, toAction(recovery)),
|
|
52
56
|
);
|
|
53
57
|
}
|
package/src/values.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Result, Option } from "./ast.js";
|
|
2
|
+
|
|
3
|
+
export function ok<TValue, TError = unknown>(
|
|
4
|
+
value: TValue,
|
|
5
|
+
): Result<TValue, TError> {
|
|
6
|
+
return { kind: "Result.Ok", value } as Result<TValue, TError>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function err<TValue = unknown, TError = never>(
|
|
10
|
+
error: TError,
|
|
11
|
+
): Result<TValue, TError> {
|
|
12
|
+
return { kind: "Result.Err", value: error } as Result<TValue, TError>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function some<T>(value: T): Option<T> {
|
|
16
|
+
return { kind: "Option.Some", value } as Option<T>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function none<T = unknown>(): Option<T> {
|
|
20
|
+
return { kind: "Option.None", value: null } as Option<T>;
|
|
21
|
+
}
|
package/src/worker.ts
CHANGED
|
@@ -5,10 +5,20 @@
|
|
|
5
5
|
* Rust → stdin: JSON `{ "value": <any> }`
|
|
6
6
|
* stdout → Rust: JSON result (handler return value)
|
|
7
7
|
*
|
|
8
|
+
* stdout is reserved for the protocol. All console output is redirected to
|
|
9
|
+
* stderr so that handler code can freely use console.log for debugging.
|
|
10
|
+
*
|
|
8
11
|
* If the handler throws or the module/export can't be resolved, the
|
|
9
12
|
* process exits non-zero. Rust interprets that as a fatal workflow error.
|
|
10
13
|
*/
|
|
11
14
|
|
|
15
|
+
// Redirect all console output to stderr — stdout is the protocol channel.
|
|
16
|
+
// This must happen before any handler code is imported or executed.
|
|
17
|
+
import { Console } from "node:console";
|
|
18
|
+
|
|
19
|
+
const stderrConsole = new Console({ stdout: process.stderr });
|
|
20
|
+
globalThis.console = stderrConsole;
|
|
21
|
+
|
|
12
22
|
// Suppress EPIPE — when the Rust binary exits (e.g., a race was resolved),
|
|
13
23
|
// orphan workers get broken pipe on stdout. This is expected, not an error.
|
|
14
24
|
process.stdout.on("error", (error: NodeJS.ErrnoException) => {
|
|
@@ -46,8 +56,13 @@ async function main(): Promise<void> {
|
|
|
46
56
|
|
|
47
57
|
const result = await handler.__definition.handle({ value: input.value });
|
|
48
58
|
|
|
49
|
-
// Write result to stdout
|
|
50
|
-
|
|
59
|
+
// Write result to stdout, then exit. Explicit exit is required because
|
|
60
|
+
// importing the handler module may leave open handles (timers, servers,
|
|
61
|
+
// etc.) that keep the Node event loop alive indefinitely.
|
|
62
|
+
const json = JSON.stringify(result) ?? "null";
|
|
63
|
+
process.stdout.write(json, () => {
|
|
64
|
+
process.exit(0);
|
|
65
|
+
});
|
|
51
66
|
}
|
|
52
67
|
|
|
53
68
|
main().catch((error) => {
|
package/dist/builtins.d.ts
DELETED
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
import { type Action, type Option as OptionT, type Pipeable, type Result as ResultT, type TaggedUnion, type TypedAction } from "./ast.js";
|
|
2
|
-
/**
|
|
3
|
-
* Typed combinators for structural data transformations.
|
|
4
|
-
*
|
|
5
|
-
* All builtins emit `{ kind: "Builtin", builtin: { kind: ... } }` handler
|
|
6
|
-
* kinds. The Rust scheduler executes them inline (no subprocess).
|
|
7
|
-
*/
|
|
8
|
-
export declare function constant<TValue>(value: TValue): TypedAction<any, TValue>;
|
|
9
|
-
export declare const identity: TypedAction<any, any>;
|
|
10
|
-
export declare const drop: TypedAction<any, never>;
|
|
11
|
-
/**
|
|
12
|
-
* Wrap input as a tagged union member. Requires the full variant map TDef
|
|
13
|
-
* so the output type carries __def for branch decomposition.
|
|
14
|
-
*
|
|
15
|
-
* Usage: tag<{ Ok: string; Err: number }, "Ok">("Ok")
|
|
16
|
-
* input: string → output: TaggedUnion<{ Ok: string; Err: number }>
|
|
17
|
-
*/
|
|
18
|
-
export declare function tag<TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(kind: TKind): TypedAction<TDef[TKind], TaggedUnion<TDef>>;
|
|
19
|
-
type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
|
|
20
|
-
export declare function merge<TObjects extends Record<string, unknown>[]>(): TypedAction<TObjects, UnionToIntersection<TObjects[number]>>;
|
|
21
|
-
export declare function flatten<TElement>(): TypedAction<TElement[][], TElement[]>;
|
|
22
|
-
export declare function extractField<TObj extends Record<string, unknown>, TField extends keyof TObj & string>(field: TField): TypedAction<TObj, TObj[TField]>;
|
|
23
|
-
export declare function extractIndex<TTuple extends unknown[], TIndex extends number>(index: TIndex): TypedAction<TTuple, TTuple[TIndex]>;
|
|
24
|
-
export declare function pick<TObj extends Record<string, unknown>, TKeys extends (keyof TObj & string)[]>(...keys: TKeys): TypedAction<TObj, Pick<TObj, TKeys[number]>>;
|
|
25
|
-
export declare function dropResult<TInput, TOutput>(action: Pipeable<TInput, TOutput>): TypedAction<TInput, never>;
|
|
26
|
-
/**
|
|
27
|
-
* RAII-style resource management combinator.
|
|
28
|
-
*
|
|
29
|
-
* Runs `create` to acquire a resource, then merges the resource with the
|
|
30
|
-
* original input into a flat object (`TResource & TIn`) for the action.
|
|
31
|
-
* After the action completes, `dispose` receives the resource for cleanup.
|
|
32
|
-
* The overall combinator returns the action's output.
|
|
33
|
-
*
|
|
34
|
-
* ```
|
|
35
|
-
* TIn → create → TResource
|
|
36
|
-
* → merge(TResource, TIn) → TResource & TIn
|
|
37
|
-
* → action(TResource & TIn) → TOut
|
|
38
|
-
* → dispose(TResource) → (discarded)
|
|
39
|
-
* → TOut
|
|
40
|
-
* ```
|
|
41
|
-
*/
|
|
42
|
-
export declare function withResource<TIn extends Record<string, unknown>, TResource extends Record<string, unknown>, TOut, TDisposeOut = unknown>({ create, action, dispose, }: {
|
|
43
|
-
create: Pipeable<TIn, TResource>;
|
|
44
|
-
action: Pipeable<TResource & TIn, TOut>;
|
|
45
|
-
dispose: Pipeable<TResource, TDisposeOut>;
|
|
46
|
-
}): TypedAction<TIn, TOut>;
|
|
47
|
-
/**
|
|
48
|
-
* Run `action` on the input, then merge the action's output fields back
|
|
49
|
-
* into the original input object. The action must accept exactly `TInput`.
|
|
50
|
-
* Use `pick` inside the action's pipe if the inner handler needs a subset.
|
|
51
|
-
*
|
|
52
|
-
* Example:
|
|
53
|
-
* augment(pipe(pick("file"), migrate))
|
|
54
|
-
* // { file, outputPath } → { file, outputPath, content, migrated }
|
|
55
|
-
*/
|
|
56
|
-
export declare function augment<TInput extends Record<string, unknown>, TOutput extends Record<string, unknown>>(action: Pipeable<TInput, TOutput>): TypedAction<TInput, TInput & TOutput>;
|
|
57
|
-
/**
|
|
58
|
-
* Run `action` on the input for its side effects, then discard the action's
|
|
59
|
-
* output and return the original input unchanged. The action must accept
|
|
60
|
-
* exactly `TInput`. Use `pick` inside the action's pipe if the inner
|
|
61
|
-
* handler needs a subset.
|
|
62
|
-
*
|
|
63
|
-
* Constraint: input must be an object (uses augment internally, which
|
|
64
|
-
* relies on all + merge).
|
|
65
|
-
*
|
|
66
|
-
* Example:
|
|
67
|
-
* pipe(tap(pipe(pick("worktreePath", "description"), implement)), createPR)
|
|
68
|
-
*/
|
|
69
|
-
export declare function tap<TInput extends Record<string, unknown>>(action: Pipeable<TInput, any>): TypedAction<TInput, TInput>;
|
|
70
|
-
export declare function range(start: number, end: number): TypedAction<any, number[]>;
|
|
71
|
-
/**
|
|
72
|
-
* Option namespace. All combinators produce TypedAction AST nodes that
|
|
73
|
-
* desugar to branch + existing builtins, except collect which uses the
|
|
74
|
-
* CollectSome builtin.
|
|
75
|
-
*/
|
|
76
|
-
export declare const Option: {
|
|
77
|
-
/**
|
|
78
|
-
* Wrap a value as Some. `T → Option<T>`
|
|
79
|
-
*
|
|
80
|
-
* Equivalent to `tag<OptionDef<T>, "Some">("Some")`.
|
|
81
|
-
*/
|
|
82
|
-
readonly some: <T>() => TypedAction<T, OptionT<T>>;
|
|
83
|
-
/**
|
|
84
|
-
* Produce a None. `never → Option<T>`
|
|
85
|
-
*
|
|
86
|
-
* Chain after `.drop()` to discard the current value first.
|
|
87
|
-
* Equivalent to `tag<OptionDef<T>, "None">("None")`.
|
|
88
|
-
*/
|
|
89
|
-
readonly none: <T>() => TypedAction<never, OptionT<T>>;
|
|
90
|
-
/**
|
|
91
|
-
* Transform the Some value. `Option<T> → Option<U>`
|
|
92
|
-
*
|
|
93
|
-
* Desugars to: `branch({ Some: pipe(action, tag("Some")), None: tag("None") })`
|
|
94
|
-
*/
|
|
95
|
-
readonly map: <T, U>(action: Pipeable<T, U>) => TypedAction<OptionT<T>, OptionT<U>>;
|
|
96
|
-
/**
|
|
97
|
-
* Monadic bind (flatMap). If Some, pass the value to action which
|
|
98
|
-
* returns Option<U>. If None, stay None. `Option<T> → Option<U>`
|
|
99
|
-
*
|
|
100
|
-
* This is the most fundamental combinator — map, flatten, and filter
|
|
101
|
-
* are all derivable from andThen + constructors.
|
|
102
|
-
*
|
|
103
|
-
* Desugars to: `branch({ Some: action, None: tag("None") })`
|
|
104
|
-
*/
|
|
105
|
-
readonly andThen: <T, U>(action: Pipeable<T, OptionT<U>>) => TypedAction<OptionT<T>, OptionT<U>>;
|
|
106
|
-
/**
|
|
107
|
-
* Extract the Some value or produce a default from an action.
|
|
108
|
-
* `Option<T> → T`
|
|
109
|
-
*
|
|
110
|
-
* The defaultAction takes no meaningful input (never) and must produce T.
|
|
111
|
-
* Use `Option.unwrapOr(constant("fallback"))`.
|
|
112
|
-
*
|
|
113
|
-
* The None branch drops its void payload before calling defaultAction,
|
|
114
|
-
* matching Rust's `unwrap_or_else(|| default)` where the closure takes
|
|
115
|
-
* no arguments.
|
|
116
|
-
*
|
|
117
|
-
* Desugars to: `branch({ Some: identity(), None: pipe(drop(), defaultAction) })`
|
|
118
|
-
*/
|
|
119
|
-
readonly unwrapOr: <T>(defaultAction: Pipeable<never, T>) => TypedAction<OptionT<T>, T>;
|
|
120
|
-
/**
|
|
121
|
-
* Unwrap a nested Option. `Option<Option<T>> → Option<T>`
|
|
122
|
-
*
|
|
123
|
-
* Desugars to: `branch({ Some: identity(), None: tag("None") })`
|
|
124
|
-
*/
|
|
125
|
-
readonly flatten: <T>() => TypedAction<OptionT<OptionT<T>>, OptionT<T>>;
|
|
126
|
-
/**
|
|
127
|
-
* Conditional keep. If Some, pass value to predicate which returns
|
|
128
|
-
* Option<T> (some() to keep, none() to discard). If None, stay None.
|
|
129
|
-
* `Option<T> → Option<T>`
|
|
130
|
-
*
|
|
131
|
-
* This has the same signature and desugaring as andThen with T=U.
|
|
132
|
-
* Named "filter" for readability when the intent is filtering.
|
|
133
|
-
*
|
|
134
|
-
* Desugars to: `branch({ Some: predicate, None: tag("None") })`
|
|
135
|
-
*/
|
|
136
|
-
readonly filter: <T>(predicate: Pipeable<T, OptionT<T>>) => TypedAction<OptionT<T>, OptionT<T>>;
|
|
137
|
-
/**
|
|
138
|
-
* Collect Some values from an array, discarding Nones.
|
|
139
|
-
* `Option<T>[] → T[]`
|
|
140
|
-
*
|
|
141
|
-
* This is a builtin handler (CollectSome) — it can't be expressed
|
|
142
|
-
* as a composition of existing AST nodes because it requires
|
|
143
|
-
* array-level filtering logic.
|
|
144
|
-
*/
|
|
145
|
-
readonly collect: <T = any>() => TypedAction<OptionT<T>[], T[]>;
|
|
146
|
-
/**
|
|
147
|
-
* Test if the value is Some. `Option<T> → boolean`
|
|
148
|
-
*
|
|
149
|
-
* Rarely useful — branch on Some/None directly instead.
|
|
150
|
-
*
|
|
151
|
-
* Desugars to: `branch({ Some: pipe(drop(), constant(true)), None: pipe(drop(), constant(false)) })`
|
|
152
|
-
*/
|
|
153
|
-
readonly isSome: <T>() => TypedAction<OptionT<T>, boolean>;
|
|
154
|
-
/**
|
|
155
|
-
* Test if the value is None. `Option<T> → boolean`
|
|
156
|
-
*
|
|
157
|
-
* Rarely useful — branch on Some/None directly instead.
|
|
158
|
-
*
|
|
159
|
-
* Desugars to: `branch({ Some: pipe(drop(), constant(false)), None: pipe(drop(), constant(true)) })`
|
|
160
|
-
*/
|
|
161
|
-
readonly isNone: <T>() => TypedAction<OptionT<T>, boolean>;
|
|
162
|
-
};
|
|
163
|
-
/**
|
|
164
|
-
* Result namespace. All combinators produce TypedAction AST nodes that
|
|
165
|
-
* desugar to branch + existing builtins.
|
|
166
|
-
*/
|
|
167
|
-
export declare const Result: {
|
|
168
|
-
/**
|
|
169
|
-
* Wrap a value as Ok. `TValue → Result<TValue, TError>`
|
|
170
|
-
*/
|
|
171
|
-
readonly ok: <TValue, TError>() => TypedAction<TValue, ResultT<TValue, TError>>;
|
|
172
|
-
/**
|
|
173
|
-
* Wrap a value as Err. `TError → Result<TValue, TError>`
|
|
174
|
-
*/
|
|
175
|
-
readonly err: <TValue, TError>() => TypedAction<TError, ResultT<TValue, TError>>;
|
|
176
|
-
/**
|
|
177
|
-
* Transform the Ok value. `Result<TValue, TError> → Result<TOut, TError>`
|
|
178
|
-
*
|
|
179
|
-
* Desugars to: `branch({ Ok: pipe(action, tag("Ok")), Err: tag("Err") })`
|
|
180
|
-
*/
|
|
181
|
-
readonly map: <TValue, TOut, TError>(action: Pipeable<TValue, TOut>) => TypedAction<ResultT<TValue, TError>, ResultT<TOut, TError>>;
|
|
182
|
-
/**
|
|
183
|
-
* Transform the Err value. `Result<TValue, TError> → Result<TValue, TErrorOut>`
|
|
184
|
-
*
|
|
185
|
-
* Desugars to: `branch({ Ok: tag("Ok"), Err: pipe(action, tag("Err")) })`
|
|
186
|
-
*/
|
|
187
|
-
readonly mapErr: <TValue, TError, TErrorOut>(action: Pipeable<TError, TErrorOut>) => TypedAction<ResultT<TValue, TError>, ResultT<TValue, TErrorOut>>;
|
|
188
|
-
/**
|
|
189
|
-
* Monadic bind (flatMap) for Ok. If Ok, pass value to action which
|
|
190
|
-
* returns Result<TOut, TError>. If Err, propagate.
|
|
191
|
-
*
|
|
192
|
-
* Desugars to: `branch({ Ok: action, Err: tag("Err") })`
|
|
193
|
-
*/
|
|
194
|
-
readonly andThen: <TValue, TOut, TError>(action: Pipeable<TValue, ResultT<TOut, TError>>) => TypedAction<ResultT<TValue, TError>, ResultT<TOut, TError>>;
|
|
195
|
-
/**
|
|
196
|
-
* Fallback on Err. If Ok, keep it. If Err, pass error to fallback
|
|
197
|
-
* which returns a new Result.
|
|
198
|
-
*
|
|
199
|
-
* Desugars to: `branch({ Ok: tag("Ok"), Err: fallback })`
|
|
200
|
-
*/
|
|
201
|
-
readonly or: <TValue, TError, TErrorOut>(fallback: Pipeable<TError, ResultT<TValue, TErrorOut>>) => TypedAction<ResultT<TValue, TError>, ResultT<TValue, TErrorOut>>;
|
|
202
|
-
/**
|
|
203
|
-
* Replace Ok value with another Result. If Ok, discard value and
|
|
204
|
-
* return other. If Err, propagate.
|
|
205
|
-
*
|
|
206
|
-
* Desugars to: `branch({ Ok: pipe(drop(), other), Err: tag("Err") })`
|
|
207
|
-
*/
|
|
208
|
-
readonly and: <TValue, TOut, TError>(other: Pipeable<never, ResultT<TOut, TError>>) => TypedAction<ResultT<TValue, TError>, ResultT<TOut, TError>>;
|
|
209
|
-
/**
|
|
210
|
-
* Extract Ok or compute default from Err. `Result<TValue, TError> → TValue`
|
|
211
|
-
*
|
|
212
|
-
* Takes an action that receives the Err payload and produces a fallback.
|
|
213
|
-
* Uses covariant output checking so throw tokens (Out=never) are assignable
|
|
214
|
-
* when TValue is provided explicitly: `Result.unwrapOr<string, string>(throwError)`.
|
|
215
|
-
*
|
|
216
|
-
* For inference-free usage with throw tokens, prefer the postfix method:
|
|
217
|
-
* `handler.unwrapOr(throwError)` — the `this` constraint provides TValue.
|
|
218
|
-
*
|
|
219
|
-
* Desugars to: `branch({ Ok: identity(), Err: defaultAction })`
|
|
220
|
-
*/
|
|
221
|
-
readonly unwrapOr: <TValue, TError>(defaultAction: Action & {
|
|
222
|
-
__in?: (input: TError) => void;
|
|
223
|
-
__out?: () => TValue;
|
|
224
|
-
}) => TypedAction<ResultT<TValue, TError>, TValue>;
|
|
225
|
-
/**
|
|
226
|
-
* Unwrap nested Result. `Result<Result<TValue, TError>, TError> → Result<TValue, TError>`
|
|
227
|
-
*
|
|
228
|
-
* Desugars to: `branch({ Ok: identity(), Err: tag("Err") })`
|
|
229
|
-
*/
|
|
230
|
-
readonly flatten: <TValue, TError>() => TypedAction<ResultT<ResultT<TValue, TError>, TError>, ResultT<TValue, TError>>;
|
|
231
|
-
/**
|
|
232
|
-
* Convert Ok to Some, Err to None. `Result<TValue, TError> → Option<TValue>`
|
|
233
|
-
*
|
|
234
|
-
* Desugars to: `branch({ Ok: tag("Some"), Err: pipe(drop(), tag("None")) })`
|
|
235
|
-
*/
|
|
236
|
-
readonly toOption: <TValue, TError>() => TypedAction<ResultT<TValue, TError>, OptionT<TValue>>;
|
|
237
|
-
/**
|
|
238
|
-
* Convert Err to Some, Ok to None. `Result<TValue, TError> → Option<TError>`
|
|
239
|
-
*
|
|
240
|
-
* Desugars to: `branch({ Ok: pipe(drop(), tag("None")), Err: tag("Some") })`
|
|
241
|
-
*/
|
|
242
|
-
readonly toOptionErr: <TValue, TError>() => TypedAction<ResultT<TValue, TError>, OptionT<TError>>;
|
|
243
|
-
/**
|
|
244
|
-
* Swap Result/Option nesting.
|
|
245
|
-
* `Result<Option<TValue>, TError> → Option<Result<TValue, TError>>`
|
|
246
|
-
*/
|
|
247
|
-
readonly transpose: <TValue, TError>() => TypedAction<ResultT<OptionT<TValue>, TError>, OptionT<ResultT<TValue, TError>>>;
|
|
248
|
-
/**
|
|
249
|
-
* Test if the value is Ok. `Result<TValue, TError> → boolean`
|
|
250
|
-
*/
|
|
251
|
-
readonly isOk: <TValue, TError>() => TypedAction<ResultT<TValue, TError>, boolean>;
|
|
252
|
-
/**
|
|
253
|
-
* Test if the value is Err. `Result<TValue, TError> → boolean`
|
|
254
|
-
*/
|
|
255
|
-
readonly isErr: <TValue, TError>() => TypedAction<ResultT<TValue, TError>, boolean>;
|
|
256
|
-
};
|
|
257
|
-
export {};
|