@onrails/result 0.3.1 → 0.4.1
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 +4 -3
- package/README.md +166 -13
- package/RECIPES.md +6 -4
- package/dist/async-fns.cjs +52 -0
- package/dist/async-fns.cjs.map +1 -0
- package/dist/async-fns.d.cts +143 -0
- package/dist/async-fns.d.ts +143 -0
- package/dist/async-fns.js +42 -0
- package/dist/async-fns.js.map +1 -0
- package/dist/async-lift.d.cts +109 -0
- package/dist/async-lift.d.ts +109 -0
- package/dist/{async-Ci6WSL5-.d.ts → async.d.cts} +42 -58
- package/dist/{async-DcXR7k9K.d.cts → async.d.ts} +42 -58
- package/dist/collections.d.cts +105 -0
- package/dist/collections.d.ts +105 -0
- package/dist/compat/neverthrow.cjs +57 -45
- package/dist/compat/neverthrow.cjs.map +1 -1
- package/dist/compat/neverthrow.d.cts +21 -24
- package/dist/compat/neverthrow.d.ts +21 -24
- package/dist/compat/neverthrow.js +56 -44
- package/dist/compat/neverthrow.js.map +1 -1
- package/dist/extra.cjs +3 -1
- package/dist/extra.cjs.map +1 -1
- package/dist/extra.d.cts +11 -14
- package/dist/extra.d.ts +11 -14
- package/dist/extra.js +3 -1
- package/dist/extra.js.map +1 -1
- package/dist/fluent.cjs +15 -28
- package/dist/fluent.cjs.map +1 -1
- package/dist/fluent.d.cts +4 -34
- package/dist/fluent.d.ts +4 -34
- package/dist/fluent.js +16 -28
- package/dist/fluent.js.map +1 -1
- package/dist/index.cjs +77 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -490
- package/dist/index.d.ts +28 -490
- package/dist/index.js +77 -53
- package/dist/index.js.map +1 -1
- package/dist/internal/ctor.d.cts +12 -0
- package/dist/internal/ctor.d.ts +12 -0
- package/dist/internal/dual.d.cts +42 -0
- package/dist/internal/dual.d.ts +42 -0
- package/dist/internal/infer.d.cts +40 -0
- package/dist/internal/infer.d.ts +40 -0
- package/dist/internal/lock.d.cts +16 -0
- package/dist/internal/lock.d.ts +16 -0
- package/dist/internal/to-error.d.cts +2 -0
- package/dist/internal/to-error.d.ts +2 -0
- package/dist/pipe.cjs +8 -0
- package/dist/pipe.cjs.map +1 -1
- package/dist/pipe.d.cts +58 -11
- package/dist/pipe.d.ts +58 -11
- package/dist/pipe.js +8 -1
- package/dist/pipe.js.map +1 -1
- package/dist/railway.cjs +87 -63
- package/dist/railway.cjs.map +1 -1
- package/dist/railway.d.cts +49 -19
- package/dist/railway.d.ts +49 -19
- package/dist/railway.js +87 -63
- package/dist/railway.js.map +1 -1
- package/dist/result.d.cts +315 -0
- package/dist/result.d.ts +315 -0
- package/dist/try-gen.cjs +3 -3
- package/dist/try-gen.cjs.map +1 -1
- package/dist/try-gen.d.cts +4 -7
- package/dist/try-gen.d.ts +4 -7
- package/dist/try-gen.js +3 -3
- package/dist/try-gen.js.map +1 -1
- package/dist/{types-BQ9vv0nD.d.cts → types.d.cts} +6 -8
- package/dist/{types-BQ9vv0nD.d.ts → types.d.ts} +6 -8
- package/package.json +69 -24
- package/skills/railway-do-notation/SKILL.md +9 -9
package/dist/railway.cjs
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// src/internal/ctor.ts
|
|
4
|
+
var mkOk = (value) => ({
|
|
5
|
+
_tag: "Ok",
|
|
6
|
+
value
|
|
7
|
+
});
|
|
8
|
+
var mkErr = (error) => ({
|
|
9
|
+
_tag: "Err",
|
|
10
|
+
error
|
|
11
|
+
});
|
|
12
|
+
|
|
3
13
|
// src/internal/dual.ts
|
|
4
14
|
var dual = (arity, body) => {
|
|
5
15
|
const run = body;
|
|
@@ -8,34 +18,30 @@ var dual = (arity, body) => {
|
|
|
8
18
|
};
|
|
9
19
|
|
|
10
20
|
// src/result.ts
|
|
11
|
-
var ok = (value) => ({
|
|
12
|
-
_tag: "Ok",
|
|
13
|
-
value
|
|
14
|
-
});
|
|
15
|
-
var err = (error) => ({
|
|
16
|
-
_tag: "Err",
|
|
17
|
-
error
|
|
18
|
-
});
|
|
19
21
|
var isOk = (result) => result._tag === "Ok";
|
|
20
22
|
var isErr = (result) => result._tag === "Err";
|
|
21
23
|
var map = dual(
|
|
22
24
|
2,
|
|
23
|
-
(result, fn) => isOk(result) ?
|
|
25
|
+
(result, fn) => isOk(result) ? mkOk(fn(result.value)) : mkErr(result.error)
|
|
24
26
|
);
|
|
25
27
|
var mapErr = dual(
|
|
26
28
|
2,
|
|
27
|
-
(result, fn) => isErr(result) ?
|
|
29
|
+
(result, fn) => isErr(result) ? mkErr(fn(result.error)) : mkOk(result.value)
|
|
30
|
+
);
|
|
31
|
+
var bimap = dual(
|
|
32
|
+
3,
|
|
33
|
+
(result, onOk, onErr) => isOk(result) ? mkOk(onOk(result.value)) : mkErr(onErr(result.error))
|
|
28
34
|
);
|
|
29
35
|
var flatMap = dual(
|
|
30
36
|
2,
|
|
31
|
-
(result, fn) => isOk(result) ? fn(result.value) :
|
|
37
|
+
(result, fn) => isOk(result) ? fn(result.value) : mkErr(result.error)
|
|
32
38
|
);
|
|
33
|
-
function
|
|
39
|
+
function fromThrowable(fn, onThrow) {
|
|
34
40
|
return (...args) => {
|
|
35
41
|
try {
|
|
36
|
-
return
|
|
42
|
+
return mkOk(fn(...args));
|
|
37
43
|
} catch (error) {
|
|
38
|
-
return
|
|
44
|
+
return mkErr(onThrow(error));
|
|
39
45
|
}
|
|
40
46
|
};
|
|
41
47
|
}
|
|
@@ -55,11 +61,11 @@ var sequenceSettled = (settled) => {
|
|
|
55
61
|
const values = [];
|
|
56
62
|
for (const result of settled) {
|
|
57
63
|
if (isErr(result)) {
|
|
58
|
-
return
|
|
64
|
+
return mkErr(result.error);
|
|
59
65
|
}
|
|
60
66
|
values.push(result.value);
|
|
61
67
|
}
|
|
62
|
-
return
|
|
68
|
+
return mkOk(values);
|
|
63
69
|
};
|
|
64
70
|
var ResultAsync = class _ResultAsync {
|
|
65
71
|
constructor(run) {
|
|
@@ -96,9 +102,9 @@ var ResultAsync = class _ResultAsync {
|
|
|
96
102
|
static fromPromise(promise, onReject) {
|
|
97
103
|
return new _ResultAsync(async () => {
|
|
98
104
|
try {
|
|
99
|
-
return
|
|
105
|
+
return mkOk(await promise);
|
|
100
106
|
} catch (error) {
|
|
101
|
-
return
|
|
107
|
+
return mkErr(onReject(error));
|
|
102
108
|
}
|
|
103
109
|
});
|
|
104
110
|
}
|
|
@@ -112,7 +118,7 @@ var ResultAsync = class _ResultAsync {
|
|
|
112
118
|
* ```
|
|
113
119
|
*/
|
|
114
120
|
static fromSafePromise(promise) {
|
|
115
|
-
return new _ResultAsync(async () =>
|
|
121
|
+
return new _ResultAsync(async () => mkOk(await promise));
|
|
116
122
|
}
|
|
117
123
|
/**
|
|
118
124
|
* Defers work until {@link resolve}. Unlike {@link fromPromise}, the factory
|
|
@@ -130,21 +136,13 @@ var ResultAsync = class _ResultAsync {
|
|
|
130
136
|
return new _ResultAsync(fn);
|
|
131
137
|
}
|
|
132
138
|
static ok(value) {
|
|
133
|
-
return new _ResultAsync(async () =>
|
|
139
|
+
return new _ResultAsync(async () => mkOk(value));
|
|
134
140
|
}
|
|
135
141
|
static of(value) {
|
|
136
142
|
return _ResultAsync.ok(value);
|
|
137
143
|
}
|
|
138
|
-
/**
|
|
139
|
-
* Lifts an error into an `Err` async result.
|
|
140
|
-
*
|
|
141
|
-
* @example
|
|
142
|
-
* ```ts
|
|
143
|
-
* const r = ResultAsync.err({ kind: "not_found" as const });
|
|
144
|
-
* ```
|
|
145
|
-
*/
|
|
146
144
|
static err(error) {
|
|
147
|
-
return new _ResultAsync(async () =>
|
|
145
|
+
return new _ResultAsync(async () => mkErr(error));
|
|
148
146
|
}
|
|
149
147
|
/**
|
|
150
148
|
* Lifts an existing `Promise<Result<T, E>>` (e.g. from interop code) into a
|
|
@@ -162,7 +160,7 @@ var ResultAsync = class _ResultAsync {
|
|
|
162
160
|
try {
|
|
163
161
|
return await promise;
|
|
164
162
|
} catch (error) {
|
|
165
|
-
return
|
|
163
|
+
return mkErr(mapDefect(error));
|
|
166
164
|
}
|
|
167
165
|
});
|
|
168
166
|
}
|
|
@@ -184,11 +182,11 @@ var ResultAsync = class _ResultAsync {
|
|
|
184
182
|
for (const ra of results) {
|
|
185
183
|
const result = await ra.resolve();
|
|
186
184
|
if (isErr(result)) {
|
|
187
|
-
return
|
|
185
|
+
return mkErr(result.error);
|
|
188
186
|
}
|
|
189
187
|
values.push(result.value);
|
|
190
188
|
}
|
|
191
|
-
return
|
|
189
|
+
return mkOk(values);
|
|
192
190
|
});
|
|
193
191
|
}
|
|
194
192
|
/**
|
|
@@ -200,7 +198,7 @@ var ResultAsync = class _ResultAsync {
|
|
|
200
198
|
*
|
|
201
199
|
* @example
|
|
202
200
|
* ```ts
|
|
203
|
-
* const combined = ResultAsync.combineTuple([loadCfg(), loadCatalog()]
|
|
201
|
+
* const combined = ResultAsync.combineTuple([loadCfg(), loadCatalog()]);
|
|
204
202
|
* // ResultAsync<readonly [Cfg, Catalog], CfgError | CatalogError>
|
|
205
203
|
* const r = await combined;
|
|
206
204
|
* if (isOk(r)) {
|
|
@@ -208,7 +206,7 @@ var ResultAsync = class _ResultAsync {
|
|
|
208
206
|
* }
|
|
209
207
|
* ```
|
|
210
208
|
*/
|
|
211
|
-
static combineTuple(results) {
|
|
209
|
+
static combineTuple(results, ..._guard) {
|
|
212
210
|
return _ResultAsync.combine(
|
|
213
211
|
results
|
|
214
212
|
);
|
|
@@ -223,12 +221,14 @@ var ResultAsync = class _ResultAsync {
|
|
|
223
221
|
* const combined = ResultAsync.combineTupleParallel([
|
|
224
222
|
* loadProfile(id),
|
|
225
223
|
* loadMetrics(id),
|
|
226
|
-
* ]
|
|
224
|
+
* ]);
|
|
227
225
|
* ```
|
|
228
226
|
*/
|
|
229
|
-
static combineTupleParallel(results) {
|
|
227
|
+
static combineTupleParallel(results, ..._guard) {
|
|
230
228
|
return new _ResultAsync(
|
|
231
|
-
async () => sequenceSettled(
|
|
229
|
+
async () => sequenceSettled(
|
|
230
|
+
await Promise.all(results.map((ra) => ra.resolve()))
|
|
231
|
+
)
|
|
232
232
|
);
|
|
233
233
|
}
|
|
234
234
|
/**
|
|
@@ -254,6 +254,18 @@ var ResultAsync = class _ResultAsync {
|
|
|
254
254
|
mapErr(fn) {
|
|
255
255
|
return new _ResultAsync(async () => mapErr(await this.resolve(), fn));
|
|
256
256
|
}
|
|
257
|
+
/**
|
|
258
|
+
* Transforms both tracks in one step — the async mirror of the sync
|
|
259
|
+
* `bimap`. Exactly one of `onOk` / `onErr` runs.
|
|
260
|
+
*
|
|
261
|
+
* @example
|
|
262
|
+
* ```ts
|
|
263
|
+
* load(id).bimap(toDto, (e): AppError => ({ kind: "load", cause: e }));
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
bimap(onOk, onErr) {
|
|
267
|
+
return new _ResultAsync(async () => bimap(await this.resolve(), onOk, onErr));
|
|
268
|
+
}
|
|
257
269
|
/**
|
|
258
270
|
* Canonical bind — chains a step that itself returns a `ResultAsync` or sync
|
|
259
271
|
* `Result`, short-circuiting on `Err`. Error types accumulate (`E | F`).
|
|
@@ -427,27 +439,27 @@ var Railway = class _Railway {
|
|
|
427
439
|
state;
|
|
428
440
|
/** Start an empty sync workflow with no fields in context. */
|
|
429
441
|
static empty() {
|
|
430
|
-
return new _Railway({ mode: "sync", result:
|
|
442
|
+
return new _Railway({ mode: "sync", result: mkOk({}) });
|
|
431
443
|
}
|
|
432
444
|
/** Start a sync workflow with the given context as the initial state. */
|
|
433
445
|
static context(context) {
|
|
434
|
-
return new _Railway({ mode: "sync", result:
|
|
446
|
+
return new _Railway({ mode: "sync", result: mkOk(context) });
|
|
435
447
|
}
|
|
436
448
|
/** Start a sync workflow with a throwing function. */
|
|
437
449
|
static fromSync(key, fn, onThrow) {
|
|
438
|
-
return _Railway.empty().
|
|
450
|
+
return _Railway.empty().addSync(key, () => fromThrowable(fn, onThrow)());
|
|
439
451
|
}
|
|
440
452
|
/** Start a sync workflow with a `Result`-returning function. */
|
|
441
453
|
static fromResult(key, fn) {
|
|
442
|
-
return _Railway.empty().
|
|
454
|
+
return _Railway.empty().addSync(key, fn);
|
|
443
455
|
}
|
|
444
456
|
/** Start an async workflow with a `PromiseLike`-returning function. */
|
|
445
457
|
static fromPromise(key, fn, onReject) {
|
|
446
|
-
return _Railway.empty().
|
|
458
|
+
return _Railway.empty().addAsync(key, () => ResultAsync.fromPromise(fn(), onReject));
|
|
447
459
|
}
|
|
448
460
|
/** Start an async workflow with a `ResultAsync`-returning function. */
|
|
449
461
|
static fromAsync(key, fn) {
|
|
450
|
-
return _Railway.empty().
|
|
462
|
+
return _Railway.empty().addAsync(key, fn);
|
|
451
463
|
}
|
|
452
464
|
/**
|
|
453
465
|
* Rebuild the workflow in its current mode after transforming the carried
|
|
@@ -472,16 +484,12 @@ var Railway = class _Railway {
|
|
|
472
484
|
toAsync() {
|
|
473
485
|
return this.state.mode === "sync" ? ResultAsync.fromResult(this.state.result) : this.state.result;
|
|
474
486
|
}
|
|
475
|
-
/**
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
return this.fromResult(key, (ctx) => trySync(fn, onThrow)(ctx));
|
|
482
|
-
}
|
|
483
|
-
/** Sync `Result`-returning step. */
|
|
484
|
-
fromResult(key, fn) {
|
|
487
|
+
/**
|
|
488
|
+
* Internal plumbing for a sync field append. Public steps wrap this and add
|
|
489
|
+
* the {@link FreshKey} collision guard; the static factories bypass the
|
|
490
|
+
* guard because they always start from an empty context.
|
|
491
|
+
*/
|
|
492
|
+
addSync(key, fn) {
|
|
485
493
|
return this.step(
|
|
486
494
|
(result) => flatMap(result, (ctx) => map(fn(ctx), (value) => addField(ctx, key, value))),
|
|
487
495
|
(result) => result.flatMap(
|
|
@@ -489,26 +497,42 @@ var Railway = class _Railway {
|
|
|
489
497
|
)
|
|
490
498
|
);
|
|
491
499
|
}
|
|
492
|
-
/**
|
|
493
|
-
|
|
494
|
-
return this.fromAsync(key, (ctx) => ResultAsync.fromPromise(fn(ctx), onReject));
|
|
495
|
-
}
|
|
496
|
-
/** `ResultAsync`-returning step — upgrades the workflow to async mode. */
|
|
497
|
-
fromAsync(key, fn) {
|
|
500
|
+
/** Internal plumbing for an async field append — upgrades the mode. */
|
|
501
|
+
addAsync(key, fn) {
|
|
498
502
|
return new _Railway({
|
|
499
503
|
mode: "async",
|
|
500
504
|
result: this.toAsync().flatMap((ctx) => fn(ctx).map((value) => addField(ctx, key, value)))
|
|
501
505
|
});
|
|
502
506
|
}
|
|
507
|
+
/** Pure sync derivation. */
|
|
508
|
+
derive(key, fn, ..._guard) {
|
|
509
|
+
return this.addSync(key, (ctx) => mkOk(fn(ctx)));
|
|
510
|
+
}
|
|
511
|
+
/** Throwing sync transform. */
|
|
512
|
+
fromSync(key, fn, onThrow, ..._guard) {
|
|
513
|
+
return this.addSync(key, (ctx) => fromThrowable(fn, onThrow)(ctx));
|
|
514
|
+
}
|
|
515
|
+
/** Sync `Result`-returning step. */
|
|
516
|
+
fromResult(key, fn, ..._guard) {
|
|
517
|
+
return this.addSync(key, fn);
|
|
518
|
+
}
|
|
519
|
+
/** Promise-returning step — upgrades the workflow to async mode. */
|
|
520
|
+
fromPromise(key, fn, onReject, ..._guard) {
|
|
521
|
+
return this.addAsync(key, (ctx) => ResultAsync.fromPromise(fn(ctx), onReject));
|
|
522
|
+
}
|
|
523
|
+
/** `ResultAsync`-returning step — upgrades the workflow to async mode. */
|
|
524
|
+
fromAsync(key, fn, ..._guard) {
|
|
525
|
+
return this.addAsync(key, fn);
|
|
526
|
+
}
|
|
503
527
|
/** Narrow a nullable context field into a required non-null field. */
|
|
504
|
-
require(key, source, onMissing) {
|
|
505
|
-
return this.
|
|
528
|
+
require(key, source, onMissing, ..._guard) {
|
|
529
|
+
return this.addSync(key, (ctx) => {
|
|
506
530
|
const value = ctx[source];
|
|
507
|
-
return value == null ?
|
|
531
|
+
return value == null ? mkErr(onMissing(ctx)) : mkOk(value);
|
|
508
532
|
});
|
|
509
533
|
}
|
|
510
534
|
/** Run independent `ResultAsync` branches concurrently and merge outputs. */
|
|
511
|
-
parallel(branches) {
|
|
535
|
+
parallel(branches, ..._guard) {
|
|
512
536
|
const merged = this.toAsync().flatMap(
|
|
513
537
|
(ctx) => ResultAsync.combineTupleParallel(
|
|
514
538
|
Object.entries(branches).map(([, branch]) => branch(ctx))
|
package/dist/railway.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/dual.ts","../src/result.ts","../src/types.ts","../src/async.ts","../src/railway.ts"],"names":[],"mappings":"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","file":"railway.cjs","sourcesContent":["/**\n * @onrails/result internal — owning module for the **dual-form idiom**.\n *\n * Every dual-form transform in this package (`map`, `flatMap`, `match`, …)\n * accepts either shape:\n *\n * data-first: `map(result, fn)` — full arity, runs immediately\n * curried: `map(fn)(result)` — arity minus the leading `self`, returns\n * a unary function awaiting the data\n *\n * {@link dual} is the single arity dispatcher those transforms derive from;\n * hand-rolled `args.length` checks are not allowed elsewhere.\n *\n * NOTE: a twin copy of this module lives at `packages/maybe/src/internal/dual.ts`\n * — keep the two in sync when editing.\n *\n * Internal only: not listed in package.json `exports` or tsup entries.\n */\n\n/**\n * Derive a dual-form (data-first / curried) function from a single\n * data-first `body`.\n *\n * When called with `args.length >= arity` the wrapper runs `body(...args)`\n * (data-first). With fewer arguments it returns `(self) => body(self, ...args)`\n * — the curried, data-last-`self` form used with `pipe`/`flow`.\n *\n * The public type is supplied entirely by the caller: annotate the exported\n * const with the exact overload set and let `F` be inferred from it.\n *\n * @example\n * ```ts\n * export const map: {\n * <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;\n * <T, U>(fn: (value: T) => U): <E>(result: Result<T, E>) => Result<U, E>;\n * } = dual(\n * 2,\n * <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 */\nexport const dual = <F>(arity: number, body: (...args: never[]) => unknown): F => {\n // `(...args: never[]) => unknown` is the top function type, so every typed\n // body is assignable to the parameter — but it cannot be invoked with\n // `unknown` arguments. Re-view it through the variadic shape the dispatcher\n // actually forwards; the constraint is that `body` only ever receives the\n // arguments the caller's overload annotation admitted.\n const run = body as (...args: readonly unknown[]) => unknown;\n const dispatcher = (...args: readonly unknown[]): unknown =>\n args.length >= arity ? run(...args) : (self: unknown) => run(self, ...args);\n // The caller's overload annotation on the exported const supplies the real\n // public type; internally the dispatcher stays `unknown`-typed.\n return dispatcher as F;\n};\n","import { dual } from \"./internal/dual.js\";\nimport 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 * Fantasy Land `pure` — alias of {@link ok}. One lift name shared across the\n * trio (`of` / `Maybe.of` / `ResultAsync.of`) for generic and FL-style code.\n *\n * @example\n * ```ts\n * const r = of(42); // Result<number, never> — identical to ok(42)\n * ```\n */\nexport const of = ok;\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// ─────────────────────────────────────────────────────────────────────────────\n// Dual-form helpers — each export accepts either shape:\n// data-first: `map(result, fn)`\n// curried: `map(fn)(result)`\n// Arity dispatch is derived from the internal `dual` combinator\n// (src/internal/dual.ts); the const annotation carries the public overloads.\n// ─────────────────────────────────────────────────────────────────────────────\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 const map: {\n <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;\n <T, U>(fn: (value: T) => U): <E>(result: Result<T, E>) => Result<U, E>;\n} = dual(\n 2,\n <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/**\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 const mapErr: {\n <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F>;\n <E, F>(fn: (error: E) => F): <T>(result: Result<T, E>) => Result<T, F>;\n} = dual(\n 2,\n <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/**\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 const bimap: {\n <T, U, E, F>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => F): Result<U, F>;\n <T, U, E, F>(\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n ): (result: Result<T, E>) => Result<U, F>;\n} = dual(\n 3,\n <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/**\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 const flatMap: {\n <T, U, E, F>(result: Result<T, E>, fn: (value: T) => Result<U, F>): Result<U, E | F>;\n <T, U, F>(fn: (value: T) => Result<U, F>): <E>(result: Result<T, E>) => Result<U, E | F>;\n} = dual(\n 2,\n <T, U, E, F>(result: Result<T, E>, fn: (value: T) => Result<U, F>): Result<U, E | F> =>\n isOk(result) ? fn(result.value) : err(result.error),\n);\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 const recover: {\n <T, E, F>(result: Result<T, E>, fn: (error: E) => Result<T, F>): Result<T, F>;\n <T, E, F>(fn: (error: E) => Result<T, F>): (result: Result<T, E>) => Result<T, F>;\n} = dual(\n 2,\n <T, E, F>(result: Result<T, E>, fn: (error: E) => Result<T, F>): Result<T, F> =>\n isErr(result) ? fn(result.error) : ok(result.value),\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 const tap: {\n <T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E>;\n <T>(fn: (value: T) => void): <E>(result: Result<T, E>) => Result<T, E>;\n} = dual(2, <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 `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 const tapErr: {\n <T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E>;\n <E>(fn: (error: E) => void): <T>(result: Result<T, E>) => Result<T, E>;\n} = dual(2, <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 * 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`, use a namespace\n * import (`import * as R from \"@onrails/result\"` → `R.match`) to dissolve\n * the collision.\n *\n * @example\n * ```ts\n * const html = match(parsed, (cfg) => render(cfg), (e) => renderError(e));\n * ```\n */\nexport const match: {\n <T, E, U>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => U): U;\n <T, E, U>(onOk: (value: T) => U, onErr: (error: E) => U): (result: Result<T, E>) => U;\n} = dual(\n 3,\n <T, E, U>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => U): U =>\n isOk(result) ? onOk(result.value) : onErr(result.error),\n);\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: {\n <T, E>(result: Result<T, E>, defaultValue: T): T;\n <T>(defaultValue: T): <E>(result: Result<T, E>) => T;\n} = dual(\n 2,\n <T, E>(result: Result<T, E>, defaultValue: T): T => (isOk(result) ? result.value : defaultValue),\n);\n\n/**\n * Test/assert helper — returns the `Ok` value, or **throws the original `Err`\n * value** when called on an `Err`. This is the assertion tier (RFC 0001 §4):\n * intended for `*.spec.ts` / `*.test.ts`, where throwing fails the test loudly.\n * In business logic prefer {@link match} or {@link unwrapOr}; the lint plugins\n * flag `unwrapOk` outside test files.\n *\n * @returns the unwrapped `Ok` value\n * @throws the carried `Err` value when the result is `Err`\n *\n * @example\n * ```ts\n * // in a *.spec.ts\n * expect(unwrapOk(ok(5))).toBe(5);\n * expect(() => unwrapOk(err(error))).toThrow(error);\n * ```\n */\nexport function unwrapOk<T, E>(result: Result<T, E>): T {\n if (isErr(result)) throw result.error;\n return result.value;\n}\n\n/** Alias of {@link unwrapOk} for syntax cohesion with `@onrails/maybe`. */\nexport const unwrap = unwrapOk;\n\n/**\n * Test/assert helper — returns the `Err` value, or **throws a `TypeError`**\n * when called on an `Ok`. Mirror of {@link unwrapOk} on the error track and\n * part of the same assertion tier (RFC 0001 §4): intended for `*.spec.ts` /\n * `*.test.ts`. Prefer {@link match} / {@link unwrapOr} in business logic; the\n * lint plugins flag `unwrapErr` outside test files.\n *\n * @returns the unwrapped `Err` value\n * @throws `TypeError` when the result is `Ok`\n *\n * @example\n * ```ts\n * // in a *.spec.ts\n * expect(unwrapErr(err(\"x\"))).toBe(\"x\");\n * expect(() => unwrapErr(ok(5))).toThrow(TypeError);\n * ```\n */\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/**\n * Wraps a throwing sync function, returning a function that produces a\n * {@link Result} instead of throwing. Thrown errors pass through `onThrow` to\n * become a typed `Err`; a normal return becomes `Ok`. The neverthrow analogue\n * is `Result.fromThrowable`.\n *\n * @param fn - the throwing function to wrap\n * @param onThrow - maps a thrown value to the `Err` channel\n * @returns a function with `fn`'s parameters that returns `Result<ReturnType, E>`\n *\n * @example\n * ```ts\n * type ParseError = { kind: \"parse\"; message: string };\n * const parse = trySync(\n * JSON.parse,\n * (e): ParseError => ({ kind: \"parse\", message: String(e) }),\n * );\n * parse(\"{}\"); // Ok({})\n * parse(\"nope\"); // Err({ kind: \"parse\", … })\n * ```\n */\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/**\n * Variadic value-first pipe — threads `value` through up to nine unary fns,\n * left-to-right. Use {@link pipe} when you already have a starting value;\n * use {@link flow} to define a reusable composed function with no value yet.\n *\n * @example\n * ```ts\n * pipe(\n * parseConfig(raw),\n * map((cfg) => cfg.name),\n * flatMap((name) => (name ? ok(name) : err({ kind: \"empty\" as const }))),\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\nconst printPayload = (payload: unknown): string => {\n try {\n return JSON.stringify(payload) ?? String(payload);\n } catch {\n // cyclic or non-JSON payload — a debug printer must not throw\n return String(payload);\n }\n};\n\n/**\n * Debug printer — renders a result as `Ok(…)` / `Err(…)` for logs. Payloads\n * print as JSON (values are plain data by design); non-JSON payloads fall\n * back to `String(...)`.\n *\n * @example\n * ```ts\n * show(ok(1)); // 'Ok(1)'\n * show(err({ kind: \"e\" })); // 'Err({\"kind\":\"e\"})'\n * ```\n */\nexport const show = <T, E>(result: Result<T, E>): string =>\n isOk(result) ? `Ok(${printPayload(result.value)})` : `Err(${printPayload(result.error)})`;\n","/**\n * The core railway type: a tagged union carrying either a success value\n * (`Ok<T>`) or a failure value (`Err<E>`). It is a plain discriminated union\n * on `_tag` — no classes — so it is immutable and tree-shake friendly. Narrow\n * with {@link isOk} / {@link isErr} to read `.value` / `.error`.\n *\n * @typeParam T - the `Ok` value type\n * @typeParam E - the `Err` error type\n *\n * @example\n * ```ts\n * function parse(raw: string): Result<number, \"nan\"> {\n * const n = Number(raw);\n * return Number.isNaN(n) ? err(\"nan\") : ok(n);\n * }\n * ```\n */\nexport type Result<T, E> =\n | { readonly _tag: \"Ok\"; readonly value: T }\n | { readonly _tag: \"Err\"; readonly error: E };\n\n/**\n * The success branch of a {@link Result} — `{ _tag: \"Ok\"; value: T }`.\n * The `E` parameter keeps the type assignable to `Result<T, E>`.\n */\nexport type Ok<T, E = never> = Extract<Result<T, E>, { _tag: \"Ok\" }>;\n\n/**\n * The failure branch of a {@link Result} — `{ _tag: \"Err\"; error: E }`.\n */\nexport type Err<T, E> = Extract<Result<T, E>, { _tag: \"Err\" }>;\n\n/**\n * Error subclass representing an **unexpected** defect — a thrown exception or\n * promise rejection that was not part of the modelled `Err` union. Used as the\n * default mapping when {@link fromAsync} is called without an `onDefect`\n * handler; the original cause is preserved on `.cause`.\n *\n * @example\n * ```ts\n * const defect = new UnexpectedError(\"Unexpected async defect\", caught);\n * defect.cause; // the original thrown value\n * ```\n */\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 type { InferErr, InferOk } from \"./internal/infer.js\";\nimport { 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 CombineTupleAsync<R extends readonly ResultAsync<unknown, unknown>[]> = ResultAsync<\n { [K in keyof R]: InferOk<R[K]> },\n { [K in keyof R]: InferErr<R[K]> }[number]\n>;\n\n/** Collapses settled results left-to-right, short-circuiting on the first `Err`. */\nconst sequenceSettled = (\n settled: readonly Result<unknown, unknown>[],\n): Result<unknown[], unknown> => {\n const values: unknown[] = [];\n for (const result of settled) {\n if (isErr(result)) {\n return err(result.error);\n }\n values.push(result.value);\n }\n return ok(values);\n};\n\n/**\n * Async railway carrier. Wraps a deferred `Promise<Result<T, E>>` and exposes\n * the same dual-track transforms as the sync {@link Result} — `map`, `flatMap`,\n * `recover`, `tap`, `match`. The public API never surfaces `Promise<Result<…>>`\n * directly: `await` the instance (it is thenable) or call {@link resolve} /\n * {@link match} to settle it.\n *\n * Construct via the static factories ({@link ok}, {@link err}, {@link fromPromise},\n * {@link defer}, …) rather than `new` — the constructor is `protected`.\n *\n * @typeParam T - the `Ok` value type\n * @typeParam E - the `Err` error type\n *\n * @example\n * ```ts\n * const user = ResultAsync.fromPromise(api.getUser(id), toAppError)\n * .map((u) => u.profile)\n * .recover(() => ResultAsync.ok(guestProfile));\n *\n * const r = await user; // Result<Profile, AppError>\n * ```\n */\nexport class ResultAsync<T, E> {\n private promise: Promise<Result<T, E>> | null = null;\n\n protected constructor(protected readonly run: PromiseFactory<T, E>) {}\n\n /**\n * Lifts an already-settled sync {@link Result} into a {@link ResultAsync}.\n *\n * @example\n * ```ts\n * const ra = ResultAsync.fromResult(ok(42)); // ResultAsync<number, never>\n * ```\n */\n static fromResult<T, E>(result: Result<T, E>): ResultAsync<T, E> {\n return new ResultAsync(async () => result);\n }\n\n /**\n * Wraps a `PromiseLike<T>` that may reject. Rejections pass through `onReject`\n * to become a typed `Err`; resolution becomes `Ok<T>`.\n *\n * @param promise - the promise to wrap\n * @param onReject - maps a rejection reason to the `Err` channel\n *\n * @example\n * ```ts\n * const body = ResultAsync.fromPromise(\n * fetch(url).then((r) => r.text()),\n * (e): NetError => ({ kind: \"net\", cause: String(e) }),\n * );\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 /**\n * Wraps a `PromiseLike<T>` that is **guaranteed not to reject**, skipping the\n * `onReject` mapper. Use only when rejection is provably impossible.\n *\n * @example\n * ```ts\n * const now = ResultAsync.fromSafePromise(Promise.resolve(Date.now()));\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}, the factory\n * does not run until the `ResultAsync` is resolved (e.g. by `combineTuple` /\n * `combineTupleParallel`). The factory runs at most once — `resolve` memoizes.\n *\n * @example\n * ```ts\n * const insert = ResultAsync.defer(() => db.orders.insert(row));\n * // nothing has run yet\n * const r = await insert; // factory runs exactly once here\n * ```\n */\n static defer<T, E>(fn: () => Promise<Result<T, E>>): ResultAsync<T, E> {\n return new ResultAsync(fn);\n }\n\n /**\n * Lifts a value into an `Ok` async result.\n *\n * @example\n * ```ts\n * const r = ResultAsync.ok(42); // ResultAsync<number, never>\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 /**\n * Fantasy Land `pure` — alias of {@link ResultAsync.ok}. One lift name\n * shared across the trio (`of` / `Maybe.of` / `ResultAsync.of`).\n */\n static of<T>(value: T): ResultAsync<T, never>;\n static of<T, E>(value: T): ResultAsync<T, E>;\n static of<T, E = never>(value: T): ResultAsync<T, E> {\n return ResultAsync.ok(value);\n }\n\n /**\n * Lifts an error into an `Err` async result.\n *\n * @example\n * ```ts\n * const r = ResultAsync.err({ kind: \"not_found\" as const });\n * ```\n */\n static err<T = never, E = unknown>(error: E): ResultAsync<T, E> {\n return new ResultAsync(async () => err(error));\n }\n\n /**\n * Lifts an existing `Promise<Result<T, E>>` (e.g. from interop code) into a\n * {@link ResultAsync}. A thrown defect is routed through `onDefect`,\n * defaulting to {@link UnexpectedError}. The `Ok` value passes through\n * verbatim — even when it happens to be Result-shaped.\n *\n * @param promise - a promise that already yields a `Result`\n * @param onDefect - maps an unexpected throw to the `Err` channel\n * @see {@link fromAsync} from `@onrails/result`\n */\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<T, E | UnexpectedError>(async () => {\n try {\n return await promise;\n } catch (error) {\n return err(mapDefect(error));\n }\n });\n }\n\n /**\n * Combines a homogeneous array of async results into one. Resolves\n * **sequentially** in input order, short-circuiting on the first `Err`.\n * For heterogeneous tuples that preserve per-index types, use\n * {@link combineTuple}; for wall-clock overlap, {@link combineTupleParallel}.\n *\n * @example\n * ```ts\n * const all = ResultAsync.combine([loadA(), loadB(), loadC()]);\n * // ResultAsync<Item[], LoadError>\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 /**\n * Heterogeneous async tuple combine — resolves branches **sequentially**\n * (left-to-right), returning the first `Err` in input order. Preserves each\n * branch's `Ok` type by position, so the result destructures type-safely.\n * This is the canonical sequential async combine (replaces the former\n * `sequenceTupleAsync`).\n *\n * @example\n * ```ts\n * const combined = ResultAsync.combineTuple([loadCfg(), loadCatalog()] as const);\n * // ResultAsync<readonly [Cfg, Catalog], CfgError | CatalogError>\n * const r = await combined;\n * if (isOk(r)) {\n * const [cfg, catalog] = r.value; // typed per position\n * }\n * ```\n */\n static combineTuple<const R extends readonly ResultAsync<unknown, unknown>[]>(\n results: R,\n ): CombineTupleAsync<R> {\n // Runtime identical to combine; the cast restores per-index tuple types.\n return ResultAsync.combine(\n results as readonly ResultAsync<unknown, unknown>[],\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 * @example\n * ```ts\n * // independent IO — overlap them\n * const combined = ResultAsync.combineTupleParallel([\n * loadProfile(id),\n * loadMetrics(id),\n * ] as const);\n * ```\n */\n static combineTupleParallel<const R extends readonly ResultAsync<unknown, unknown>[]>(\n results: R,\n ): CombineTupleAsync<R> {\n // Cast restores per-index tuple types over the untyped sequence core.\n return new ResultAsync(async () =>\n sequenceSettled(await Promise.all(results.map((ra) => ra.resolve()))),\n ) as CombineTupleAsync<R>;\n }\n\n /**\n * Transforms the `Ok` value, passing `Err` through unchanged.\n *\n * @example\n * ```ts\n * ResultAsync.ok(2).map((n) => n * 3); // ResultAsync<number> → Ok 6\n * ```\n */\n map<U>(fn: (value: T) => U): ResultAsync<U, E> {\n return new ResultAsync(async () => map(await this.resolve(), fn));\n }\n\n /**\n * Transforms the `Err` value, passing `Ok` through unchanged — useful for\n * unifying heterogeneous failures into one app-level union.\n *\n * @example\n * ```ts\n * load(id).mapErr((e): AppError => ({ kind: \"load\", cause: e })); // ResultAsync<T, AppError>\n * ```\n */\n mapErr<F>(fn: (error: E) => F): ResultAsync<T, F> {\n return new ResultAsync(async () => mapErr(await this.resolve(), fn));\n }\n\n /**\n * Canonical bind — chains a step that itself returns a `ResultAsync` or sync\n * `Result`, short-circuiting on `Err`. Error types accumulate (`E | F`).\n *\n * @example\n * ```ts\n * authenticate(req)\n * .flatMap((user) => loadProfile(user.id)) // ResultAsync\n * .flatMap((p) => validate(p)); // sync Result also accepted\n * ```\n */\n flatMap<U, F = E>(fn: (value: T) => ResultAsync<U, F> | Result<U, F>): ResultAsync<U, E | F> {\n return new ResultAsync<U, E | F>(async () => {\n const first = await this.resolve();\n if (isErr(first)) {\n return first;\n }\n const next = fn(first.value);\n return next instanceof ResultAsync ? next.resolve() : next;\n });\n }\n\n /**\n * neverthrow-compat alias of {@link flatMap}. Kept as the documented compat\n * tier; prefer {@link flatMap} in new code.\n *\n * @example\n * ```ts\n * authenticate(req).andThen((user) => loadProfile(user.id));\n * ```\n */\n andThen<U, F = E>(fn: (value: T) => ResultAsync<U, F> | Result<U, F>): ResultAsync<U, E | F> {\n return this.flatMap(fn);\n }\n\n /**\n * Error-channel bind — runs `fn` only on `Err`, swapping in a recovery\n * `ResultAsync` or sync `Result`. `Ok` passes through. The mirror of\n * {@link flatMap} on the error track.\n *\n * @example\n * ```ts\n * loadFromCache(id).recover(() => loadFromOrigin(id)); // ResultAsync<T, F>\n * ```\n */\n recover<F>(fn: (error: E) => ResultAsync<T, F> | Result<T, F>): ResultAsync<T, F> {\n return new ResultAsync<T, F>(async () => {\n const first = await this.resolve();\n if (!isErr(first)) {\n return first;\n }\n const next = fn(first.error);\n return next instanceof ResultAsync ? next.resolve() : next;\n });\n }\n\n /**\n * neverthrow-compat alias of {@link recover}. Kept as the documented compat\n * tier; prefer {@link recover} in new code.\n *\n * @example\n * ```ts\n * loadFromCache(id).orElse(() => loadFromOrigin(id));\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 /**\n * Runs a side effect on the `Ok` value and passes the result through\n * unchanged; a no-op on `Err`. Mirrors {@link tapErr}.\n *\n * @example\n * ```ts\n * saveUser(u).tap((saved) => analytics.track(\"user_saved\", saved.id));\n * ```\n */\n tap(fn: (value: T) => void): ResultAsync<T, E> {\n return new ResultAsync(async () => {\n const result = await this.resolve();\n if (!isErr(result)) {\n fn(result.value);\n }\n return result;\n });\n }\n\n /**\n * Runs a side effect on the `Err` value and passes the result through\n * unchanged; a no-op on `Ok`. The error-track mirror of {@link tap}.\n *\n * @example\n * ```ts\n * saveUser(u).tapErr((e) => logger.warn(\"save failed\", e));\n * ```\n */\n tapErr(fn: (error: E) => void): ResultAsync<T, E> {\n return new ResultAsync(async () => {\n const result = await this.resolve();\n if (isErr(result)) {\n fn(result.error);\n }\n return result;\n });\n }\n\n /**\n * Settles to the `Ok` value, or `defaultValue` if `Err`. Terminal — returns a\n * plain `Promise`, not a `ResultAsync`.\n *\n * @example\n * ```ts\n * const profile = await loadProfile(id).unwrapOr(guestProfile);\n * ```\n */\n unwrapOr<U>(defaultValue: U): Promise<T | U> {\n return this.resolve().then((result) => (isErr(result) ? defaultValue : result.value));\n }\n\n /**\n * Terminal collapse — folds both tracks into a single awaited value. Returns\n * a plain `Promise`, settling the carrier exactly once.\n *\n * @param onOk - handles the `Ok` value\n * @param onErr - handles the `Err` value\n *\n * @example\n * ```ts\n * const status = await save(row).match(\n * () => 200,\n * (e) => (e.kind === \"conflict\" ? 409 : 500),\n * );\n * ```\n */\n match<U1, U2 = U1>(onOk: (value: T) => U1, onErr: (error: E) => U2): Promise<U1 | U2> {\n return this.resolve().then((result) =>\n isErr(result) ? onErr(result.error) : onOk(result.value),\n );\n }\n\n /**\n * Settles the carrier to a bare sync {@link Result}, memoizing so the\n * underlying factory runs at most once. Prefer `await ra` (the thenable) or\n * {@link match} in app code; use `resolve` when you need the tagged union back.\n *\n * @example\n * ```ts\n * const r = await load(id).resolve(); // Result<Data, LoadError>\n * if (isOk(r)) use(r.value);\n * ```\n */\n resolve(): Promise<Result<T, E>> {\n if (!this.promise) {\n this.promise = this.run();\n }\n return this.promise;\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.resolve().then(\n // Safe: without onfulfilled, R1 stays at its Result<T, E> default.\n (r) => (onfulfilled ? onfulfilled(r) : (r as unknown as R1)),\n onrejected ?? undefined,\n );\n }\n}\n\n/**\n * The free-function lift helpers (`okAsync`, `errAsync`, `fromPromise`,\n * `fromSafePromise`, `fromResult`, `fromAsync`, `asyncAfter`, `tryAsync`)\n * live in `./async-lift.ts` and are re-exported from the package index.\n */\n","import { ResultAsync } from \"./async.js\";\nimport { err, flatMap, map, 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 * Runtime carrier for a workflow. Invariant: the `mode` tag mirrors the\n * phantom `M` on {@link Railway} — every construction site writes matching\n * tag and type parameter, and {@link Railway.step} / {@link Railway.out}\n * are the only places that re-link the two.\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\nexport type BranchFn<C extends object> = (ctx: C) => ResultAsync<unknown, unknown>;\nexport type 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;\nexport type ParallelOutput<R extends BranchRecord> = {\n [K in keyof R]: BranchOk<R[K]>;\n};\nexport type ParallelError<R extends BranchRecord> = BranchErr<R[keyof R]>;\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\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 */\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 /** Start a sync workflow with a throwing function. */\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 * Rebuild the workflow in its current mode after transforming the carried\n * result. Single re-link point for the state/phantom invariant: the mode\n * tag is preserved verbatim, so `M` still describes the new state — TS\n * cannot narrow the phantom `M` from the runtime tag, hence the cast.\n */\n private step<C2 extends object, F>(\n onSync: (result: Result<C, E>) => Result<C2, E | F>,\n onAsync: (result: ResultAsync<C, E>) => ResultAsync<C2, E | F>,\n ): Railway<C2, E | F, M> {\n const next: RailwayState<C2, E | F> =\n this.state.mode === \"sync\"\n ? { mode: \"sync\", result: onSync(this.state.result) }\n : { mode: \"async\", result: onAsync(this.state.result) };\n return new Railway(next) as Railway<C2, E | F, M>;\n }\n\n /**\n * Project the carried result into the mode-aware output type. Counterpart\n * of {@link Railway.step} for terminal steps: the runtime branch matches\n * the branch `RailwayOutput` picks for `M` (state/phantom invariant), but\n * TS cannot resolve the conditional on an unresolved `M`, hence the cast.\n */\n private out<T>(\n onSync: (result: Result<C, E>) => Result<T, E>,\n onAsync: (result: ResultAsync<C, E>) => ResultAsync<T, E>,\n ): RailwayOutput<T, E, M> {\n return (\n this.state.mode === \"sync\" ? onSync(this.state.result) : onAsync(this.state.result)\n ) as RailwayOutput<T, E, M>;\n }\n\n /** Lift the carried result into `ResultAsync` for async-upgrading steps. */\n private toAsync(): ResultAsync<C, E> {\n return this.state.mode === \"sync\"\n ? ResultAsync.fromResult(this.state.result)\n : this.state.result;\n }\n\n /** Pure sync derivation. */\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 /** Throwing sync transform. */\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 /** Sync `Result`-returning step. */\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 return this.step(\n (result) => flatMap(result, (ctx) => map(fn(ctx), (value) => addField(ctx, key, value))),\n (result) =>\n result.flatMap((ctx) =>\n ResultAsync.fromResult(fn(ctx)).map((value) => addField(ctx, key, value)),\n ),\n );\n }\n\n /** Promise-returning step — upgrades the workflow to async mode. */\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 /** `ResultAsync`-returning step — upgrades the workflow to async mode. */\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 return new Railway({\n mode: \"async\",\n result: this.toAsync().flatMap((ctx) => fn(ctx).map((value) => addField(ctx, key, value))),\n });\n }\n\n /** Narrow a nullable context field into a required non-null field. */\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);\n });\n }\n\n /** Run independent `ResultAsync` branches concurrently and merge outputs. */\n parallel<R extends Record<string, BranchFn<C>>>(\n branches: R,\n ): Railway<C & ParallelOutput<R>, E | ParallelError<R>, \"async\"> {\n const merged = this.toAsync().flatMap((ctx) =>\n ResultAsync.combineTupleParallel(\n Object.entries(branches).map(([, branch]) => branch(ctx)),\n ).map(\n (values) =>\n // Branch outputs land under exactly R's keys; Object.fromEntries\n // erases that correspondence, so reassert the merged shape.\n ({\n ...ctx,\n ...Object.fromEntries(Object.keys(branches).map((key, index) => [key, values[index]])),\n }) as C & ParallelOutput<R>,\n ),\n );\n return new Railway({\n mode: \"async\",\n // BranchFn erases per-key types to `ResultAsync<unknown, unknown>`\n // (ParallelOutput/ParallelError recover them from R), so re-assert the\n // precise value/error union the branches actually produce.\n result: merged as ResultAsync<C & ParallelOutput<R>, E | ParallelError<R>>,\n });\n }\n\n /** Project the final context into the workflow's output type. */\n select<T>(fn: (ctx: C) => T): RailwayOutput<T, E, M> {\n return this.out(\n (result) => map(result, fn),\n (result) => result.map(fn),\n );\n }\n\n /** Return the accumulated context as-is. */\n done(): RailwayOutput<C, E, M> {\n return this.out(\n (result) => result,\n (result) => result,\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/ctor.ts","../src/internal/dual.ts","../src/result.ts","../src/types.ts","../src/async.ts","../src/railway.ts"],"names":[],"mappings":"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","file":"railway.cjs","sourcesContent":["import type { Result } from \"../types.js\";\n\n/**\n * Unlocked `Ok` constructor for library internals.\n *\n * The public {@link ok} takes a `const` type parameter so caller literals stay\n * narrow. That is wrong inside a generic transform, where the payload type is\n * an unresolved type parameter and the resulting `Locked<T>` would never reduce\n * back to `T`. Internals build results through this constructor instead.\n */\nexport const mkOk = <T, E = never>(value: T): Result<T, E> => ({\n _tag: \"Ok\",\n value,\n});\n\n/** Unlocked `Err` constructor for library internals. Mirror of {@link mkOk}. */\nexport const mkErr = <T = never, E = unknown>(error: E): Result<T, E> => ({\n _tag: \"Err\",\n error,\n});\n","/**\n * @onrails/result internal — owning module for the **dual-form idiom**.\n *\n * Every dual-form transform in this package (`map`, `flatMap`, `match`, …)\n * accepts either shape:\n *\n * data-first: `map(result, fn)` — full arity, runs immediately\n * curried: `map(fn)(result)` — arity minus the leading `self`, returns\n * a unary function awaiting the data\n *\n * {@link dual} is the single arity dispatcher those transforms derive from;\n * hand-rolled `args.length` checks are not allowed elsewhere.\n *\n * NOTE: a twin copy of this module lives at `packages/maybe/src/internal/dual.ts`\n * — keep the two in sync when editing.\n *\n * Internal only: not listed in package.json `exports` or tsup entries.\n */\n\n/**\n * Derive a dual-form (data-first / curried) function from a single\n * data-first `body`.\n *\n * When called with `args.length >= arity` the wrapper runs `body(...args)`\n * (data-first). With fewer arguments it returns `(self) => body(self, ...args)`\n * — the curried, data-last-`self` form used with `pipe`/`flow`.\n *\n * The public type is supplied entirely by the caller: annotate the exported\n * const with the exact overload set and let `F` be inferred from it.\n *\n * @example\n * ```ts\n * export const map: {\n * <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;\n * <T, U>(fn: (value: T) => U): <E>(result: Result<T, E>) => Result<U, E>;\n * } = dual(\n * 2,\n * <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 */\nexport const dual = <F>(arity: number, body: (...args: never[]) => unknown): F => {\n // `(...args: never[]) => unknown` is the top function type, so every typed\n // body is assignable to the parameter — but it cannot be invoked with\n // `unknown` arguments. Re-view it through the variadic shape the dispatcher\n // actually forwards; the constraint is that `body` only ever receives the\n // arguments the caller's overload annotation admitted.\n const run = body as (...args: readonly unknown[]) => unknown;\n const dispatcher = (...args: readonly unknown[]): unknown =>\n args.length >= arity ? run(...args) : (self: unknown) => run(self, ...args);\n // The caller's overload annotation on the exported const supplies the real\n // public type; internally the dispatcher stays `unknown`-typed.\n return dispatcher as F;\n};\n","import { mkErr, mkOk } from \"./internal/ctor.js\";\nimport { dual } from \"./internal/dual.js\";\nimport type { Locked } from \"./internal/lock.js\";\nimport { toError } from \"./internal/to-error.js\";\nimport 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<42, never> — literal locked\n * const typed: Result<number, \"parse\"> = ok(1);\n * const lift = <T, E>(v: T): Result<T, E> => ok<T, E>(v); // explicit args opt out\n * ```\n *\n * @remarks\n * An inline literal keeps its narrow type instead of widening (`ok(\"a\")` is\n * `Result<\"a\", never>`, not `Result<string, never>`). Pass both type arguments\n * to opt out — generic code that must produce `Result<T, E>` for an unresolved\n * `T` needs that form.\n */\nexport function ok<const T>(value: T): Result<Locked<T>, never>;\nexport function ok<T, E>(value: T): Result<T, E>;\nexport function ok<T>(value: T): Result<T, never> {\n // Safe: `Locked<T>` only unwraps the readonly tuple that `const` inference\n // adds; the runtime payload is the value the caller passed, unchanged.\n return mkOk(value);\n}\n\n/**\n * Fantasy Land `pure` — alias of {@link ok}. One lift name shared across the\n * trio (`of` / `Maybe.of` / `ResultAsync.of`) for generic and FL-style code.\n *\n * @example\n * ```ts\n * const r = of(42); // Result<42, never> — identical to ok(42)\n * ```\n */\nexport const of = ok;\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, { readonly kind: \"parse\"; readonly message: string }>\n *\n * type AppError = { kind: \"parse\" } | { kind: \"io\" };\n * err<AppError>({ kind: \"io\" }); // Result<never, AppError> — one arg names the error\n * err<number, AppError>({ kind: \"io\" }); // Result<number, AppError> — neverthrow's T, E order\n * ```\n *\n * @remarks\n * One explicit type argument names the **error** channel, which is what the\n * call site almost always means. Both channels still take neverthrow's `T, E`\n * order, and that two-argument form is also the escape hatch for generic code:\n * inference-driven calls lock literals, so a generic `E` must be passed\n * explicitly to keep the error type from being rewritten.\n */\nexport function err<const E>(error: E): Result<never, Locked<E>>;\nexport function err<T, E>(error: E): Result<T, E>;\nexport function err<E>(error: E): Result<never, E> {\n // Safe: see the note on `ok` — `Locked` is a type-level unwrap only.\n return mkErr(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// ─────────────────────────────────────────────────────────────────────────────\n// Dual-form helpers — each export accepts either shape:\n// data-first: `map(result, fn)`\n// curried: `map(fn)(result)`\n// Arity dispatch is derived from the internal `dual` combinator\n// (src/internal/dual.ts); the const annotation carries the public overloads.\n// ─────────────────────────────────────────────────────────────────────────────\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 const map: {\n <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E>;\n <T, U>(fn: (value: T) => U): <E>(result: Result<T, E>) => Result<U, E>;\n} = dual(\n 2,\n <T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> =>\n isOk(result) ? mkOk(fn(result.value)) : mkErr(result.error),\n);\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 const mapErr: {\n <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F>;\n <E, F>(fn: (error: E) => F): <T>(result: Result<T, E>) => Result<T, F>;\n} = dual(\n 2,\n <T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F> =>\n isErr(result) ? mkErr(fn(result.error)) : mkOk(result.value),\n);\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 const bimap: {\n <T, U, E, F>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => F): Result<U, F>;\n <T, U, E, F>(\n onOk: (value: T) => U,\n onErr: (error: E) => F,\n ): (result: Result<T, E>) => Result<U, F>;\n} = dual(\n 3,\n <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) ? mkOk(onOk(result.value)) : mkErr(onErr(result.error))),\n);\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 const flatMap: {\n <T, U, E, F>(result: Result<T, E>, fn: (value: T) => Result<U, F>): Result<U, E | F>;\n <T, U, F>(fn: (value: T) => Result<U, F>): <E>(result: Result<T, E>) => Result<U, E | F>;\n} = dual(\n 2,\n <T, U, E, F>(result: Result<T, E>, fn: (value: T) => Result<U, F>): Result<U, E | F> =>\n isOk(result) ? fn(result.value) : mkErr(result.error),\n);\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 const recover: {\n <T, E, F>(result: Result<T, E>, fn: (error: E) => Result<T, F>): Result<T, F>;\n <T, E, F>(fn: (error: E) => Result<T, F>): (result: Result<T, E>) => Result<T, F>;\n} = dual(\n 2,\n <T, E, F>(result: Result<T, E>, fn: (error: E) => Result<T, F>): Result<T, F> =>\n isErr(result) ? fn(result.error) : mkOk(result.value),\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 const tap: {\n <T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E>;\n <T>(fn: (value: T) => void): <E>(result: Result<T, E>) => Result<T, E>;\n} = dual(2, <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 `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 const tapErr: {\n <T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E>;\n <E>(fn: (error: E) => void): <T>(result: Result<T, E>) => Result<T, E>;\n} = dual(2, <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 * 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`, use a namespace\n * import (`import * as R from \"@onrails/result\"` → `R.match`) to dissolve\n * the collision.\n *\n * @example\n * ```ts\n * const html = match(parsed, (cfg) => render(cfg), (e) => renderError(e));\n * ```\n */\nexport const match: {\n <T, E, U>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => U): U;\n <T, E, U>(onOk: (value: T) => U, onErr: (error: E) => U): (result: Result<T, E>) => U;\n} = dual(\n 3,\n <T, E, U>(result: Result<T, E>, onOk: (value: T) => U, onErr: (error: E) => U): U =>\n isOk(result) ? onOk(result.value) : onErr(result.error),\n);\n\n/**\n * Returns the `Ok` value, or `defaultValue` when the result is `Err`. The\n * fallback may be a different type from `T` — the return widens to `T | U`,\n * matching `ResultAsync.unwrapOr` and the compat shim.\n *\n * @example\n * ```ts\n * unwrapOr(parsedSetting, \"default-value\"); // string\n * unwrapOr(parsedPort, null); // number | null\n * ```\n */\nexport const unwrapOr: {\n <T, E, U>(result: Result<T, E>, defaultValue: U): T | U;\n <U>(defaultValue: U): <T, E>(result: Result<T, E>) => T | U;\n} = dual(2, <T, E, U>(result: Result<T, E>, defaultValue: U): T | U =>\n isOk(result) ? result.value : defaultValue,\n);\n\n/**\n * Test/assert helper — returns the `Ok` value, or **throws the original `Err`\n * value** when called on an `Err`. This is the assertion tier (RFC 0001 §4):\n * intended for `*.spec.ts` / `*.test.ts`, where throwing fails the test loudly.\n * In business logic prefer {@link match} or {@link unwrapOr}; the lint plugins\n * flag `unwrapOk` outside test files.\n *\n * @returns the unwrapped `Ok` value\n * @throws the carried `Err` value when the result is `Err`\n *\n * @example\n * ```ts\n * // in a *.spec.ts\n * expect(unwrapOk(ok(5))).toBe(5);\n * expect(() => unwrapOk(err(error))).toThrow(error);\n * ```\n */\nexport function unwrapOk<T, E>(result: Result<T, E>): T {\n if (isErr(result)) throw result.error;\n return result.value;\n}\n\n/** Alias of {@link unwrapOk} for syntax cohesion with `@onrails/maybe`. */\nexport const unwrap = unwrapOk;\n\n/**\n * Test/assert helper — returns the `Err` value, or **throws a `TypeError`**\n * when called on an `Ok`. Mirror of {@link unwrapOk} on the error track and\n * part of the same assertion tier (RFC 0001 §4): intended for `*.spec.ts` /\n * `*.test.ts`. Prefer {@link match} / {@link unwrapOr} in business logic; the\n * lint plugins flag `unwrapErr` outside test files.\n *\n * @returns the unwrapped `Err` value\n * @throws `TypeError` when the result is `Ok`\n *\n * @example\n * ```ts\n * // in a *.spec.ts\n * expect(unwrapErr(err(\"x\"))).toBe(\"x\");\n * expect(() => unwrapErr(ok(5))).toThrow(TypeError);\n * ```\n */\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/**\n * Wraps a throwing sync **function**, returning a function that produces a\n * {@link Result} instead of throwing. Thrown errors pass through `onThrow` to\n * become a typed `Err`; a normal return becomes `Ok`. Same name and shape as\n * neverthrow's `Result.fromThrowable`.\n *\n * Reach for {@link trySync} instead when you want to run the call right now\n * rather than build a reusable wrapper.\n *\n * @param fn - the throwing function to wrap\n * @param onThrow - maps a thrown value to the `Err` channel\n * @returns a function with `fn`'s parameters that returns `Result<ReturnType, E>`\n *\n * @example\n * ```ts\n * type ParseError = { kind: \"parse\"; message: string };\n * const parse = fromThrowable(\n * JSON.parse,\n * (e): ParseError => ({ kind: \"parse\", message: String(e) }),\n * );\n * parse(\"{}\"); // Ok({})\n * parse(\"nope\"); // Err({ kind: \"parse\", … })\n * ```\n */\nexport function fromThrowable<A extends readonly unknown[], T, E>(\n fn: (...args: A) => T,\n onThrow: (error: unknown) => E,\n): (...args: A) => Result<T, E>;\nexport function fromThrowable<F extends (...args: never) => unknown, E>(\n fn: F,\n onThrow: (error: unknown) => E,\n): (...args: Parameters<F>) => Result<ReturnType<F>, E>;\nexport function fromThrowable(\n fn: (...args: never) => unknown,\n onThrow: (error: unknown) => unknown,\n): (...args: never) => Result<unknown, unknown> {\n return (...args: never) => {\n try {\n return mkOk(fn(...args));\n } catch (error) {\n return mkErr(onThrow(error));\n }\n };\n}\n\n/**\n * Runs `fn` **now**, catching a throw into the `Err` track — the sync mirror\n * of `tryAsync`. Without `onThrow` the thrown value is normalized to an\n * `Error`; pass a mapper for a typed error.\n *\n * To lift a throwing function once and call it many times, use\n * {@link fromThrowable}.\n *\n * @param fn - the throwing thunk to run\n * @param onThrow - maps a thrown value to the `Err` channel\n *\n * @example\n * ```ts\n * trySync(() => JSON.parse(raw)); // Result<unknown, Error>\n * trySync(() => Schema.parse(input), (e): SchemaError => ({\n * kind: \"schema\",\n * cause: e,\n * }));\n * ```\n */\nexport function trySync<T>(fn: () => T): Result<T, Error>;\nexport function trySync<T, E>(fn: () => T, onThrow: (error: unknown) => E): Result<T, E>;\nexport function trySync<T, E>(fn: () => T, onThrow?: (error: unknown) => E): Result<T, E | Error> {\n try {\n return mkOk(fn());\n } catch (error) {\n return mkErr(onThrow ? onThrow(error) : toError(error));\n }\n}\n\nconst printPayload = (payload: unknown): string => {\n try {\n return JSON.stringify(payload) ?? String(payload);\n } catch {\n // cyclic or non-JSON payload — a debug printer must not throw\n return String(payload);\n }\n};\n\n/**\n * Debug printer — renders a result as `Ok(…)` / `Err(…)` for logs. Payloads\n * print as JSON (values are plain data by design); non-JSON payloads fall\n * back to `String(...)`.\n *\n * @example\n * ```ts\n * show(ok(1)); // 'Ok(1)'\n * show(err({ kind: \"e\" })); // 'Err({\"kind\":\"e\"})'\n * ```\n */\nexport const show = <T, E>(result: Result<T, E>): string =>\n isOk(result) ? `Ok(${printPayload(result.value)})` : `Err(${printPayload(result.error)})`;\n","/**\n * The core railway type: a tagged union carrying either a success value\n * (`Ok<T>`) or a failure value (`Err<E>`). It is a plain discriminated union\n * on `_tag` — no classes — so it is immutable and tree-shake friendly. Narrow\n * with {@link isOk} / {@link isErr} to read `.value` / `.error`.\n *\n * @typeParam T - the `Ok` value type\n * @typeParam E - the `Err` error type\n *\n * @example\n * ```ts\n * function parse(raw: string): Result<number, \"nan\"> {\n * const n = Number(raw);\n * return Number.isNaN(n) ? err(\"nan\") : ok(n);\n * }\n * ```\n */\nexport type Result<T, E> =\n | { readonly _tag: \"Ok\"; readonly value: T }\n | { readonly _tag: \"Err\"; readonly error: E };\n\n/**\n * The success branch of a {@link Result} — `{ _tag: \"Ok\"; value: T }`.\n * The `E` parameter keeps the type assignable to `Result<T, E>`.\n */\nexport type Ok<T, E = never> = Extract<Result<T, E>, { _tag: \"Ok\" }>;\n\n/**\n * The failure branch of a {@link Result} — `{ _tag: \"Err\"; error: E }`.\n */\nexport type Err<T, E> = Extract<Result<T, E>, { _tag: \"Err\" }>;\n\n/**\n * Error subclass representing an **unexpected** defect — a thrown exception or\n * promise rejection that was not part of the modelled `Err` union. Used as the\n * default mapping when {@link fromAsync} is called without an `onDefect`\n * handler; the original cause is preserved on `.cause`.\n *\n * @example\n * ```ts\n * const defect = new UnexpectedError(\"Unexpected async defect\", caught);\n * defect.cause; // the original thrown value\n * ```\n */\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 { mkErr, mkOk } from \"./internal/ctor.js\";\nimport type { InferErr, InferOk } from \"./internal/infer.js\";\nimport type { Locked } from \"./internal/lock.js\";\nimport { bimap, isErr, map, mapErr } from \"./result.js\";\nimport type { Result } from \"./types.js\";\nimport { UnexpectedError } from \"./types.js\";\n\ntype PromiseFactory<T, E> = () => Promise<Result<T, E>>;\ntype AnyResultAsync = ResultAsync<unknown, unknown>;\n\n/**\n * Mirrors the sync `CombineTuple` in `./collections.ts`: the element check\n * lives in the RETURN type, never in the parameter constraint. A\n * `ResultAsync<unknown, unknown>` constraint contextually types the arguments\n * and widens `okAsync(1)`'s defaulted `E = never` to `unknown`, so call sites\n * would need hoisted intermediates to keep their error union.\n */\ntype CombineTupleAsync<R extends readonly unknown[]> = R[number] extends AnyResultAsync\n ? ResultAsync<{ [K in keyof R]: InferOk<R[K]> }, InferErr<R[number]>>\n : never;\n\n/** Mirrors `TupleGuard` in `./collections.ts` — see the note there. */\ntype AsyncTupleGuard<R extends readonly unknown[]> = R[number] extends AnyResultAsync\n ? []\n : [error: \"expected an array of ResultAsync values\"];\n\n/** Collapses settled results left-to-right, short-circuiting on the first `Err`. */\nconst sequenceSettled = (\n settled: readonly Result<unknown, unknown>[],\n): Result<unknown[], unknown> => {\n const values: unknown[] = [];\n for (const result of settled) {\n if (isErr(result)) {\n return mkErr(result.error);\n }\n values.push(result.value);\n }\n return mkOk(values);\n};\n\n/**\n * Async railway carrier. Wraps a deferred `Promise<Result<T, E>>` and exposes\n * the same dual-track transforms as the sync {@link Result} — `map`, `mapErr`,\n * `bimap`, `flatMap`, `recover`, `tap`, `match`. The public API never surfaces `Promise<Result<…>>`\n * directly: `await` the instance (it is thenable) or call {@link resolve} /\n * {@link match} to settle it.\n *\n * Construct via the static factories ({@link ok}, {@link err}, {@link fromPromise},\n * {@link defer}, …) rather than `new` — the constructor is `protected`.\n *\n * @typeParam T - the `Ok` value type\n * @typeParam E - the `Err` error type\n *\n * @example\n * ```ts\n * const user = ResultAsync.fromPromise(api.getUser(id), toAppError)\n * .map((u) => u.profile)\n * .recover(() => ResultAsync.ok(guestProfile));\n *\n * const r = await user; // Result<Profile, AppError>\n * ```\n */\nexport class ResultAsync<T, E> {\n private promise: Promise<Result<T, E>> | null = null;\n\n protected constructor(protected readonly run: PromiseFactory<T, E>) {}\n\n /**\n * Lifts an already-settled sync {@link Result} into a {@link ResultAsync}.\n *\n * @example\n * ```ts\n * const ra = ResultAsync.fromResult(ok(42)); // ResultAsync<number, never>\n * ```\n */\n static fromResult<T, E>(result: Result<T, E>): ResultAsync<T, E> {\n return new ResultAsync(async () => result);\n }\n\n /**\n * Wraps a `PromiseLike<T>` that may reject. Rejections pass through `onReject`\n * to become a typed `Err`; resolution becomes `Ok<T>`.\n *\n * @param promise - the promise to wrap\n * @param onReject - maps a rejection reason to the `Err` channel\n *\n * @example\n * ```ts\n * const body = ResultAsync.fromPromise(\n * fetch(url).then((r) => r.text()),\n * (e): NetError => ({ kind: \"net\", cause: String(e) }),\n * );\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 mkOk(await promise);\n } catch (error) {\n return mkErr(onReject(error));\n }\n });\n }\n\n /**\n * Wraps a `PromiseLike<T>` that is **guaranteed not to reject**, skipping the\n * `onReject` mapper. Use only when rejection is provably impossible.\n *\n * @example\n * ```ts\n * const now = ResultAsync.fromSafePromise(Promise.resolve(Date.now()));\n * ```\n */\n static fromSafePromise<T, E = never>(promise: PromiseLike<T>): ResultAsync<T, E> {\n return new ResultAsync(async () => mkOk(await promise));\n }\n\n /**\n * Defers work until {@link resolve}. Unlike {@link fromPromise}, the factory\n * does not run until the `ResultAsync` is resolved (e.g. by `combineTuple` /\n * `combineTupleParallel`). The factory runs at most once — `resolve` memoizes.\n *\n * @example\n * ```ts\n * const insert = ResultAsync.defer(() => db.orders.insert(row));\n * // nothing has run yet\n * const r = await insert; // factory runs exactly once here\n * ```\n */\n static defer<T, E>(fn: () => Promise<Result<T, E>>): ResultAsync<T, E> {\n return new ResultAsync(fn);\n }\n\n /**\n * Lifts a value into an `Ok` async result.\n *\n * @example\n * ```ts\n * const r = ResultAsync.ok(42); // ResultAsync<number, never>\n * ```\n */\n static ok<const T>(value: T): ResultAsync<Locked<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 () => mkOk(value));\n }\n\n /**\n * Fantasy Land `pure` — alias of {@link ResultAsync.ok}. One lift name\n * shared across the trio (`of` / `Maybe.of` / `ResultAsync.of`).\n */\n static of<const T>(value: T): ResultAsync<Locked<T>, never>;\n static of<T, E>(value: T): ResultAsync<T, E>;\n static of<T, E = never>(value: T): ResultAsync<T, E> {\n return ResultAsync.ok<T, E>(value);\n }\n\n /**\n * Lifts an error into an `Err` async result.\n *\n * @example\n * ```ts\n * const r = ResultAsync.err({ kind: \"not_found\" as const });\n * ```\n */\n static err<const E>(error: E): ResultAsync<never, Locked<E>>;\n static err<T, E>(error: E): ResultAsync<T, E>;\n static err<T = never, E = unknown>(error: E): ResultAsync<T, E> {\n return new ResultAsync(async () => mkErr(error));\n }\n\n /**\n * Lifts an existing `Promise<Result<T, E>>` (e.g. from interop code) into a\n * {@link ResultAsync}. A thrown defect is routed through `onDefect`,\n * defaulting to {@link UnexpectedError}. The `Ok` value passes through\n * verbatim — even when it happens to be Result-shaped.\n *\n * @param promise - a promise that already yields a `Result`\n * @param onDefect - maps an unexpected throw to the `Err` channel\n * @see {@link fromAsync} from `@onrails/result`\n */\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<T, E | UnexpectedError>(async () => {\n try {\n return await promise;\n } catch (error) {\n return mkErr(mapDefect(error));\n }\n });\n }\n\n /**\n * Combines a homogeneous array of async results into one. Resolves\n * **sequentially** in input order, short-circuiting on the first `Err`.\n * For heterogeneous tuples that preserve per-index types, use\n * {@link combineTuple}; for wall-clock overlap, {@link combineTupleParallel}.\n *\n * @example\n * ```ts\n * const all = ResultAsync.combine([loadA(), loadB(), loadC()]);\n * // ResultAsync<Item[], LoadError>\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 mkErr(result.error);\n }\n values.push(result.value);\n }\n return mkOk(values);\n });\n }\n\n /**\n * Heterogeneous async tuple combine — resolves branches **sequentially**\n * (left-to-right), returning the first `Err` in input order. Preserves each\n * branch's `Ok` type by position, so the result destructures type-safely.\n * This is the canonical sequential async combine (replaces the former\n * `sequenceTupleAsync`).\n *\n * @example\n * ```ts\n * const combined = ResultAsync.combineTuple([loadCfg(), loadCatalog()]);\n * // ResultAsync<readonly [Cfg, Catalog], CfgError | CatalogError>\n * const r = await combined;\n * if (isOk(r)) {\n * const [cfg, catalog] = r.value; // typed per position\n * }\n * ```\n */\n static combineTuple<const R extends readonly unknown[]>(\n results: R,\n ..._guard: AsyncTupleGuard<R>\n ): CombineTupleAsync<R> {\n // Runtime identical to combine; the cast restores per-index tuple types.\n return ResultAsync.combine(\n results as readonly AnyResultAsync[],\n ) as unknown 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 * @example\n * ```ts\n * // independent IO — overlap them\n * const combined = ResultAsync.combineTupleParallel([\n * loadProfile(id),\n * loadMetrics(id),\n * ]);\n * ```\n */\n static combineTupleParallel<const R extends readonly unknown[]>(\n results: R,\n ..._guard: AsyncTupleGuard<R>\n ): CombineTupleAsync<R> {\n // Cast restores per-index tuple types over the untyped sequence core.\n return new ResultAsync(async () =>\n sequenceSettled(\n await Promise.all((results as readonly AnyResultAsync[]).map((ra) => ra.resolve())),\n ),\n ) as unknown as CombineTupleAsync<R>;\n }\n\n /**\n * Transforms the `Ok` value, passing `Err` through unchanged.\n *\n * @example\n * ```ts\n * ResultAsync.ok(2).map((n) => n * 3); // ResultAsync<number> → Ok 6\n * ```\n */\n map<U>(fn: (value: T) => U): ResultAsync<U, E> {\n return new ResultAsync(async () => map(await this.resolve(), fn));\n }\n\n /**\n * Transforms the `Err` value, passing `Ok` through unchanged — useful for\n * unifying heterogeneous failures into one app-level union.\n *\n * @example\n * ```ts\n * load(id).mapErr((e): AppError => ({ kind: \"load\", cause: e })); // ResultAsync<T, AppError>\n * ```\n */\n mapErr<F>(fn: (error: E) => F): ResultAsync<T, F> {\n return new ResultAsync(async () => mapErr(await this.resolve(), fn));\n }\n\n /**\n * Transforms both tracks in one step — the async mirror of the sync\n * `bimap`. Exactly one of `onOk` / `onErr` runs.\n *\n * @example\n * ```ts\n * load(id).bimap(toDto, (e): AppError => ({ kind: \"load\", cause: e }));\n * ```\n */\n bimap<U, F>(onOk: (value: T) => U, onErr: (error: E) => F): ResultAsync<U, F> {\n return new ResultAsync(async () => bimap(await this.resolve(), onOk, onErr));\n }\n\n /**\n * Canonical bind — chains a step that itself returns a `ResultAsync` or sync\n * `Result`, short-circuiting on `Err`. Error types accumulate (`E | F`).\n *\n * @example\n * ```ts\n * authenticate(req)\n * .flatMap((user) => loadProfile(user.id)) // ResultAsync\n * .flatMap((p) => validate(p)); // sync Result also accepted\n * ```\n */\n flatMap<U, F = E>(fn: (value: T) => ResultAsync<U, F> | Result<U, F>): ResultAsync<U, E | F> {\n return new ResultAsync<U, E | F>(async () => {\n const first = await this.resolve();\n if (isErr(first)) {\n return first;\n }\n const next = fn(first.value);\n return next instanceof ResultAsync ? next.resolve() : next;\n });\n }\n\n /**\n * neverthrow-compat alias of {@link flatMap}. Kept as the documented compat\n * tier; prefer {@link flatMap} in new code.\n *\n * @example\n * ```ts\n * authenticate(req).andThen((user) => loadProfile(user.id));\n * ```\n */\n andThen<U, F = E>(fn: (value: T) => ResultAsync<U, F> | Result<U, F>): ResultAsync<U, E | F> {\n return this.flatMap(fn);\n }\n\n /**\n * Error-channel bind — runs `fn` only on `Err`, swapping in a recovery\n * `ResultAsync` or sync `Result`. `Ok` passes through. The mirror of\n * {@link flatMap} on the error track.\n *\n * @example\n * ```ts\n * loadFromCache(id).recover(() => loadFromOrigin(id)); // ResultAsync<T, F>\n * ```\n */\n recover<F>(fn: (error: E) => ResultAsync<T, F> | Result<T, F>): ResultAsync<T, F> {\n return new ResultAsync<T, F>(async () => {\n const first = await this.resolve();\n if (!isErr(first)) {\n return first;\n }\n const next = fn(first.error);\n return next instanceof ResultAsync ? next.resolve() : next;\n });\n }\n\n /**\n * neverthrow-compat alias of {@link recover}. Kept as the documented compat\n * tier; prefer {@link recover} in new code.\n *\n * @example\n * ```ts\n * loadFromCache(id).orElse(() => loadFromOrigin(id));\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 /**\n * Runs a side effect on the `Ok` value and passes the result through\n * unchanged; a no-op on `Err`. Mirrors {@link tapErr}.\n *\n * @example\n * ```ts\n * saveUser(u).tap((saved) => analytics.track(\"user_saved\", saved.id));\n * ```\n */\n tap(fn: (value: T) => void): ResultAsync<T, E> {\n return new ResultAsync(async () => {\n const result = await this.resolve();\n if (!isErr(result)) {\n fn(result.value);\n }\n return result;\n });\n }\n\n /**\n * Runs a side effect on the `Err` value and passes the result through\n * unchanged; a no-op on `Ok`. The error-track mirror of {@link tap}.\n *\n * @example\n * ```ts\n * saveUser(u).tapErr((e) => logger.warn(\"save failed\", e));\n * ```\n */\n tapErr(fn: (error: E) => void): ResultAsync<T, E> {\n return new ResultAsync(async () => {\n const result = await this.resolve();\n if (isErr(result)) {\n fn(result.error);\n }\n return result;\n });\n }\n\n /**\n * Settles to the `Ok` value, or `defaultValue` if `Err`. Terminal — returns a\n * plain `Promise`, not a `ResultAsync`.\n *\n * @example\n * ```ts\n * const profile = await loadProfile(id).unwrapOr(guestProfile);\n * ```\n */\n unwrapOr<U>(defaultValue: U): Promise<T | U> {\n return this.resolve().then((result) => (isErr(result) ? defaultValue : result.value));\n }\n\n /**\n * Terminal collapse — folds both tracks into a single awaited value. Returns\n * a plain `Promise`, settling the carrier exactly once.\n *\n * @param onOk - handles the `Ok` value\n * @param onErr - handles the `Err` value\n *\n * @example\n * ```ts\n * const status = await save(row).match(\n * () => 200,\n * (e) => (e.kind === \"conflict\" ? 409 : 500),\n * );\n * ```\n */\n match<U1, U2 = U1>(onOk: (value: T) => U1, onErr: (error: E) => U2): Promise<U1 | U2> {\n return this.resolve().then((result) =>\n isErr(result) ? onErr(result.error) : onOk(result.value),\n );\n }\n\n /**\n * Settles the carrier to a bare sync {@link Result}, memoizing so the\n * underlying factory runs at most once. Prefer `await ra` (the thenable) or\n * {@link match} in app code; use `resolve` when you need the tagged union back.\n *\n * @example\n * ```ts\n * const r = await load(id).resolve(); // Result<Data, LoadError>\n * if (isOk(r)) use(r.value);\n * ```\n */\n resolve(): Promise<Result<T, E>> {\n if (!this.promise) {\n this.promise = this.run();\n }\n return this.promise;\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.resolve().then(\n // Safe: without onfulfilled, R1 stays at its Result<T, E> default.\n (r) => (onfulfilled ? onfulfilled(r) : (r as unknown as R1)),\n onrejected ?? undefined,\n );\n }\n}\n\n/**\n * The free-function lift helpers (`okAsync`, `errAsync`, `fromPromise`,\n * `fromSafePromise`, `fromResult`, `fromAsync`, `asyncAfter`, `tryAsync`)\n * live in `./async-lift.ts` and are re-exported from the package index.\n */\n","import { ResultAsync } from \"./async.js\";\nimport { mkErr, mkOk } from \"./internal/ctor.js\";\nimport { flatMap, fromThrowable, map } 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 * Runtime carrier for a workflow. Invariant: the `mode` tag mirrors the\n * phantom `M` on {@link Railway} — every construction site writes matching\n * tag and type parameter, and {@link Railway.step} / {@link Railway.out}\n * are the only places that re-link the two.\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\nexport type BranchFn<C extends object> = (ctx: C) => ResultAsync<unknown, unknown>;\nexport type 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;\nexport type ParallelOutput<R extends BranchRecord> = {\n [K in keyof R]: BranchOk<R[K]>;\n};\nexport type ParallelError<R extends BranchRecord> = BranchErr<R[keyof R]>;\n\n/** Collapses an intersection into a single displayed object type. */\ntype Prettify<T> = { [K in keyof T]: T[K] } & {};\n\n/**\n * The context after one more named step. Chaining `C & Record<K, T>` instead\n * builds an intersection that TS echoes verbatim in every hover and error\n * message (`Record<never, never> & Record<\"id\", string> & …`); `Omit` keeps\n * property modifiers and `Prettify` collapses the result to a flat object.\n */\ntype Extend<C extends object, K extends string, T> = Prettify<Omit<C, K> & Record<K, T>>;\n\n/**\n * Rejects a key already present in the context. Railway merges each step with\n * a spread, so a repeated key overwrites at runtime while the old\n * `C & Record<K, T>` type intersected the two field types — `number & string`\n * became `never` and nothing complained. Resolves to `[]` for a fresh key and\n * to an unsatisfiable extra parameter otherwise, so the collision fails at the\n * call site with the offending name in the message.\n */\ntype FreshKey<C, K extends string> = K extends keyof C\n ? [error: `key \"${K}\" already exists in the workflow context`]\n : [];\n\n/** {@link FreshKey} for a whole record of parallel branches. */\ntype FreshKeys<C, R> =\n Extract<keyof R, keyof C> extends never\n ? []\n : [\n error: `branch key \"${Extract<keyof R, keyof C> & string}\" already exists in the workflow context`,\n ];\n\nconst addField = <C extends object, K extends string, T>(\n ctx: C,\n key: K,\n value: T,\n): Extend<C, K, T> => ({ ...ctx, [key]: value }) as Extend<C, K, T>;\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 */\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: mkOk({}) });\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: mkOk(context) });\n }\n\n /** Start a sync workflow with a throwing function. */\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().addSync(key, () => fromThrowable(fn, onThrow)()) as Railway<\n Record<K, T>,\n E,\n \"sync\"\n >;\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().addSync(key, fn) as Railway<Record<K, T>, E, \"sync\">;\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().addAsync(key, () => ResultAsync.fromPromise(fn(), onReject)) as Railway<\n Record<K, T>,\n E,\n \"async\"\n >;\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().addAsync(key, fn) as Railway<Record<K, T>, E, \"async\">;\n }\n\n /**\n * Rebuild the workflow in its current mode after transforming the carried\n * result. Single re-link point for the state/phantom invariant: the mode\n * tag is preserved verbatim, so `M` still describes the new state — TS\n * cannot narrow the phantom `M` from the runtime tag, hence the cast.\n */\n private step<C2 extends object, F>(\n onSync: (result: Result<C, E>) => Result<C2, E | F>,\n onAsync: (result: ResultAsync<C, E>) => ResultAsync<C2, E | F>,\n ): Railway<C2, E | F, M> {\n const next: RailwayState<C2, E | F> =\n this.state.mode === \"sync\"\n ? { mode: \"sync\", result: onSync(this.state.result) }\n : { mode: \"async\", result: onAsync(this.state.result) };\n return new Railway(next) as Railway<C2, E | F, M>;\n }\n\n /**\n * Project the carried result into the mode-aware output type. Counterpart\n * of {@link Railway.step} for terminal steps: the runtime branch matches\n * the branch `RailwayOutput` picks for `M` (state/phantom invariant), but\n * TS cannot resolve the conditional on an unresolved `M`, hence the cast.\n */\n private out<T>(\n onSync: (result: Result<C, E>) => Result<T, E>,\n onAsync: (result: ResultAsync<C, E>) => ResultAsync<T, E>,\n ): RailwayOutput<T, E, M> {\n return (\n this.state.mode === \"sync\" ? onSync(this.state.result) : onAsync(this.state.result)\n ) as RailwayOutput<T, E, M>;\n }\n\n /** Lift the carried result into `ResultAsync` for async-upgrading steps. */\n private toAsync(): ResultAsync<C, E> {\n return this.state.mode === \"sync\"\n ? ResultAsync.fromResult(this.state.result)\n : this.state.result;\n }\n\n /**\n * Internal plumbing for a sync field append. Public steps wrap this and add\n * the {@link FreshKey} collision guard; the static factories bypass the\n * guard because they always start from an empty context.\n */\n private addSync<K extends string, T, F>(\n key: K,\n fn: (ctx: C) => Result<T, F>,\n ): Railway<Extend<C, K, T>, E | F, M> {\n return this.step<Extend<C, K, T>, F>(\n (result) => flatMap(result, (ctx) => map(fn(ctx), (value) => addField(ctx, key, value))),\n (result) =>\n result.flatMap((ctx) =>\n ResultAsync.fromResult(fn(ctx)).map((value) => addField(ctx, key, value)),\n ),\n );\n }\n\n /** Internal plumbing for an async field append — upgrades the mode. */\n private addAsync<K extends string, T, F>(\n key: K,\n fn: (ctx: C) => ResultAsync<T, F>,\n ): Railway<Extend<C, K, T>, E | F, \"async\"> {\n return new Railway({\n mode: \"async\",\n result: this.toAsync().flatMap((ctx) => fn(ctx).map((value) => addField(ctx, key, value))),\n });\n }\n\n /** Pure sync derivation. */\n derive<K extends string, T>(\n key: K,\n fn: (ctx: C) => T,\n ..._guard: FreshKey<C, K>\n ): Railway<Extend<C, K, T>, E, M> {\n return this.addSync(key, (ctx) => mkOk(fn(ctx)));\n }\n\n /** Throwing sync transform. */\n fromSync<K extends string, T, F>(\n key: K,\n fn: (ctx: C) => T,\n onThrow: (error: unknown) => F,\n ..._guard: FreshKey<C, K>\n ): Railway<Extend<C, K, T>, E | F, M> {\n return this.addSync(key, (ctx) => fromThrowable(fn, onThrow)(ctx));\n }\n\n /** Sync `Result`-returning step. */\n fromResult<K extends string, T, F>(\n key: K,\n fn: (ctx: C) => Result<T, F>,\n ..._guard: FreshKey<C, K>\n ): Railway<Extend<C, K, T>, E | F, M> {\n return this.addSync(key, fn);\n }\n\n /** Promise-returning step — upgrades the workflow to async mode. */\n fromPromise<K extends string, T, F>(\n key: K,\n fn: (ctx: C) => PromiseLike<T>,\n onReject: (error: unknown) => F,\n ..._guard: FreshKey<C, K>\n ): Railway<Extend<C, K, T>, E | F, \"async\"> {\n return this.addAsync(key, (ctx) => ResultAsync.fromPromise(fn(ctx), onReject));\n }\n\n /** `ResultAsync`-returning step — upgrades the workflow to async mode. */\n fromAsync<K extends string, T, F>(\n key: K,\n fn: (ctx: C) => ResultAsync<T, F>,\n ..._guard: FreshKey<C, K>\n ): Railway<Extend<C, K, T>, E | F, \"async\"> {\n return this.addAsync(key, fn);\n }\n\n /** Narrow a nullable context field into a required non-null field. */\n require<K extends string, S extends keyof C, F>(\n key: K,\n source: S,\n onMissing: (ctx: C) => F,\n ..._guard: FreshKey<C, K>\n ): Railway<Extend<C, K, NonNullable<C[S]>>, E | F, M> {\n return this.addSync(key, (ctx) => {\n const value = ctx[source];\n return value == null ? mkErr(onMissing(ctx)) : mkOk(value as NonNullable<C[S]>);\n });\n }\n\n /** Run independent `ResultAsync` branches concurrently and merge outputs. */\n parallel<R extends Record<string, BranchFn<C>>>(\n branches: R,\n ..._guard: FreshKeys<C, R>\n ): Railway<Prettify<Omit<C, keyof R> & ParallelOutput<R>>, E | ParallelError<R>, \"async\"> {\n const merged = this.toAsync().flatMap((ctx) =>\n ResultAsync.combineTupleParallel(\n Object.entries(branches).map(([, branch]) => branch(ctx)),\n ).map(\n (values) =>\n // Branch outputs land under exactly R's keys; Object.fromEntries\n // erases that correspondence, so reassert the merged shape.\n ({\n ...ctx,\n ...Object.fromEntries(Object.keys(branches).map((key, index) => [key, values[index]])),\n }) as Prettify<Omit<C, keyof R> & ParallelOutput<R>>,\n ),\n );\n return new Railway({\n mode: \"async\",\n // BranchFn erases per-key types to `ResultAsync<unknown, unknown>`\n // (ParallelOutput/ParallelError recover them from R), so re-assert the\n // precise value/error union the branches actually produce.\n result: merged as ResultAsync<\n Prettify<Omit<C, keyof R> & ParallelOutput<R>>,\n E | ParallelError<R>\n >,\n });\n }\n\n /** Project the final context into the workflow's output type. */\n select<T>(fn: (ctx: C) => T): RailwayOutput<T, E, M> {\n return this.out(\n (result) => map(result, fn),\n (result) => result.map(fn),\n );\n }\n\n /** Return the accumulated context as-is. */\n done(): RailwayOutput<C, E, M> {\n return this.out(\n (result) => result,\n (result) => result,\n );\n }\n}\n"]}
|