@onrails/result 0.1.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/DESIGN.md +119 -0
- package/LICENSE +21 -0
- package/README.md +323 -0
- package/RECIPES.md +367 -0
- package/dist/async-CCA1yK8q.d.cts +147 -0
- package/dist/async-DH_-dNIo.d.ts +147 -0
- package/dist/compat/neverthrow.cjs +446 -0
- package/dist/compat/neverthrow.cjs.map +1 -0
- package/dist/compat/neverthrow.d.cts +77 -0
- package/dist/compat/neverthrow.d.ts +77 -0
- package/dist/compat/neverthrow.js +435 -0
- package/dist/compat/neverthrow.js.map +1 -0
- package/dist/extra.cjs +37 -0
- package/dist/extra.cjs.map +1 -0
- package/dist/extra.d.cts +50 -0
- package/dist/extra.d.ts +50 -0
- package/dist/extra.js +31 -0
- package/dist/extra.js.map +1 -0
- package/dist/fluent.cjs +64 -0
- package/dist/fluent.cjs.map +1 -0
- package/dist/fluent.d.cts +28 -0
- package/dist/fluent.d.ts +28 -0
- package/dist/fluent.js +61 -0
- package/dist/fluent.js.map +1 -0
- package/dist/index.cjs +406 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +227 -0
- package/dist/index.d.ts +227 -0
- package/dist/index.js +369 -0
- package/dist/index.js.map +1 -0
- package/dist/interop.cjs +248 -0
- package/dist/interop.cjs.map +1 -0
- package/dist/interop.d.cts +25 -0
- package/dist/interop.d.ts +25 -0
- package/dist/interop.js +244 -0
- package/dist/interop.js.map +1 -0
- package/dist/mcp.cjs +292 -0
- package/dist/mcp.cjs.map +1 -0
- package/dist/mcp.d.cts +62 -0
- package/dist/mcp.d.ts +62 -0
- package/dist/mcp.js +284 -0
- package/dist/mcp.js.map +1 -0
- package/dist/pipe.cjs +16 -0
- package/dist/pipe.cjs.map +1 -0
- package/dist/pipe.d.cts +26 -0
- package/dist/pipe.d.ts +26 -0
- package/dist/pipe.js +14 -0
- package/dist/pipe.js.map +1 -0
- package/dist/railway.cjs +443 -0
- package/dist/railway.cjs.map +1 -0
- package/dist/railway.d.cts +214 -0
- package/dist/railway.d.ts +214 -0
- package/dist/railway.js +431 -0
- package/dist/railway.js.map +1 -0
- package/dist/try-gen.cjs +40 -0
- package/dist/try-gen.cjs.map +1 -0
- package/dist/try-gen.d.cts +23 -0
- package/dist/try-gen.d.ts +23 -0
- package/dist/try-gen.js +36 -0
- package/dist/try-gen.js.map +1 -0
- package/dist/types-C2Dp1d5J.d.cts +21 -0
- package/dist/types-C2Dp1d5J.d.ts +21 -0
- package/dist/validation.cjs +70 -0
- package/dist/validation.cjs.map +1 -0
- package/dist/validation.d.cts +72 -0
- package/dist/validation.d.ts +72 -0
- package/dist/validation.js +65 -0
- package/dist/validation.js.map +1 -0
- package/package.json +114 -0
package/dist/railway.cjs
ADDED
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/result.ts
|
|
4
|
+
var ok = (value) => ({
|
|
5
|
+
_tag: "Ok",
|
|
6
|
+
value
|
|
7
|
+
});
|
|
8
|
+
var err = (error) => ({
|
|
9
|
+
_tag: "Err",
|
|
10
|
+
error
|
|
11
|
+
});
|
|
12
|
+
var isOk = (result) => result._tag === "Ok";
|
|
13
|
+
var isErr = (result) => result._tag === "Err";
|
|
14
|
+
var mapImpl = (result, fn) => isOk(result) ? ok(fn(result.value)) : err(result.error);
|
|
15
|
+
function map(...args) {
|
|
16
|
+
if (args.length === 2) return mapImpl(args[0], args[1]);
|
|
17
|
+
const fn = args[0];
|
|
18
|
+
return (result) => mapImpl(result, fn);
|
|
19
|
+
}
|
|
20
|
+
var mapErrImpl = (result, fn) => isErr(result) ? err(fn(result.error)) : ok(result.value);
|
|
21
|
+
function mapErr(...args) {
|
|
22
|
+
if (args.length === 2) return mapErrImpl(args[0], args[1]);
|
|
23
|
+
const fn = args[0];
|
|
24
|
+
return (result) => mapErrImpl(result, fn);
|
|
25
|
+
}
|
|
26
|
+
function trySync(fn, onThrow) {
|
|
27
|
+
return (...args) => {
|
|
28
|
+
try {
|
|
29
|
+
return ok(fn(...args));
|
|
30
|
+
} catch (error) {
|
|
31
|
+
return err(onThrow(error));
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/types.ts
|
|
37
|
+
var UnexpectedError = class extends Error {
|
|
38
|
+
constructor(message, cause) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.cause = cause;
|
|
41
|
+
this.name = "UnexpectedError";
|
|
42
|
+
}
|
|
43
|
+
cause;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// src/async.ts
|
|
47
|
+
var liftPromiseResult = async (promise, onDefect) => {
|
|
48
|
+
try {
|
|
49
|
+
const result = await promise;
|
|
50
|
+
if (isErr(result)) {
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
const inner = result.value;
|
|
54
|
+
if (inner && typeof inner === "object" && "_tag" in inner) {
|
|
55
|
+
if (inner._tag === "Ok" || inner._tag === "Err") {
|
|
56
|
+
return inner;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
} catch (error) {
|
|
61
|
+
return err(onDefect(error));
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
var ResultAsync = class _ResultAsync {
|
|
65
|
+
constructor(run) {
|
|
66
|
+
this.run = run;
|
|
67
|
+
}
|
|
68
|
+
run;
|
|
69
|
+
static fromResult(result) {
|
|
70
|
+
return new _ResultAsync(async () => result);
|
|
71
|
+
}
|
|
72
|
+
static fromPromise(promise, onReject) {
|
|
73
|
+
return new _ResultAsync(async () => {
|
|
74
|
+
try {
|
|
75
|
+
return ok(await promise);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
return err(onReject(error));
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
static fromSafePromise(promise) {
|
|
82
|
+
return new _ResultAsync(async () => ok(await promise));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Defers work until {@link resolve}. Unlike {@link fromPromise}, nothing runs
|
|
86
|
+
* until the `ResultAsync` is resolved (e.g. by `combineTuple` / `combineTupleParallel`).
|
|
87
|
+
*/
|
|
88
|
+
static defer(fn) {
|
|
89
|
+
return new _ResultAsync(fn);
|
|
90
|
+
}
|
|
91
|
+
static ok(value) {
|
|
92
|
+
return new _ResultAsync(async () => ok(value));
|
|
93
|
+
}
|
|
94
|
+
static err(error) {
|
|
95
|
+
return new _ResultAsync(async () => err(error));
|
|
96
|
+
}
|
|
97
|
+
/** @see {@link fromAsync} from `@onrails/result/interop` */
|
|
98
|
+
static fromResultPromise(promise, onDefect) {
|
|
99
|
+
const mapDefect = onDefect ?? ((error) => new UnexpectedError("Unexpected async defect", error));
|
|
100
|
+
return new _ResultAsync(() => liftPromiseResult(promise, mapDefect));
|
|
101
|
+
}
|
|
102
|
+
static combine(results) {
|
|
103
|
+
return new _ResultAsync(async () => {
|
|
104
|
+
const values = [];
|
|
105
|
+
for (const ra of results) {
|
|
106
|
+
const result = await ra.resolve();
|
|
107
|
+
if (isErr(result)) {
|
|
108
|
+
return err(result.error);
|
|
109
|
+
}
|
|
110
|
+
values.push(result.value);
|
|
111
|
+
}
|
|
112
|
+
return ok(values);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
static combineTuple(results) {
|
|
116
|
+
return new _ResultAsync(async () => {
|
|
117
|
+
const values = [];
|
|
118
|
+
for (const ra of results) {
|
|
119
|
+
const result = await ra.resolve();
|
|
120
|
+
if (isErr(result)) {
|
|
121
|
+
return err(result.error);
|
|
122
|
+
}
|
|
123
|
+
values.push(result.value);
|
|
124
|
+
}
|
|
125
|
+
return ok(values);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Like {@link combineTuple}, but starts every branch before awaiting (wall-clock
|
|
130
|
+
* parallel for independent IO). On failure, returns the first `Err` in input order.
|
|
131
|
+
*/
|
|
132
|
+
static combineTupleParallel(results) {
|
|
133
|
+
return new _ResultAsync(async () => {
|
|
134
|
+
const settled = await Promise.all(results.map((ra) => ra.resolve()));
|
|
135
|
+
const values = [];
|
|
136
|
+
for (const result of settled) {
|
|
137
|
+
if (isErr(result)) {
|
|
138
|
+
return err(result.error);
|
|
139
|
+
}
|
|
140
|
+
values.push(result.value);
|
|
141
|
+
}
|
|
142
|
+
return ok(values);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
map(fn) {
|
|
146
|
+
return new _ResultAsync(async () => map(await this.run(), fn));
|
|
147
|
+
}
|
|
148
|
+
mapErr(fn) {
|
|
149
|
+
return new _ResultAsync(async () => mapErr(await this.run(), fn));
|
|
150
|
+
}
|
|
151
|
+
flatMap(fn) {
|
|
152
|
+
return new _ResultAsync(async () => {
|
|
153
|
+
const first = await this.run();
|
|
154
|
+
if (isErr(first)) {
|
|
155
|
+
return err(first.error);
|
|
156
|
+
}
|
|
157
|
+
const next = fn(first.value);
|
|
158
|
+
if (next instanceof _ResultAsync) {
|
|
159
|
+
return next.resolve();
|
|
160
|
+
}
|
|
161
|
+
if (isResultLike(next)) {
|
|
162
|
+
return next;
|
|
163
|
+
}
|
|
164
|
+
if (isCompatLike(next)) {
|
|
165
|
+
return next.inner;
|
|
166
|
+
}
|
|
167
|
+
return next;
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
andThen(fn) {
|
|
171
|
+
return this.flatMap(fn);
|
|
172
|
+
}
|
|
173
|
+
chain(fn) {
|
|
174
|
+
return this.flatMap(fn);
|
|
175
|
+
}
|
|
176
|
+
recover(fn) {
|
|
177
|
+
return new _ResultAsync(async () => {
|
|
178
|
+
const first = await this.run();
|
|
179
|
+
if (!isErr(first)) {
|
|
180
|
+
return first;
|
|
181
|
+
}
|
|
182
|
+
const next = fn(first.error);
|
|
183
|
+
if (next instanceof _ResultAsync) {
|
|
184
|
+
return next.resolve();
|
|
185
|
+
}
|
|
186
|
+
return next;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
orElse(fn) {
|
|
190
|
+
return this.recover(fn);
|
|
191
|
+
}
|
|
192
|
+
tap(fn) {
|
|
193
|
+
return new _ResultAsync(async () => {
|
|
194
|
+
const result = await this.run();
|
|
195
|
+
if (!isErr(result)) {
|
|
196
|
+
fn(result.value);
|
|
197
|
+
}
|
|
198
|
+
return result;
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
tapErr(fn) {
|
|
202
|
+
return new _ResultAsync(async () => {
|
|
203
|
+
const result = await this.run();
|
|
204
|
+
if (isErr(result)) {
|
|
205
|
+
fn(result.error);
|
|
206
|
+
}
|
|
207
|
+
return result;
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
unwrapOr(defaultValue) {
|
|
211
|
+
return this.run().then((result) => isErr(result) ? defaultValue : result.value);
|
|
212
|
+
}
|
|
213
|
+
isOk() {
|
|
214
|
+
return this.run().then((result) => !isErr(result));
|
|
215
|
+
}
|
|
216
|
+
isErr() {
|
|
217
|
+
return this.run().then((result) => isErr(result));
|
|
218
|
+
}
|
|
219
|
+
match(onOk, onErr) {
|
|
220
|
+
return this.run().then(
|
|
221
|
+
(result) => isErr(result) ? onErr(result.error) : onOk(result.value)
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
resolve() {
|
|
225
|
+
return this.run();
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Thenable shim — `await ra` resolves to a bare tagged-union `Result<T, E>`.
|
|
229
|
+
* Narrow with `isOk(r)` / `isErr(r)` to read `.value` / `.error`.
|
|
230
|
+
*/
|
|
231
|
+
// biome-ignore lint/suspicious/noThenProperty: makes ResultAsync awaitable
|
|
232
|
+
then(onfulfilled, onrejected) {
|
|
233
|
+
return this.run().then(
|
|
234
|
+
(r) => onfulfilled ? onfulfilled(r) : r,
|
|
235
|
+
onrejected ?? void 0
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
function isResultLike(v) {
|
|
240
|
+
return typeof v === "object" && v !== null && "_tag" in v && (v._tag === "Ok" || v._tag === "Err");
|
|
241
|
+
}
|
|
242
|
+
function isCompatLike(v) {
|
|
243
|
+
return typeof v === "object" && v !== null && "inner" in v && isResultLike(v.inner);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// src/railway.ts
|
|
247
|
+
var addField = (ctx, key, value) => ({ ...ctx, [key]: value });
|
|
248
|
+
var liftResult = (result) => ResultAsync.fromResult(result);
|
|
249
|
+
var parseWithParser = (parser, input) => typeof parser === "function" ? parser(input) : parser.parse(input);
|
|
250
|
+
var Railway = class _Railway {
|
|
251
|
+
constructor(state) {
|
|
252
|
+
this.state = state;
|
|
253
|
+
}
|
|
254
|
+
state;
|
|
255
|
+
/** Start an empty sync workflow with no fields in context. */
|
|
256
|
+
static empty() {
|
|
257
|
+
return new _Railway({ mode: "sync", result: ok({}) });
|
|
258
|
+
}
|
|
259
|
+
/** Start a sync workflow with the given context as the initial state. */
|
|
260
|
+
static context(context) {
|
|
261
|
+
return new _Railway({ mode: "sync", result: ok(context) });
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Start a sync workflow with a throwing function — `onThrow` maps any
|
|
265
|
+
* exception to a typed error.
|
|
266
|
+
*/
|
|
267
|
+
static fromSync(key, fn, onThrow) {
|
|
268
|
+
return _Railway.empty().fromSync(key, fn, onThrow);
|
|
269
|
+
}
|
|
270
|
+
/** Start a sync workflow with a `Result`-returning function. */
|
|
271
|
+
static fromResult(key, fn) {
|
|
272
|
+
return _Railway.empty().fromResult(key, fn);
|
|
273
|
+
}
|
|
274
|
+
/** Start an async workflow with a `PromiseLike`-returning function. */
|
|
275
|
+
static fromPromise(key, fn, onReject) {
|
|
276
|
+
return _Railway.empty().fromPromise(key, fn, onReject);
|
|
277
|
+
}
|
|
278
|
+
/** Start an async workflow with a `ResultAsync`-returning function. */
|
|
279
|
+
static fromAsync(key, fn) {
|
|
280
|
+
return _Railway.empty().fromAsync(key, fn);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Pure sync derivation — `fn` must not throw. Use {@link fromSync} for
|
|
284
|
+
* throwing transforms.
|
|
285
|
+
*/
|
|
286
|
+
derive(key, fn) {
|
|
287
|
+
return this.fromResult(key, (ctx) => ok(fn(ctx)));
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Throwing sync transform. Adds `{ [key]: T }` to context; converts any
|
|
291
|
+
* exception to `Err<F>` via `onThrow`.
|
|
292
|
+
*/
|
|
293
|
+
fromSync(key, fn, onThrow) {
|
|
294
|
+
return this.fromResult(key, (ctx) => trySync(fn, onThrow)(ctx));
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Sync `Result`-returning step. Adds `{ [key]: T }` to context on `Ok`;
|
|
298
|
+
* short-circuits the workflow on `Err`. Error union widens to `E | F`.
|
|
299
|
+
*/
|
|
300
|
+
fromResult(key, fn) {
|
|
301
|
+
if (this.state.mode === "sync") {
|
|
302
|
+
const current = this.state.result;
|
|
303
|
+
if (isErr(current)) {
|
|
304
|
+
return new _Railway({ mode: "sync", result: err(current.error) });
|
|
305
|
+
}
|
|
306
|
+
const next = fn(current.value);
|
|
307
|
+
if (isErr(next)) {
|
|
308
|
+
return new _Railway({ mode: "sync", result: err(next.error) });
|
|
309
|
+
}
|
|
310
|
+
return new _Railway({
|
|
311
|
+
mode: "sync",
|
|
312
|
+
result: ok(addField(current.value, key, next.value))
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
return new _Railway({
|
|
316
|
+
mode: "async",
|
|
317
|
+
result: this.state.result.flatMap(
|
|
318
|
+
(ctx) => ResultAsync.fromResult(fn(ctx)).map((value) => addField(ctx, key, value))
|
|
319
|
+
)
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Promise-returning step — upgrades the workflow to async mode. Reject
|
|
324
|
+
* reasons go through `onReject` to become typed `Err<F>`.
|
|
325
|
+
*/
|
|
326
|
+
fromPromise(key, fn, onReject) {
|
|
327
|
+
return this.fromAsync(key, (ctx) => ResultAsync.fromPromise(fn(ctx), onReject));
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* `ResultAsync`-returning step — upgrades the workflow to async mode.
|
|
331
|
+
* Already-typed error: no mapper needed.
|
|
332
|
+
*/
|
|
333
|
+
fromAsync(key, fn) {
|
|
334
|
+
const current = this.state.mode === "sync" ? liftResult(this.state.result) : this.state.result;
|
|
335
|
+
return new _Railway({
|
|
336
|
+
mode: "async",
|
|
337
|
+
result: current.flatMap((ctx) => fn(ctx).map((value) => addField(ctx, key, value)))
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Narrow a nullable context field into a required non-null field. If the
|
|
342
|
+
* source field is `null` / `undefined`, the workflow short-circuits with
|
|
343
|
+
* `onMissing(ctx)`.
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```ts
|
|
347
|
+
* .fromPromise("row", ({ id }) => db.users.findFirst({ where: eq(users.id, id) }))
|
|
348
|
+
* .require("user", "row", ({ id }) => ({ kind: "not_found" as const, id }))
|
|
349
|
+
* // user is now User (non-null), not User | null
|
|
350
|
+
* ```
|
|
351
|
+
*/
|
|
352
|
+
require(key, source, onMissing) {
|
|
353
|
+
return this.fromResult(key, (ctx) => {
|
|
354
|
+
const value = ctx[source];
|
|
355
|
+
return value == null ? err(onMissing(ctx)) : ok(value);
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Run independent `ResultAsync` branches concurrently and merge their
|
|
360
|
+
* named outputs back into context. Upgrades the workflow to async mode.
|
|
361
|
+
* On multiple failures, the first `Err` in record-iteration order wins.
|
|
362
|
+
*
|
|
363
|
+
* @example
|
|
364
|
+
* ```ts
|
|
365
|
+
* .parallel({
|
|
366
|
+
* recent: ({ userId }) => loadRecent(userId),
|
|
367
|
+
* metrics: ({ userId }) => loadMetrics(userId),
|
|
368
|
+
* })
|
|
369
|
+
* // ctx now has { ..., recent, metrics }
|
|
370
|
+
* ```
|
|
371
|
+
*/
|
|
372
|
+
parallel(branches) {
|
|
373
|
+
const current = this.state.mode === "sync" ? liftResult(this.state.result) : this.state.result;
|
|
374
|
+
return new _Railway({
|
|
375
|
+
mode: "async",
|
|
376
|
+
result: current.flatMap(
|
|
377
|
+
(ctx) => ResultAsync.combineTupleParallel(
|
|
378
|
+
Object.entries(branches).map(([, branch]) => branch(ctx))
|
|
379
|
+
).map((values) => {
|
|
380
|
+
const next = { ...ctx };
|
|
381
|
+
Object.keys(branches).forEach((key, index) => {
|
|
382
|
+
next[key] = values[index];
|
|
383
|
+
});
|
|
384
|
+
return next;
|
|
385
|
+
})
|
|
386
|
+
)
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Project the final context into the workflow's output type. Hides the
|
|
391
|
+
* internal context shape from callers.
|
|
392
|
+
*/
|
|
393
|
+
select(fn) {
|
|
394
|
+
if (this.state.mode === "sync") {
|
|
395
|
+
const current = this.state.result;
|
|
396
|
+
return isErr(current) ? err(current.error) : ok(fn(current.value));
|
|
397
|
+
}
|
|
398
|
+
return this.state.result.map(fn);
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Return the accumulated context as-is. Use when downstream code needs
|
|
402
|
+
* every named field; prefer {@link select} when you can project to a DTO.
|
|
403
|
+
*/
|
|
404
|
+
done() {
|
|
405
|
+
return this.state.mode === "sync" ? this.state.result : this.state.result;
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
function railway(input, ...steps) {
|
|
409
|
+
let current = Railway.context({ input });
|
|
410
|
+
for (const step of steps) {
|
|
411
|
+
const applyStep = step;
|
|
412
|
+
current = applyStep(current);
|
|
413
|
+
}
|
|
414
|
+
return current;
|
|
415
|
+
}
|
|
416
|
+
var parseWith = (parser, onThrow) => ({
|
|
417
|
+
as: (key) => (workflow) => workflow.fromSync(key, ({ input }) => parseWithParser(parser, input), onThrow)
|
|
418
|
+
});
|
|
419
|
+
var fromSyncNamed = (key, fn, onThrow) => (workflow) => workflow.fromSync(key, fn, onThrow);
|
|
420
|
+
var fromResultNamed = (key, fn) => (workflow) => workflow.fromResult(key, fn);
|
|
421
|
+
var fromPromiseNamed = (key, fn, onReject) => (workflow) => workflow.fromPromise(key, fn, onReject);
|
|
422
|
+
var fromAsyncNamed = (key, fn) => (workflow) => workflow.fromAsync(key, fn);
|
|
423
|
+
var deriveNamed = (key, fn) => (workflow) => workflow.derive(key, fn);
|
|
424
|
+
var requireNamed = (key, source, onMissing) => (workflow) => workflow.require(key, source, onMissing);
|
|
425
|
+
var parallelNamed = (branches) => (workflow) => {
|
|
426
|
+
const typedBranches = branches;
|
|
427
|
+
return workflow.parallel(typedBranches);
|
|
428
|
+
};
|
|
429
|
+
var select = (fn) => (workflow) => workflow.select(fn);
|
|
430
|
+
|
|
431
|
+
exports.Railway = Railway;
|
|
432
|
+
exports.deriveNamed = deriveNamed;
|
|
433
|
+
exports.fromAsyncNamed = fromAsyncNamed;
|
|
434
|
+
exports.fromPromiseNamed = fromPromiseNamed;
|
|
435
|
+
exports.fromResultNamed = fromResultNamed;
|
|
436
|
+
exports.fromSyncNamed = fromSyncNamed;
|
|
437
|
+
exports.parallelNamed = parallelNamed;
|
|
438
|
+
exports.parseWith = parseWith;
|
|
439
|
+
exports.railway = railway;
|
|
440
|
+
exports.requireNamed = requireNamed;
|
|
441
|
+
exports.select = select;
|
|
442
|
+
//# sourceMappingURL=railway.cjs.map
|
|
443
|
+
//# sourceMappingURL=railway.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/result.ts","../src/types.ts","../src/async.ts","../src/railway.ts"],"names":[],"mappings":"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","file":"railway.cjs","sourcesContent":["import type { Err, Ok, Result } from \"./types.js\";\n\nexport type { Err, Ok, Result } from \"./types.js\";\n\n/**\n * Lifts a value into the success track.\n *\n * @example\n * ```ts\n * const r = ok(42); // Result<number, never>\n * const typed: Result<number, \"parse\"> = ok(1);\n * ```\n */\nexport const ok = <T, E = never>(value: T): Result<T, E> => ({\n _tag: \"Ok\",\n value,\n});\n\n/**\n * Lifts a value into the error track.\n *\n * @example\n * ```ts\n * const r = err({ kind: \"parse\", message: \"bad json\" });\n * // Result<never, { kind: \"parse\"; message: string }>\n * ```\n */\nexport const err = <T = never, E = unknown>(error: E): Result<T, E> => ({\n _tag: \"Err\",\n error,\n});\n\n/**\n * Type-narrowing predicate: returns `true` when the result is `Ok`.\n *\n * @example\n * ```ts\n * if (isOk(r)) {\n * console.log(r.value); // narrowed to Ok branch\n * }\n * ```\n */\nexport const isOk = <T, E>(result: Result<T, E>): result is Ok<T, E> => result._tag === \"Ok\";\n\n/**\n * Type-narrowing predicate: returns `true` when the result is `Err`.\n *\n * @example\n * ```ts\n * if (isErr(r)) {\n * metrics.inc(\"error\", { kind: r.error.kind });\n * }\n * ```\n */\nexport const isErr = <T, E>(result: Result<T, E>): result is Err<T, E> => result._tag === \"Err\";\n\n/** Fantasy Land `of` — alias of {@link ok}. */\nexport const of = ok;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Dual-form helpers — each export accepts either shape:\n// data-first: `map(result, fn)`\n// curried: `map(fn)(result)`\n// Arity at the call site selects the overload.\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst mapImpl = <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> =>\n isOk(result) ? ok(fn(result.value)) : err(result.error);\n\n/**\n * Transform the `Ok` value, passing `Err` through unchanged. Dual-form:\n * call data-first or curried (for use with {@link pipe}).\n *\n * @example\n * ```ts\n * map(ok(2), (n) => n * 3); // Ok 6 — data-first\n * pipe(ok(\"x\"), map((s) => s.length));// Ok 1 — curried\n * ```\n */\nexport function map<T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;\nexport function map<T, U>(fn: (value: T) => U): <E>(result: Result<T, E>) => Result<U, E>;\nexport function map(\n ...args: [Result<unknown, unknown>, (value: unknown) => unknown] | [(value: unknown) => unknown]\n): unknown {\n if (args.length === 2) return mapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => mapImpl(result, fn);\n}\n\nconst mapErrImpl = <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F> =>\n isErr(result) ? err(fn(result.error)) : ok(result.value);\n\n/**\n * Transform the `Err` value, passing `Ok` through unchanged. Useful for\n * unifying heterogeneous failure types into one app-level union.\n *\n * @example\n * ```ts\n * type AppError = { kind: \"http\"; status: number } | { kind: \"parse\" };\n * pipe(\n * fetchSync(url), // Result<Body, { status: number }>\n * mapErr((e): AppError => ({ kind: \"http\", status: e.status })),\n * );\n * ```\n */\nexport function mapErr<T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F>;\nexport function mapErr<E, F>(fn: (error: E) => F): <T>(result: Result<T, E>) => Result<T, F>;\nexport function mapErr(\n ...args: [Result<unknown, unknown>, (error: unknown) => unknown] | [(error: unknown) => unknown]\n): unknown {\n if (args.length === 2) return mapErrImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => mapErrImpl(result, fn);\n}\n\nconst bimapImpl = <T, U, E, F>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n): Result<U, F> => (isOk(result) ? ok(onOk(result.value)) : err(onErr(result.error)));\n\n/**\n * Transform both tracks at once — `Ok` via `onOk`, `Err` via `onErr`.\n * Equivalent to `mapErr(onErr)(map(onOk)(result))` but in one pass.\n *\n * @example\n * ```ts\n * bimap(parsed, (cfg) => cfg.name, (e) => ({ kind: \"input\", cause: e }));\n * ```\n */\nexport function bimap<T, U, E, F>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n): Result<U, F>;\nexport function bimap<T, U, E, F>(\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n): (result: Result<T, E>) => Result<U, F>;\nexport function bimap(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => unknown, (error: unknown) => unknown]\n | [(value: unknown) => unknown, (error: unknown) => unknown]\n): unknown {\n if (args.length === 3) return bimapImpl(args[0], args[1], args[2]);\n const [onOk, onErr] = args;\n return (result: Result<unknown, unknown>) => bimapImpl(result, onOk, onErr);\n}\n\nconst flatMapImpl = <T, U, E, F>(\n result: Result<T, E>,\n fn: (value: T) => Result<U, F>,\n): Result<U, E | F> => (isOk(result) ? fn(result.value) : err(result.error));\n\n/**\n * Canonical bind (Fantasy Land `chain`). Chains a Result-returning step,\n * widening the error union to `E | F`. Short-circuits on `Err`.\n *\n * @example\n * ```ts\n * flatMap(parseInput(raw), (data) =>\n * data.id != null ? ok(data) : err({ kind: \"missing_id\" as const }),\n * );\n * // Result<Data, ParseError | { kind: \"missing_id\" }>\n * ```\n */\nexport function flatMap<T, U, E, F>(\n result: Result<T, E>,\n fn: (value: T) => Result<U, F>,\n): Result<U, E | F>;\nexport function flatMap<T, U, F>(\n fn: (value: T) => Result<U, F>,\n): <E>(result: Result<T, E>) => Result<U, E | F>;\nexport function flatMap(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => Result<unknown, unknown>]\n | [(value: unknown) => Result<unknown, unknown>]\n): unknown {\n if (args.length === 2) return flatMapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => flatMapImpl(result, fn);\n}\n\nconst recoverImpl = <T, E, F>(\n result: Result<T, E>,\n fn: (error: E) => Result<T, F>,\n): Result<T, F> => (isErr(result) ? fn(result.error) : ok(result.value));\n\n/**\n * Error-track bind — runs `fn` only when the result is `Err`, allowing\n * a failed workflow to recover to `Ok` or remap the failure. Mirror of\n * {@link flatMap} on the error channel.\n *\n * @example\n * ```ts\n * recover(networkResult, (e) =>\n * e.kind === \"rate_limit\" ? ok(cachedBody) : err(e),\n * );\n * ```\n */\nexport function recover<T, E, F>(\n result: Result<T, E>,\n fn: (error: E) => Result<T, F>,\n): Result<T, F>;\nexport function recover<T, E, F>(\n fn: (error: E) => Result<T, F>,\n): (result: Result<T, E>) => Result<T, F>;\nexport function recover(\n ...args:\n | [Result<unknown, unknown>, (error: unknown) => Result<unknown, unknown>]\n | [(error: unknown) => Result<unknown, unknown>]\n): unknown {\n if (args.length === 2) return recoverImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => recoverImpl(result, fn);\n}\n\nconst tapImpl = <T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E> => {\n if (isOk(result)) fn(result.value);\n return result;\n};\n\n/**\n * Observe the `Ok` value for side effects (logging, metrics) without\n * changing the carried value. Passes `Err` through untouched.\n *\n * @example\n * ```ts\n * pipe(\n * parseConfig(raw),\n * tap((cfg) => log.info({ msg: \"parsed\", name: cfg.name })),\n * flatMap(validate),\n * );\n * ```\n */\nexport function tap<T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E>;\nexport function tap<T>(fn: (value: T) => void): <E>(result: Result<T, E>) => Result<T, E>;\nexport function tap(\n ...args: [Result<unknown, unknown>, (value: unknown) => void] | [(value: unknown) => void]\n): unknown {\n if (args.length === 2) return tapImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => tapImpl(result, fn);\n}\n\nconst tapErrImpl = <T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E> => {\n if (isErr(result)) fn(result.error);\n return result;\n};\n\n/**\n * Observe the `Err` value for side effects (logging, metrics) without\n * changing the carried error. Passes `Ok` through untouched.\n *\n * @example\n * ```ts\n * pipe(\n * loadUser(id),\n * tapErr((e) => metrics.inc(\"user.load.fail\", { kind: e.kind })),\n * );\n * ```\n */\nexport function tapErr<T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E>;\nexport function tapErr<E>(fn: (error: E) => void): <T>(result: Result<T, E>) => Result<T, E>;\nexport function tapErr(\n ...args: [Result<unknown, unknown>, (error: unknown) => void] | [(error: unknown) => void]\n): unknown {\n if (args.length === 2) return tapErrImpl(args[0], args[1]);\n const fn = args[0];\n return (result: Result<unknown, unknown>) => tapErrImpl(result, fn);\n}\n\nconst matchImpl = <T, E, U>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): U => (isOk(result) ? onOk(result.value) : onErr(result.error));\n\n/**\n * Terminal collapse — fold both tracks into a single value. Dual-form:\n * 3-args data-first, 2-args curried for {@link pipe}. Returns whatever\n * the handlers return.\n *\n * For files that also import `match` from `ts-pattern`, the\n * collision-free alias {@link matchResult} is identical.\n *\n * @example\n * ```ts\n * const html = match(parsed, (cfg) => render(cfg), (e) => renderError(e));\n * ```\n */\nexport function match<T, E, U>(\n result: Result<T, E>,\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): U;\nexport function match<T, E, U>(\n onOk: (value: T) => U,\n onErr: (error: E) => U,\n): (result: Result<T, E>) => U;\nexport function match(\n ...args:\n | [Result<unknown, unknown>, (value: unknown) => unknown, (error: unknown) => unknown]\n | [(value: unknown) => unknown, (error: unknown) => unknown]\n): unknown {\n if (args.length === 3) return matchImpl(args[0], args[1], args[2]);\n const [onOk, onErr] = args;\n return (result: Result<unknown, unknown>) => matchImpl(result, onOk, onErr);\n}\n\n/** Collision-free alias for files that also import `match` from ts-pattern. */\nexport const matchResult = match;\n\n/**\n * Curried collapse with named slots — escape valve when positional `match`\n * order is unclear at the call site (e.g. when both handlers return the same\n * type and a transposed `match(r, onErr, onOk)` would silently compile).\n */\nexport const fold =\n <T, E, U>(handlers: { readonly ok: (value: T) => U; readonly err: (error: E) => U }) =>\n (result: Result<T, E>): U =>\n matchImpl(result, handlers.ok, handlers.err);\n\n/**\n * Returns the `Ok` value, or `defaultValue` when the result is `Err`.\n *\n * @example\n * ```ts\n * unwrapOr(parsedSetting, \"default-value\");\n * ```\n */\nexport const unwrapOr = <T, E>(result: Result<T, E>, defaultValue: T): T =>\n isOk(result) ? result.value : defaultValue;\n\n/** Test/assert helper — throws the original Err value when called on Err. */\nexport function unwrapOk<T, E>(result: Result<T, E>): T {\n if (isErr(result)) throw result.error;\n return result.value;\n}\n\n/** Test/assert helper — throws TypeError when called on Ok. */\nexport function unwrapErr<T, E>(result: Result<T, E>): E {\n if (isOk(result)) throw new TypeError(\"unwrapErr called on Ok\");\n return result.error;\n}\n\n/** Wrap a throwing sync function — neverthrow `Result.fromThrowable` */\nexport function trySync<A extends readonly unknown[], T, E>(\n fn: (...args: A) => T,\n onThrow: (error: unknown) => E,\n): (...args: A) => Result<T, E>;\nexport function trySync<F extends (...args: never) => unknown, E>(\n fn: F,\n onThrow: (error: unknown) => E,\n): (...args: Parameters<F>) => Result<ReturnType<F>, E>;\nexport function trySync(\n fn: (...args: never) => unknown,\n onThrow: (error: unknown) => unknown,\n): (...args: never) => Result<unknown, unknown> {\n return (...args: never) => {\n try {\n return ok(fn(...args));\n } catch (error) {\n return err(onThrow(error));\n }\n };\n}\n\n/** First failure wins; otherwise collects values in order */\nexport const combine = <T, E>(results: readonly Result<T, E>[]): Result<T[], E> => {\n const values: T[] = [];\n for (const result of results) {\n if (isErr(result)) return err(result.error);\n values.push(result.value);\n }\n return ok(values);\n};\n\n/** Tuple-preserving combine (neverthrow-style) */\nexport const combineTuple = <const R extends readonly Result<unknown, unknown>[]>(\n results: R,\n): CombineTuple<R> => {\n const values: unknown[] = [];\n for (const result of results) {\n if (isErr(result)) return err(result.error) as CombineTuple<R>;\n values.push(result.value);\n }\n return ok(values) as CombineTuple<R>;\n};\n\ntype _OkValue<R> = R extends { _tag: \"Ok\"; readonly value: infer T } ? T : never;\ntype _ErrValue<R> = R extends { _tag: \"Err\"; readonly error: infer E } ? E : never;\n\ntype CombineTuple<R extends readonly Result<unknown, unknown>[]> = Result<\n { [K in keyof R]: _OkValue<R[K]> },\n { [K in keyof R]: _ErrValue<R[K]> }[number]\n>;\n\n/**\n * Variadic value-first pipe — threads `value` through up to nine unary fns.\n *\n * ```ts\n * pipe(\n * parseConfig(raw),\n * map((cfg) => cfg.name),\n * flatMap((name) => name ? ok(name) : err({ kind: \"empty\" })),\n * tap(log),\n * );\n * ```\n */\nexport function pipe<A>(value: A): A;\nexport function pipe<A, B>(value: A, ab: (a: A) => B): B;\nexport function pipe<A, B, C>(value: A, ab: (a: A) => B, bc: (b: B) => C): C;\nexport function pipe<A, B, C, D>(value: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): D;\nexport function pipe<A, B, C, D, E>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n): E;\nexport function pipe<A, B, C, D, E, F>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n): F;\nexport function pipe<A, B, C, D, E, F, G>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n): G;\nexport function pipe<A, B, C, D, E, F, G, H>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n gh: (g: G) => H,\n): H;\nexport function pipe<A, B, C, D, E, F, G, H, I>(\n value: A,\n ab: (a: A) => B,\n bc: (b: B) => C,\n cd: (c: C) => D,\n de: (d: D) => E,\n ef: (e: E) => F,\n fg: (f: F) => G,\n gh: (g: G) => H,\n hi: (h: H) => I,\n): I;\nexport function pipe(value: unknown, ...fns: ReadonlyArray<(x: unknown) => unknown>): unknown {\n let acc = value;\n for (const fn of fns) {\n acc = fn(acc);\n }\n return acc;\n}\n","/** Tagged success/failure — no classes, tree-shake friendly. */\nexport type Result<T, E> =\n | { readonly _tag: \"Ok\"; readonly value: T }\n | { readonly _tag: \"Err\"; readonly error: E };\n\nexport type Ok<T, E = never> = Extract<Result<T, E>, { _tag: \"Ok\" }>;\nexport type Err<T, E> = Extract<Result<T, E>, { _tag: \"Err\" }>;\n\n/** Thrown defect mapped when {@link fromAsync} has no `onDefect` */\nexport class UnexpectedError extends Error {\n constructor(\n message: string,\n override readonly cause?: unknown,\n ) {\n super(message);\n this.name = \"UnexpectedError\";\n }\n}\n","import { err, isErr, map, mapErr, ok } from \"./result.js\";\nimport type { Result } from \"./types.js\";\nimport { UnexpectedError } from \"./types.js\";\n\ntype PromiseFactory<T, E> = () => Promise<Result<T, E>>;\ntype AsyncOk<R> = R extends ResultAsync<infer T, unknown> ? T : never;\ntype AsyncErr<R> = R extends ResultAsync<unknown, infer E> ? E : never;\ntype CombineTupleAsync<R extends readonly ResultAsync<unknown, unknown>[]> = ResultAsync<\n { [K in keyof R]: AsyncOk<R[K]> },\n { [K in keyof R]: AsyncErr<R[K]> }[number]\n>;\n\nconst liftPromiseResult = async <T, E>(\n promise: Promise<Result<T, E>>,\n onDefect: (error: unknown) => E | UnexpectedError,\n): Promise<Result<T, E | UnexpectedError>> => {\n try {\n const result = await promise;\n if (isErr(result)) {\n return result;\n }\n const inner = result.value;\n if (inner && typeof inner === \"object\" && \"_tag\" in inner) {\n if (inner._tag === \"Ok\" || inner._tag === \"Err\") {\n return inner as unknown as Result<T, E | UnexpectedError>;\n }\n }\n return result;\n } catch (error) {\n return err(onDefect(error));\n }\n};\n\n/**\n * Async result — public API never exposes `Promise<Result<…>>` directly;\n * await via `.resolve()` or `.match()`.\n */\nexport class ResultAsync<T, E> {\n protected constructor(protected readonly run: PromiseFactory<T, E>) {}\n\n static fromResult<T, E>(result: Result<T, E>): ResultAsync<T, E> {\n return new ResultAsync(async () => result);\n }\n\n static fromPromise<T, E>(\n promise: PromiseLike<T>,\n onReject: (error: unknown) => E,\n ): ResultAsync<T, E> {\n return new ResultAsync(async () => {\n try {\n return ok(await promise);\n } catch (error) {\n return err(onReject(error));\n }\n });\n }\n\n static fromSafePromise<T, E = never>(promise: PromiseLike<T>): ResultAsync<T, E> {\n return new ResultAsync(async () => ok(await promise));\n }\n\n /**\n * Defers work until {@link resolve}. Unlike {@link fromPromise}, nothing runs\n * until the `ResultAsync` is resolved (e.g. by `combineTuple` / `combineTupleParallel`).\n */\n static defer<T, E>(fn: () => Promise<Result<T, E>>): ResultAsync<T, E> {\n return new ResultAsync(fn);\n }\n\n static ok<T>(value: T): ResultAsync<T, never>;\n static ok<T, E>(value: T): ResultAsync<T, E>;\n static ok<T, E = never>(value: T): ResultAsync<T, E> {\n return new ResultAsync(async () => ok(value));\n }\n\n static err<T = never, E = unknown>(error: E): ResultAsync<T, E> {\n return new ResultAsync(async () => err(error));\n }\n\n /** @see {@link fromAsync} from `@onrails/result/interop` */\n static fromResultPromise<T, E>(\n promise: Promise<Result<T, E>>,\n onDefect?: (error: unknown) => E | UnexpectedError,\n ): ResultAsync<T, E | UnexpectedError> {\n const mapDefect =\n onDefect ?? ((error: unknown) => new UnexpectedError(\"Unexpected async defect\", error));\n return new ResultAsync(() => liftPromiseResult(promise, mapDefect));\n }\n\n static combine<T, E>(results: readonly ResultAsync<T, E>[]): ResultAsync<T[], E> {\n return new ResultAsync(async () => {\n const values: T[] = [];\n for (const ra of results) {\n const result = await ra.resolve();\n if (isErr(result)) {\n return err(result.error);\n }\n values.push(result.value);\n }\n return ok(values);\n });\n }\n\n static combineTuple<const R extends readonly ResultAsync<unknown, unknown>[]>(\n results: R,\n ): CombineTupleAsync<R> {\n return new ResultAsync(async () => {\n const values: unknown[] = [];\n for (const ra of results) {\n const result = await ra.resolve();\n if (isErr(result)) {\n return err(result.error) as Result<\n { [K in keyof R]: AsyncOk<R[K]> },\n { [K in keyof R]: AsyncErr<R[K]> }[number]\n >;\n }\n values.push(result.value);\n }\n return ok(values) as Result<\n { [K in keyof R]: AsyncOk<R[K]> },\n { [K in keyof R]: AsyncErr<R[K]> }[number]\n >;\n }) as CombineTupleAsync<R>;\n }\n\n /**\n * Like {@link combineTuple}, but starts every branch before awaiting (wall-clock\n * parallel for independent IO). On failure, returns the first `Err` in input order.\n */\n static combineTupleParallel<const R extends readonly ResultAsync<unknown, unknown>[]>(\n results: R,\n ): CombineTupleAsync<R> {\n return new ResultAsync(async () => {\n const settled = await Promise.all(results.map((ra) => ra.resolve()));\n const values: unknown[] = [];\n for (const result of settled) {\n if (isErr(result)) {\n return err(result.error) as Result<\n { [K in keyof R]: AsyncOk<R[K]> },\n { [K in keyof R]: AsyncErr<R[K]> }[number]\n >;\n }\n values.push(result.value);\n }\n return ok(values) as Result<\n { [K in keyof R]: AsyncOk<R[K]> },\n { [K in keyof R]: AsyncErr<R[K]> }[number]\n >;\n }) as CombineTupleAsync<R>;\n }\n\n map<U>(fn: (value: T) => U): ResultAsync<U, E> {\n return new ResultAsync(async () => map(await this.run(), fn));\n }\n\n mapErr<F>(fn: (error: E) => F): ResultAsync<T, F> {\n return new ResultAsync(async () => mapErr(await this.run(), fn));\n }\n\n flatMap<U, F = E>(\n fn: (value: T) => ResultAsync<U, F> | Result<U, F> | { inner: Result<U, F> },\n ): ResultAsync<U, E | F> {\n return new ResultAsync(async () => {\n const first = await this.run();\n if (isErr(first)) {\n return err(first.error) as Result<U, E | F>;\n }\n const next = fn(first.value);\n if (next instanceof ResultAsync) {\n return next.resolve() as Promise<Result<U, E | F>>;\n }\n if (isResultLike(next)) {\n return next as Result<U, E | F>;\n }\n if (isCompatLike(next)) {\n return next.inner as Result<U, E | F>;\n }\n return next as Result<U, E | F>;\n });\n }\n\n andThen<U, F = E>(\n fn: (value: T) => ResultAsync<U, F> | Result<U, F> | { inner: Result<U, F> },\n ): ResultAsync<U, E | F> {\n return this.flatMap(fn);\n }\n\n chain<U, F = E>(\n fn: (value: T) => ResultAsync<U, F> | Result<U, F> | { inner: Result<U, F> },\n ): ResultAsync<U, E | F> {\n return this.flatMap(fn);\n }\n\n recover<F>(fn: (error: E) => ResultAsync<T, F> | Result<T, F>): ResultAsync<T, F> {\n return new ResultAsync(async () => {\n const first = await this.run();\n if (!isErr(first)) {\n return first as Result<T, F>;\n }\n const next = fn(first.error);\n if (next instanceof ResultAsync) {\n return next.resolve();\n }\n return next;\n });\n }\n\n orElse<F>(fn: (error: E) => ResultAsync<T, F> | Result<T, F>): ResultAsync<T, F> {\n return this.recover(fn);\n }\n\n tap(fn: (value: T) => void): ResultAsync<T, E> {\n return new ResultAsync(async () => {\n const result = await this.run();\n if (!isErr(result)) {\n fn(result.value);\n }\n return result;\n });\n }\n\n tapErr(fn: (error: E) => void): ResultAsync<T, E> {\n return new ResultAsync(async () => {\n const result = await this.run();\n if (isErr(result)) {\n fn(result.error);\n }\n return result;\n });\n }\n\n unwrapOr<U>(defaultValue: U): Promise<T | U> {\n return this.run().then((result) => (isErr(result) ? defaultValue : result.value));\n }\n\n isOk(): Promise<boolean> {\n return this.run().then((result) => !isErr(result));\n }\n\n isErr(): Promise<boolean> {\n return this.run().then((result) => isErr(result));\n }\n\n match<U1, U2 = U1>(onOk: (value: T) => U1, onErr: (error: E) => U2): Promise<U1 | U2> {\n return this.run().then((result) =>\n isErr(result) ? onErr(result.error) : onOk(result.value),\n ) as Promise<U1 | U2>;\n }\n\n resolve(): Promise<Result<T, E>> {\n return this.run();\n }\n\n /**\n * Thenable shim — `await ra` resolves to a bare tagged-union `Result<T, E>`.\n * Narrow with `isOk(r)` / `isErr(r)` to read `.value` / `.error`.\n */\n // biome-ignore lint/suspicious/noThenProperty: makes ResultAsync awaitable\n then<R1 = Result<T, E>, R2 = never>(\n onfulfilled?: ((value: Result<T, E>) => R1 | PromiseLike<R1>) | undefined | null,\n onrejected?: ((reason: unknown) => R2 | PromiseLike<R2>) | undefined | null,\n ): Promise<R1 | R2> {\n return this.run().then(\n (r) => (onfulfilled ? onfulfilled(r) : (r as unknown as R1)),\n onrejected ?? undefined,\n );\n }\n}\n\nfunction isResultLike<U, F>(v: unknown): v is Result<U, F> {\n return (\n typeof v === \"object\" &&\n v !== null &&\n \"_tag\" in v &&\n ((v as { _tag: unknown })._tag === \"Ok\" || (v as { _tag: unknown })._tag === \"Err\")\n );\n}\n\nfunction isCompatLike<U, F>(v: unknown): v is { inner: Result<U, F> } {\n return (\n typeof v === \"object\" &&\n v !== null &&\n \"inner\" in v &&\n isResultLike((v as { inner: unknown }).inner)\n );\n}\n\n/**\n * Lifts a value into an `Ok` async result.\n *\n * @example\n * ```ts\n * const r = okAsync(42); // ResultAsync<number, never>\n * ```\n */\nexport const okAsync = ResultAsync.ok;\n\n/**\n * Lifts a value into an `Err` async result.\n *\n * @example\n * ```ts\n * const r = errAsync({ kind: \"not_found\" as const });\n * ```\n */\nexport const errAsync = ResultAsync.err;\n\n/**\n * Wraps a `PromiseLike<T>` into a {@link ResultAsync}. Reject reasons go\n * through `onReject` to become typed `Err`s; success becomes `Ok<T>`.\n *\n * @example\n * ```ts\n * const body = fromPromise(\n * fetch(url).then((r) => r.text()),\n * (e): NetworkError => ({ kind: \"network\", cause: String(e) }),\n * );\n * ```\n */\nexport const fromPromise = ResultAsync.fromPromise;\n\n/**\n * Wraps a `PromiseLike<T>` that **never rejects** into {@link ResultAsync}.\n * Skips the `onReject` mapper. Use only when the promise is provably safe.\n */\nexport const fromSafePromise = ResultAsync.fromSafePromise;\n\n/**\n * Heterogeneous async tuple combine — left-to-right, short-circuit on\n * first `Err` in input order. Preserves tuple positions so destructuring\n * stays type-safe.\n *\n * @example\n * ```ts\n * const combined = sequenceTupleAsync([loadCfg(), loadCatalog()] as const);\n * // ResultAsync<readonly [Cfg, Catalog], CfgError | CatalogError>\n * ```\n */\nexport const sequenceTupleAsync = ResultAsync.combineTuple;\n\n/**\n * Heterogeneous async tuple combine — branches overlap in wall-clock time.\n * Returns the first `Err` in **input** order (not completion order).\n *\n * @example\n * ```ts\n * const combined = parallelTupleAsync([\n * loadProfile(id),\n * loadMetrics(id),\n * loadFlags(id),\n * ] as const);\n * // ResultAsync<readonly [Profile, Metrics, Flags], …>\n * ```\n */\nexport const parallelTupleAsync = ResultAsync.combineTupleParallel;\n\nconst toError = (error: unknown): Error =>\n error instanceof Error ? error : new Error(String(error));\n\n/**\n * Convenience wrapper over {@link fromPromise} with default `Error`\n * normalization. Call without `onReject` to get `ResultAsync<T, Error>`,\n * or pass a custom mapper for a typed error.\n *\n * @example\n * ```ts\n * // Default: rejection → Err(Error)\n * const a = tryAsync(db.users.insert(row));\n *\n * // Custom: typed error\n * const b = tryAsync(db.users.insert(row), (e): DbError => ({\n * kind: \"db\",\n * cause: e,\n * }));\n * ```\n */\nexport function tryAsync<T>(promise: PromiseLike<T>): ResultAsync<T, Error>;\nexport function tryAsync<T, E>(\n promise: PromiseLike<T>,\n onReject: (error: unknown) => E,\n): ResultAsync<T, E>;\nexport function tryAsync<T, E>(\n promise: PromiseLike<T>,\n onReject?: (error: unknown) => E,\n): ResultAsync<T, E | Error> {\n if (onReject) {\n return ResultAsync.fromPromise(promise, onReject);\n }\n return ResultAsync.fromPromise(promise, toError);\n}\n","import { ResultAsync } from \"./async.js\";\nimport { err, isErr, ok, trySync } from \"./result.js\";\nimport type { Result } from \"./types.js\";\n\n/**\n * Tracks whether a {@link Railway} workflow has crossed an async boundary.\n * Sync workflows return {@link Result}; async workflows return {@link ResultAsync}.\n */\nexport type RailwayMode = \"sync\" | \"async\";\n\n/**\n * Mode-aware output type for a {@link Railway} workflow: sync mode →\n * `Result<T, E>`, async mode → `ResultAsync<T, E>`.\n */\nexport type RailwayOutput<T, E, M extends RailwayMode> = M extends \"async\"\n ? ResultAsync<T, E>\n : Result<T, E>;\n\n/**\n * Initial context shape for a {@link railway} functional pipeline.\n * Wraps the raw input under the `input` key so subsequent named steps\n * can reference it via `ctx.input`.\n */\nexport type RailwayInput<I> = { readonly input: I };\n\ntype RailwayState<C extends object, E> =\n | { readonly mode: \"sync\"; readonly result: Result<C, E> }\n | { readonly mode: \"async\"; readonly result: ResultAsync<C, E> };\n\ntype BranchFn<C extends object> = (ctx: C) => ResultAsync<unknown, unknown>;\ntype BranchRecord = Record<string, (ctx: never) => ResultAsync<unknown, unknown>>;\ntype BranchOk<R> = R extends (ctx: never) => ResultAsync<infer T, infer _E> ? T : never;\ntype BranchErr<R> = R extends (ctx: never) => ResultAsync<infer _T, infer E> ? E : never;\ntype BranchInput<R> = R extends (ctx: infer C) => ResultAsync<unknown, unknown> ? C : never;\ntype ParallelInput<R extends BranchRecord> = BranchInput<R[keyof R]> & object;\ntype ParallelOutput<R extends BranchRecord> = {\n [K in keyof R]: BranchOk<R[K]>;\n};\ntype ParallelError<R extends BranchRecord> = BranchErr<R[keyof R]>;\ntype ParserLike<I, T> = { readonly parse: (input: I) => T } | ((input: I) => T);\ntype UnaryStep<I, O> = (input: I) => O;\n\nconst addField = <C extends object, K extends string, T>(\n ctx: C,\n key: K,\n value: T,\n): C & Record<K, T> => ({ ...ctx, [key]: value }) as C & Record<K, T>;\n\nconst liftResult = <C extends object, E>(result: Result<C, E>): ResultAsync<C, E> =>\n ResultAsync.fromResult(result);\n\nconst parseWithParser = <I, T>(parser: ParserLike<I, T>, input: I): T =>\n typeof parser === \"function\" ? parser(input) : parser.parse(input);\n\n/**\n * Named-context workflow builder. Each step appends a typed field to the\n * accumulating context object; the workflow tracks sync/async mode so the\n * final output type ({@link RailwayOutput}) is correct.\n *\n * Use `Railway` when a service workflow has 4+ named steps, mixed sync and\n * async boundaries, or independent async branches that should run in\n * parallel. For 1–2 step flows, prefer `flatMap` / `asyncAfter` directly.\n *\n * @example\n * ```ts\n * const summary = Railway\n * .fromSync(\"id\", () => IdSchema.parse(raw), toError)\n * .fromPromise(\"row\", ({ id }) => db.profiles.findFirst({ where: eq(profiles.id, id) }), toError)\n * .require(\"profile\", \"row\", ({ id }) => ({ kind: \"not_found\" as const, id }))\n * .derive(\"normalized\", ({ profile }) => normalizeProfile(profile))\n * .parallel({\n * artifacts: ({ normalized }) => loadArtifacts(normalized.id),\n * metrics: ({ normalized }) => loadMetrics(normalized.id),\n * })\n * .select(({ normalized, artifacts, metrics }) =>\n * toProfileSummary({ profile: normalized, artifacts, metrics }),\n * );\n * // ResultAsync<ProfileSummary, ParseError | DbError | NotFound>\n * ```\n */\nexport class Railway<C extends object, E, M extends RailwayMode> {\n private constructor(private readonly state: RailwayState<C, E>) {}\n\n /** Start an empty sync workflow with no fields in context. */\n static empty(): Railway<Record<never, never>, never, \"sync\"> {\n return new Railway({ mode: \"sync\", result: ok({}) });\n }\n\n /** Start a sync workflow with the given context as the initial state. */\n static context<C extends object>(context: C): Railway<C, never, \"sync\"> {\n return new Railway({ mode: \"sync\", result: ok(context) });\n }\n\n /**\n * Start a sync workflow with a throwing function — `onThrow` maps any\n * exception to a typed error.\n */\n static fromSync<K extends string, T, E>(\n key: K,\n fn: () => T,\n onThrow: (error: unknown) => E,\n ): Railway<Record<K, T>, E, \"sync\"> {\n return Railway.empty().fromSync(key, fn, onThrow);\n }\n\n /** Start a sync workflow with a `Result`-returning function. */\n static fromResult<K extends string, T, E>(\n key: K,\n fn: () => Result<T, E>,\n ): Railway<Record<K, T>, E, \"sync\"> {\n return Railway.empty().fromResult(key, fn);\n }\n\n /** Start an async workflow with a `PromiseLike`-returning function. */\n static fromPromise<K extends string, T, E>(\n key: K,\n fn: () => PromiseLike<T>,\n onReject: (error: unknown) => E,\n ): Railway<Record<K, T>, E, \"async\"> {\n return Railway.empty().fromPromise(key, fn, onReject);\n }\n\n /** Start an async workflow with a `ResultAsync`-returning function. */\n static fromAsync<K extends string, T, E>(\n key: K,\n fn: () => ResultAsync<T, E>,\n ): Railway<Record<K, T>, E, \"async\"> {\n return Railway.empty().fromAsync(key, fn);\n }\n\n /**\n * Pure sync derivation — `fn` must not throw. Use {@link fromSync} for\n * throwing transforms.\n */\n derive<K extends string, T>(key: K, fn: (ctx: C) => T): Railway<C & Record<K, T>, E, M> {\n return this.fromResult(key, (ctx) => ok(fn(ctx)));\n }\n\n /**\n * Throwing sync transform. Adds `{ [key]: T }` to context; converts any\n * exception to `Err<F>` via `onThrow`.\n */\n fromSync<K extends string, T, F>(\n key: K,\n fn: (ctx: C) => T,\n onThrow: (error: unknown) => F,\n ): Railway<C & Record<K, T>, E | F, M> {\n return this.fromResult(key, (ctx) => trySync(fn, onThrow)(ctx));\n }\n\n /**\n * Sync `Result`-returning step. Adds `{ [key]: T }` to context on `Ok`;\n * short-circuits the workflow on `Err`. Error union widens to `E | F`.\n */\n fromResult<K extends string, T, F>(\n key: K,\n fn: (ctx: C) => Result<T, F>,\n ): Railway<C & Record<K, T>, E | F, M> {\n if (this.state.mode === \"sync\") {\n const current = this.state.result;\n if (isErr(current)) {\n return new Railway({ mode: \"sync\", result: err(current.error) });\n }\n const next = fn(current.value);\n if (isErr(next)) {\n return new Railway({ mode: \"sync\", result: err(next.error) });\n }\n return new Railway({\n mode: \"sync\",\n result: ok(addField(current.value, key, next.value)),\n });\n }\n\n return new Railway({\n mode: \"async\",\n result: this.state.result.flatMap((ctx) =>\n ResultAsync.fromResult(fn(ctx)).map((value) => addField(ctx, key, value)),\n ),\n }) as Railway<C & Record<K, T>, E | F, M>;\n }\n\n /**\n * Promise-returning step — upgrades the workflow to async mode. Reject\n * reasons go through `onReject` to become typed `Err<F>`.\n */\n fromPromise<K extends string, T, F>(\n key: K,\n fn: (ctx: C) => PromiseLike<T>,\n onReject: (error: unknown) => F,\n ): Railway<C & Record<K, T>, E | F, \"async\"> {\n return this.fromAsync(key, (ctx) => ResultAsync.fromPromise(fn(ctx), onReject));\n }\n\n /**\n * `ResultAsync`-returning step — upgrades the workflow to async mode.\n * Already-typed error: no mapper needed.\n */\n fromAsync<K extends string, T, F>(\n key: K,\n fn: (ctx: C) => ResultAsync<T, F>,\n ): Railway<C & Record<K, T>, E | F, \"async\"> {\n const current = this.state.mode === \"sync\" ? liftResult(this.state.result) : this.state.result;\n\n return new Railway({\n mode: \"async\",\n result: current.flatMap((ctx) => fn(ctx).map((value) => addField(ctx, key, value))),\n });\n }\n\n /**\n * Narrow a nullable context field into a required non-null field. If the\n * source field is `null` / `undefined`, the workflow short-circuits with\n * `onMissing(ctx)`.\n *\n * @example\n * ```ts\n * .fromPromise(\"row\", ({ id }) => db.users.findFirst({ where: eq(users.id, id) }))\n * .require(\"user\", \"row\", ({ id }) => ({ kind: \"not_found\" as const, id }))\n * // user is now User (non-null), not User | null\n * ```\n */\n require<K extends string, S extends keyof C, F>(\n key: K,\n source: S,\n onMissing: (ctx: C) => F,\n ): Railway<C & Record<K, NonNullable<C[S]>>, E | F, M> {\n return this.fromResult(key, (ctx) => {\n const value = ctx[source];\n return value == null ? err(onMissing(ctx)) : ok(value as NonNullable<C[S]>);\n });\n }\n\n /**\n * Run independent `ResultAsync` branches concurrently and merge their\n * named outputs back into context. Upgrades the workflow to async mode.\n * On multiple failures, the first `Err` in record-iteration order wins.\n *\n * @example\n * ```ts\n * .parallel({\n * recent: ({ userId }) => loadRecent(userId),\n * metrics: ({ userId }) => loadMetrics(userId),\n * })\n * // ctx now has { ..., recent, metrics }\n * ```\n */\n parallel<R extends Record<string, BranchFn<C>>>(\n branches: R,\n ): Railway<C & ParallelOutput<R>, E | ParallelError<R>, \"async\"> {\n const current = this.state.mode === \"sync\" ? liftResult(this.state.result) : this.state.result;\n\n return new Railway({\n mode: \"async\",\n result: current.flatMap((ctx) =>\n ResultAsync.combineTupleParallel(\n Object.entries(branches).map(([, branch]) => branch(ctx)),\n ).map((values) => {\n const next = { ...ctx } as C & ParallelOutput<R>;\n Object.keys(branches).forEach((key, index) => {\n (next as Record<string, unknown>)[key] = values[index];\n });\n return next;\n }),\n ),\n }) as Railway<C & ParallelOutput<R>, E | ParallelError<R>, \"async\">;\n }\n\n /**\n * Project the final context into the workflow's output type. Hides the\n * internal context shape from callers.\n */\n select<T>(fn: (ctx: C) => T): RailwayOutput<T, E, M> {\n if (this.state.mode === \"sync\") {\n const current = this.state.result;\n return (isErr(current) ? err(current.error) : ok(fn(current.value))) as RailwayOutput<\n T,\n E,\n M\n >;\n }\n\n return this.state.result.map(fn) as RailwayOutput<T, E, M>;\n }\n\n /**\n * Return the accumulated context as-is. Use when downstream code needs\n * every named field; prefer {@link select} when you can project to a DTO.\n */\n done(): RailwayOutput<C, E, M> {\n return (this.state.mode === \"sync\" ? this.state.result : this.state.result) as RailwayOutput<\n C,\n E,\n M\n >;\n }\n}\n\n/**\n * Functional companion to {@link Railway} — point-free composition of\n * reusable workflow steps. Starts from `Railway.context({ input })` and\n * applies each step in order. Step factories live below: {@link parseWith},\n * {@link fromSyncNamed}, {@link fromResultNamed}, {@link fromPromiseNamed},\n * {@link fromAsyncNamed}, {@link deriveNamed}, {@link requireNamed},\n * {@link parallelNamed}, {@link select}.\n *\n * @example\n * ```ts\n * const summary = railway(\n * rawId,\n * parseWith(IdSchema, toError).as(\"id\"),\n * fromPromiseNamed(\"row\", ({ id }) => db.profiles.findFirst({ where: eq(profiles.id, id) }), toError),\n * requireNamed(\"profile\", \"row\", ({ id }) => ({ kind: \"not_found\" as const, id })),\n * deriveNamed(\"normalized\", ({ profile }) => normalizeProfile(profile)),\n * select(({ normalized }) => toProfileSummary(normalized)),\n * );\n * ```\n */\nexport function railway<I, A>(\n input: I,\n step1: UnaryStep<Railway<RailwayInput<I>, never, \"sync\">, A>,\n): A;\nexport function railway<I, A, B>(\n input: I,\n step1: UnaryStep<Railway<RailwayInput<I>, never, \"sync\">, A>,\n step2: UnaryStep<A, B>,\n): B;\nexport function railway<I, A, B, C>(\n input: I,\n step1: UnaryStep<Railway<RailwayInput<I>, never, \"sync\">, A>,\n step2: UnaryStep<A, B>,\n step3: UnaryStep<B, C>,\n): C;\nexport function railway<I, A, B, C, D>(\n input: I,\n step1: UnaryStep<Railway<RailwayInput<I>, never, \"sync\">, A>,\n step2: UnaryStep<A, B>,\n step3: UnaryStep<B, C>,\n step4: UnaryStep<C, D>,\n): D;\nexport function railway<I, A, B, C, D, E>(\n input: I,\n step1: UnaryStep<Railway<RailwayInput<I>, never, \"sync\">, A>,\n step2: UnaryStep<A, B>,\n step3: UnaryStep<B, C>,\n step4: UnaryStep<C, D>,\n step5: UnaryStep<D, E>,\n): E;\nexport function railway<I, A, B, C, D, E, F>(\n input: I,\n step1: UnaryStep<Railway<RailwayInput<I>, never, \"sync\">, A>,\n step2: UnaryStep<A, B>,\n step3: UnaryStep<B, C>,\n step4: UnaryStep<C, D>,\n step5: UnaryStep<D, E>,\n step6: UnaryStep<E, F>,\n): F;\nexport function railway<I, A, B, C, D, E, F, G>(\n input: I,\n step1: UnaryStep<Railway<RailwayInput<I>, never, \"sync\">, A>,\n step2: UnaryStep<A, B>,\n step3: UnaryStep<B, C>,\n step4: UnaryStep<C, D>,\n step5: UnaryStep<D, E>,\n step6: UnaryStep<E, F>,\n step7: UnaryStep<F, G>,\n): G;\nexport function railway<I, A, B, C, D, E, F, G, H>(\n input: I,\n step1: UnaryStep<Railway<RailwayInput<I>, never, \"sync\">, A>,\n step2: UnaryStep<A, B>,\n step3: UnaryStep<B, C>,\n step4: UnaryStep<C, D>,\n step5: UnaryStep<D, E>,\n step6: UnaryStep<E, F>,\n step7: UnaryStep<F, G>,\n step8: UnaryStep<G, H>,\n): H;\nexport function railway<I>(input: I, ...steps: readonly ((input: never) => unknown)[]): unknown {\n let current: unknown = Railway.context({ input });\n for (const step of steps) {\n const applyStep = step as (input: unknown) => unknown;\n current = applyStep(current);\n }\n return current;\n}\n\n/**\n * Step factory: parse the workflow input with a Zod-like schema (or a\n * unary parse function). Call `.as(key)` to name the output field.\n *\n * @example\n * ```ts\n * parseWith(IdSchema, toError).as(\"id\");\n * // Used as the first step in `railway(rawId, parseId, ...)`\n * ```\n */\nexport const parseWith = <I, T, E>(parser: ParserLike<I, T>, onThrow: (error: unknown) => E) => ({\n as:\n <K extends string>(key: K) =>\n <F, M extends RailwayMode>(\n workflow: Railway<RailwayInput<I>, F, M>,\n ): Railway<RailwayInput<I> & Record<K, T>, F | E, M> =>\n workflow.fromSync(key, ({ input }) => parseWithParser(parser, input), onThrow),\n});\n\n/**\n * Reusable wrapper around {@link Railway.fromSync}. Captures key + fn +\n * onThrow once; applies to any compatible workflow.\n */\nexport const fromSyncNamed =\n <K extends string, C extends object, T, E>(\n key: K,\n fn: (ctx: C) => T,\n onThrow: (error: unknown) => E,\n ) =>\n <I extends C, F, M extends RailwayMode>(\n workflow: Railway<I, F, M>,\n ): Railway<I & Record<K, T>, F | E, M> =>\n workflow.fromSync(key, fn, onThrow);\n\n/** Reusable wrapper around {@link Railway.fromResult}. */\nexport const fromResultNamed =\n <K extends string, C extends object, T, E>(key: K, fn: (ctx: C) => Result<T, E>) =>\n <I extends C, F, M extends RailwayMode>(\n workflow: Railway<I, F, M>,\n ): Railway<I & Record<K, T>, F | E, M> =>\n workflow.fromResult(key, fn);\n\n/**\n * Reusable wrapper around {@link Railway.fromPromise}. Upgrades the\n * workflow to async mode when applied.\n */\nexport const fromPromiseNamed =\n <K extends string, C extends object, T, E>(\n key: K,\n fn: (ctx: C) => PromiseLike<T>,\n onReject: (error: unknown) => E,\n ) =>\n <I extends C, F, M extends RailwayMode>(\n workflow: Railway<I, F, M>,\n ): Railway<I & Record<K, T>, F | E, \"async\"> =>\n workflow.fromPromise(key, fn, onReject);\n\n/** Reusable wrapper around {@link Railway.fromAsync}. */\nexport const fromAsyncNamed =\n <K extends string, C extends object, T, E>(key: K, fn: (ctx: C) => ResultAsync<T, E>) =>\n <I extends C, F, M extends RailwayMode>(\n workflow: Railway<I, F, M>,\n ): Railway<I & Record<K, T>, F | E, \"async\"> =>\n workflow.fromAsync(key, fn);\n\n/** Reusable wrapper around {@link Railway.derive} — pure sync derivation. */\nexport const deriveNamed =\n <K extends string, C extends object, T>(key: K, fn: (ctx: C) => T) =>\n <I extends C, E, M extends RailwayMode>(\n workflow: Railway<I, E, M>,\n ): Railway<I & Record<K, T>, E, M> =>\n workflow.derive(key, fn);\n\n/** Reusable wrapper around {@link Railway.require} — narrows a nullable field. */\nexport const requireNamed =\n <K extends string, S extends string, C extends object, E>(\n key: K,\n source: S,\n onMissing: (ctx: C & Record<S, unknown>) => E,\n ) =>\n <I extends C & Record<S, unknown>, F, M extends RailwayMode>(\n workflow: Railway<I, F, M>,\n ): Railway<I & Record<K, NonNullable<I[S]>>, F | E, M> =>\n workflow.require(key, source, onMissing);\n\n/**\n * Reusable wrapper around {@link Railway.parallel}. Branches run\n * concurrently and merge their named outputs back into context.\n */\nexport const parallelNamed =\n <R extends BranchRecord>(branches: R) =>\n <I extends ParallelInput<R>, E, M extends RailwayMode>(\n workflow: Railway<I, E, M>,\n ): Railway<I & ParallelOutput<R>, E | ParallelError<R>, \"async\"> => {\n // TS cannot prove contravariant branch params after storing reusable steps.\n const typedBranches = branches as unknown as Record<string, BranchFn<I>>;\n return workflow.parallel(typedBranches) as unknown as Railway<\n I & ParallelOutput<R>,\n E | ParallelError<R>,\n \"async\"\n >;\n };\n\n/**\n * Reusable wrapper around {@link Railway.select} — projects the final\n * context into the workflow's output type.\n */\nexport const select =\n <C extends object, T>(fn: (ctx: C) => T) =>\n <E, M extends RailwayMode>(workflow: Railway<C, E, M>): RailwayOutput<T, E, M> =>\n workflow.select(fn);\n"]}
|