@onrails/result 0.4.0 → 0.4.2

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.
Files changed (73) hide show
  1. package/DESIGN.md +1 -1
  2. package/README.md +168 -12
  3. package/RECIPES.md +11 -9
  4. package/dist/async-fns.cjs +52 -0
  5. package/dist/async-fns.cjs.map +1 -0
  6. package/dist/async-fns.d.cts +143 -0
  7. package/dist/async-fns.d.ts +143 -0
  8. package/dist/async-fns.js +42 -0
  9. package/dist/async-fns.js.map +1 -0
  10. package/dist/async-lift.d.cts +109 -0
  11. package/dist/async-lift.d.ts +109 -0
  12. package/dist/{async-Ci6WSL5-.d.ts → async.d.cts} +45 -58
  13. package/dist/{async-DcXR7k9K.d.cts → async.d.ts} +45 -58
  14. package/dist/collections.d.cts +105 -0
  15. package/dist/collections.d.ts +105 -0
  16. package/dist/compat/neverthrow.cjs +57 -45
  17. package/dist/compat/neverthrow.cjs.map +1 -1
  18. package/dist/compat/neverthrow.d.cts +21 -24
  19. package/dist/compat/neverthrow.d.ts +21 -24
  20. package/dist/compat/neverthrow.js +56 -44
  21. package/dist/compat/neverthrow.js.map +1 -1
  22. package/dist/extra.cjs +3 -1
  23. package/dist/extra.cjs.map +1 -1
  24. package/dist/extra.d.cts +11 -14
  25. package/dist/extra.d.ts +11 -14
  26. package/dist/extra.js +3 -1
  27. package/dist/extra.js.map +1 -1
  28. package/dist/fluent.cjs +15 -13
  29. package/dist/fluent.cjs.map +1 -1
  30. package/dist/fluent.d.cts +4 -7
  31. package/dist/fluent.d.ts +4 -7
  32. package/dist/fluent.js +15 -13
  33. package/dist/fluent.js.map +1 -1
  34. package/dist/index.cjs +77 -52
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +28 -490
  37. package/dist/index.d.ts +28 -490
  38. package/dist/index.js +77 -53
  39. package/dist/index.js.map +1 -1
  40. package/dist/internal/ctor.d.cts +11 -0
  41. package/dist/internal/ctor.d.ts +11 -0
  42. package/dist/internal/dual.d.cts +42 -0
  43. package/dist/internal/dual.d.ts +42 -0
  44. package/dist/internal/infer.d.cts +40 -0
  45. package/dist/internal/infer.d.ts +40 -0
  46. package/dist/internal/payload.d.cts +17 -0
  47. package/dist/internal/payload.d.ts +17 -0
  48. package/dist/internal/to-error.d.cts +2 -0
  49. package/dist/internal/to-error.d.ts +2 -0
  50. package/dist/pipe.cjs +8 -0
  51. package/dist/pipe.cjs.map +1 -1
  52. package/dist/pipe.d.cts +58 -11
  53. package/dist/pipe.d.ts +58 -11
  54. package/dist/pipe.js +8 -1
  55. package/dist/pipe.js.map +1 -1
  56. package/dist/railway.cjs +87 -63
  57. package/dist/railway.cjs.map +1 -1
  58. package/dist/railway.d.cts +49 -19
  59. package/dist/railway.d.ts +49 -19
  60. package/dist/railway.js +87 -63
  61. package/dist/railway.js.map +1 -1
  62. package/dist/result.d.cts +317 -0
  63. package/dist/result.d.ts +317 -0
  64. package/dist/try-gen.cjs +3 -3
  65. package/dist/try-gen.cjs.map +1 -1
  66. package/dist/try-gen.d.cts +4 -7
  67. package/dist/try-gen.d.ts +4 -7
  68. package/dist/try-gen.js +3 -3
  69. package/dist/try-gen.js.map +1 -1
  70. package/dist/{types-BQ9vv0nD.d.cts → types.d.cts} +6 -8
  71. package/dist/{types-BQ9vv0nD.d.ts → types.d.ts} +6 -8
  72. package/package.json +69 -24
  73. package/skills/railway-do-notation/SKILL.md +9 -9
@@ -1,56 +1,25 @@
1
- import { R as Result, U as UnexpectedError } from './types-BQ9vv0nD.cjs';
2
-
3
- /**
4
- * @onrails/result internal — the single payload-extraction pair.
5
- *
6
- * `InferOk` / `InferErr` pull the success/error type out of a {@link Result}
7
- * (tagged union) or a {@link ResultAsync} (class carrier), resolving to
8
- * `never` for anything else. Every module that needs to extract a payload
9
- * type imports from here; do not redeclare local copies.
10
- *
11
- * Internal only: not listed in package.json `exports` or tsup entries.
12
- * The package index re-exports the pair under the same names.
13
- */
14
-
15
- /**
16
- * Extracts the `Ok` value type from a {@link Result} or {@link ResultAsync},
17
- * resolving to `never` for any other type.
18
- *
19
- * @example
20
- * ```ts
21
- * type T = InferOk<Result<number, string>>; // number
22
- * type U = InferOk<ResultAsync<User, AppError>>; // User
23
- * ```
24
- */
25
- type InferOk<R> = R extends {
26
- _tag: "Ok";
27
- readonly value: infer T;
28
- } ? T : R extends ResultAsync<infer T, unknown> ? T : never;
1
+ import type { InferErr, InferOk } from "./internal/infer.js";
2
+ import type { Payload } from "./internal/payload.js";
3
+ import type { Result } from "./types.js";
4
+ import { UnexpectedError } from "./types.js";
5
+ type PromiseFactory<T, E> = () => Promise<Result<T, E>>;
6
+ type AnyResultAsync = ResultAsync<unknown, unknown>;
29
7
  /**
30
- * Extracts the `Err` error type from a {@link Result} or {@link ResultAsync},
31
- * resolving to `never` for any other type. Mirror of {@link InferOk}.
32
- *
33
- * @example
34
- * ```ts
35
- * type E = InferErr<Result<number, string>>; // string
36
- * type F = InferErr<ResultAsync<User, AppError>>; // AppError
37
- * ```
8
+ * Mirrors the sync `CombineTuple` in `./collections.ts`: the element check
9
+ * lives in the RETURN type, never in the parameter constraint. A
10
+ * `ResultAsync<unknown, unknown>` constraint contextually types the arguments
11
+ * and widens `okAsync(1)`'s defaulted `E = never` to `unknown`, so call sites
12
+ * would need hoisted intermediates to keep their error union.
38
13
  */
39
- type InferErr<R> = R extends {
40
- _tag: "Err";
41
- readonly error: infer E;
42
- } ? E : R extends ResultAsync<unknown, infer E> ? E : never;
43
-
44
- type PromiseFactory<T, E> = () => Promise<Result<T, E>>;
45
- type CombineTupleAsync<R extends readonly ResultAsync<unknown, unknown>[]> = ResultAsync<{
14
+ type CombineTupleAsync<R extends readonly unknown[]> = R[number] extends AnyResultAsync ? ResultAsync<{
46
15
  [K in keyof R]: InferOk<R[K]>;
47
- }, {
48
- [K in keyof R]: InferErr<R[K]>;
49
- }[number]>;
16
+ }, InferErr<R[number]>> : never;
17
+ /** Mirrors `TupleGuard` in `./collections.ts` — see the note there. */
18
+ type AsyncTupleGuard<R extends readonly unknown[]> = R[number] extends AnyResultAsync ? [] : [error: "expected an array of ResultAsync values"];
50
19
  /**
51
20
  * Async railway carrier. Wraps a deferred `Promise<Result<T, E>>` and exposes
52
- * the same dual-track transforms as the sync {@link Result} — `map`, `flatMap`,
53
- * `recover`, `tap`, `match`. The public API never surfaces `Promise<Result<…>>`
21
+ * the same dual-track transforms as the sync {@link Result} — `map`, `mapErr`,
22
+ * `bimap`, `flatMap`, `recover`, `tap`, `match`. The public API never surfaces `Promise<Result<…>>`
54
23
  * directly: `await` the instance (it is thenable) or call {@link resolve} /
55
24
  * {@link match} to settle it.
56
25
  *
@@ -69,7 +38,7 @@ type CombineTupleAsync<R extends readonly ResultAsync<unknown, unknown>[]> = Res
69
38
  * const r = await user; // Result<Profile, AppError>
70
39
  * ```
71
40
  */
72
- declare class ResultAsync<T, E> {
41
+ export declare class ResultAsync<T, E> {
73
42
  protected readonly run: PromiseFactory<T, E>;
74
43
  private promise;
75
44
  protected constructor(run: PromiseFactory<T, E>);
@@ -129,13 +98,15 @@ declare class ResultAsync<T, E> {
129
98
  * const r = ResultAsync.ok(42); // ResultAsync<number, never>
130
99
  * ```
131
100
  */
132
- static ok<T>(value: T): ResultAsync<T, never>;
101
+ static ok<const T extends Payload[]>(value: T): ResultAsync<T, never>;
102
+ static ok<const T>(value: T): ResultAsync<T, never>;
133
103
  static ok<T, E>(value: T): ResultAsync<T, E>;
134
104
  /**
135
105
  * Fantasy Land `pure` — alias of {@link ResultAsync.ok}. One lift name
136
106
  * shared across the trio (`of` / `Maybe.of` / `ResultAsync.of`).
137
107
  */
138
- static of<T>(value: T): ResultAsync<T, never>;
108
+ static of<const T extends Payload[]>(value: T): ResultAsync<T, never>;
109
+ static of<const T>(value: T): ResultAsync<T, never>;
139
110
  static of<T, E>(value: T): ResultAsync<T, E>;
140
111
  /**
141
112
  * Lifts an error into an `Err` async result.
@@ -145,7 +116,9 @@ declare class ResultAsync<T, E> {
145
116
  * const r = ResultAsync.err({ kind: "not_found" as const });
146
117
  * ```
147
118
  */
148
- static err<T = never, E = unknown>(error: E): ResultAsync<T, E>;
119
+ static err<const E extends Payload[]>(error: E): ResultAsync<never, E>;
120
+ static err<const E>(error: E): ResultAsync<never, E>;
121
+ static err<T, E>(error: E): ResultAsync<T, E>;
149
122
  /**
150
123
  * Lifts an existing `Promise<Result<T, E>>` (e.g. from interop code) into a
151
124
  * {@link ResultAsync}. A thrown defect is routed through `onDefect`,
@@ -179,7 +152,7 @@ declare class ResultAsync<T, E> {
179
152
  *
180
153
  * @example
181
154
  * ```ts
182
- * const combined = ResultAsync.combineTuple([loadCfg(), loadCatalog()] as const);
155
+ * const combined = ResultAsync.combineTuple([loadCfg(), loadCatalog()]);
183
156
  * // ResultAsync<readonly [Cfg, Catalog], CfgError | CatalogError>
184
157
  * const r = await combined;
185
158
  * if (isOk(r)) {
@@ -187,7 +160,7 @@ declare class ResultAsync<T, E> {
187
160
  * }
188
161
  * ```
189
162
  */
190
- static combineTuple<const R extends readonly ResultAsync<unknown, unknown>[]>(results: R): CombineTupleAsync<R>;
163
+ static combineTuple<const R extends readonly unknown[]>(results: R, ..._guard: AsyncTupleGuard<R>): CombineTupleAsync<R>;
191
164
  /**
192
165
  * Like {@link combineTuple}, but starts every branch before awaiting (wall-clock
193
166
  * parallel for independent IO). On failure, returns the first `Err` in input order.
@@ -198,10 +171,10 @@ declare class ResultAsync<T, E> {
198
171
  * const combined = ResultAsync.combineTupleParallel([
199
172
  * loadProfile(id),
200
173
  * loadMetrics(id),
201
- * ] as const);
174
+ * ]);
202
175
  * ```
203
176
  */
204
- static combineTupleParallel<const R extends readonly ResultAsync<unknown, unknown>[]>(results: R): CombineTupleAsync<R>;
177
+ static combineTupleParallel<const R extends readonly unknown[]>(results: R, ..._guard: AsyncTupleGuard<R>): CombineTupleAsync<R>;
205
178
  /**
206
179
  * Transforms the `Ok` value, passing `Err` through unchanged.
207
180
  *
@@ -221,6 +194,16 @@ declare class ResultAsync<T, E> {
221
194
  * ```
222
195
  */
223
196
  mapErr<F>(fn: (error: E) => F): ResultAsync<T, F>;
197
+ /**
198
+ * Transforms both tracks in one step — the async mirror of the sync
199
+ * `bimap`. Exactly one of `onOk` / `onErr` runs.
200
+ *
201
+ * @example
202
+ * ```ts
203
+ * load(id).bimap(toDto, (e): AppError => ({ kind: "load", cause: e }));
204
+ * ```
205
+ */
206
+ bimap<U, F>(onOk: (value: T) => U, onErr: (error: E) => F): ResultAsync<U, F>;
224
207
  /**
225
208
  * Canonical bind — chains a step that itself returns a `ResultAsync` or sync
226
209
  * `Result`, short-circuiting on `Err`. Error types accumulate (`E | F`).
@@ -328,5 +311,9 @@ declare class ResultAsync<T, E> {
328
311
  */
329
312
  then<R1 = Result<T, E>, R2 = never>(onfulfilled?: ((value: Result<T, E>) => R1 | PromiseLike<R1>) | undefined | null, onrejected?: ((reason: unknown) => R2 | PromiseLike<R2>) | undefined | null): Promise<R1 | R2>;
330
313
  }
331
-
332
- export { type InferErr as I, ResultAsync as R, type InferOk as a };
314
+ export {};
315
+ /**
316
+ * The free-function lift helpers (`okAsync`, `errAsync`, `fromPromise`,
317
+ * `fromSafePromise`, `fromResult`, `fromAsync`, `asyncAfter`, `tryAsync`)
318
+ * live in `./async-lift.ts` and are re-exported from the package index.
319
+ */
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @onrails/result — sync aggregation, one module, two axes:
3
+ *
4
+ * short-circuit (first `Err` wins) — {@link combine} / {@link combineTuple}
5
+ * accumulate expected failures — {@link validateAll} / {@link validateTuple}
6
+ *
7
+ * The accumulate pair collects every failure into a readonly array by
8
+ * default, or folds them with an explicit `combineErrors` when given one.
9
+ */
10
+ import type { InferErr, InferOk } from "./internal/infer.js";
11
+ import type { Result } from "./types.js";
12
+ /**
13
+ * Combines a homogeneous array of results into a single result holding an
14
+ * array of the `Ok` values, in input order. Short-circuits on the first `Err`
15
+ * (first failure wins). For heterogeneous tuples that preserve per-index
16
+ * types, use {@link combineTuple}.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * combine([ok(1), ok(2)]); // Ok([1, 2])
21
+ * combine([ok(1), err("e")]); // Err("e")
22
+ * ```
23
+ */
24
+ export declare const combine: <T, E>(results: readonly Result<T, E>[]) => Result<T[], E>;
25
+ type AnyResult = Result<unknown, unknown>;
26
+ /** Positionally preserved `Ok` payloads for a tuple of results. */
27
+ type OkTuple<R extends readonly unknown[]> = {
28
+ [K in keyof R]: InferOk<R[K]>;
29
+ };
30
+ /**
31
+ * The element check lives in the RETURN type, never in the parameter
32
+ * constraint. A `readonly Result<unknown, unknown>[]` constraint contextually
33
+ * types the arguments, which widens `ok(1)`'s defaulted `E = never` — and
34
+ * `err(e)`'s `T = never` — all the way to `unknown`. Holding the parameter at
35
+ * a bare `R` keeps both channels precise for inline literals, so call sites
36
+ * need neither `as const` nor hoisted intermediates.
37
+ */
38
+ type CombineTuple<R extends readonly unknown[]> = R[number] extends AnyResult ? Result<OkTuple<R>, InferErr<R[number]>> : never;
39
+ /**
40
+ * Restores the "every element is a Result" check the parameter constraint used
41
+ * to provide. Resolves to `[]` for a well-formed tuple and to a one-element
42
+ * tuple otherwise, so a bad call fails at the call site (with the message
43
+ * visible in signature help) instead of silently yielding `never`.
44
+ */
45
+ type TupleGuard<R extends readonly unknown[]> = R[number] extends AnyResult ? [] : [error: "expected an array of Result values"];
46
+ /**
47
+ * Heterogeneous tuple combine — like {@link combine} but preserves each
48
+ * branch's `Ok` type by position, so the result destructures type-safely.
49
+ * Short-circuits on the first `Err` in input order (neverthrow-style).
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * const r = combineTuple([ok(1), ok("x")]);
54
+ * // Result<readonly [number, string], never> — no `as const` needed
55
+ * if (isOk(r)) {
56
+ * const [n, s] = r.value; // typed per position
57
+ * }
58
+ * ```
59
+ */
60
+ export declare const combineTuple: <const R extends readonly unknown[]>(results: R, ..._guard: TupleGuard<R>) => CombineTuple<R>;
61
+ /**
62
+ * Accumulate independent validation failures. Returns `Ok<T[]>` only when
63
+ * every input is `Ok`. Without a combiner, failures are collected into a
64
+ * readonly array; with `combineErrors` they are folded into a single `E`.
65
+ *
66
+ * Unlike {@link combine}, this does **not** short-circuit on first failure —
67
+ * use for independent checks where you want to report all problems at once.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * const checks: Result<string, string[]>[] = [ok("Ada"), err(["age required"])];
72
+ *
73
+ * validateAll(checks);
74
+ * // Result<string[], readonly string[][]>
75
+ *
76
+ * validateAll(checks, (left, right) => [...left, ...right]);
77
+ * // Result<string[], string[]>
78
+ * ```
79
+ */
80
+ export declare function validateAll<T, E>(results: readonly Result<T, E>[]): Result<T[], readonly E[]>;
81
+ export declare function validateAll<T, E>(results: readonly Result<T, E>[], combineErrors: (left: E, right: E) => E): Result<T[], E>;
82
+ /**
83
+ * Tuple-preserving variant of {@link validateAll}. Heterogeneous input tuple
84
+ * → preserved `Ok` tuple shape. Without a combiner, the error union is
85
+ * collected into a readonly array; with `combineErrors`, all inputs must
86
+ * share the error type `E` and failures fold into a single `E`.
87
+ *
88
+ * Like {@link combineTuple}, the element check lives in the return type, so
89
+ * inline literals keep their precise error types without `as const`.
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * const name: Result<string, string[]> = ok("Ada");
94
+ * const age: Result<number, string[]> = ok(36);
95
+ *
96
+ * validateTuple([name, age]);
97
+ * // Result<readonly [string, number], readonly string[][]>
98
+ *
99
+ * validateTuple([name, age], (l, r) => [...l, ...r]);
100
+ * // Result<readonly [string, number], string[]>
101
+ * ```
102
+ */
103
+ export declare function validateTuple<const R extends readonly unknown[]>(results: R, ..._guard: TupleGuard<R>): R[number] extends AnyResult ? Result<OkTuple<R>, readonly InferErr<R[number]>[]> : never;
104
+ export declare function validateTuple<const R extends readonly unknown[], E = InferErr<R[number]>>(results: R, combineErrors: (left: E, right: E) => E, ..._guard: TupleGuard<R>): R[number] extends AnyResult ? Result<OkTuple<R>, E> : never;
105
+ export {};
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @onrails/result — sync aggregation, one module, two axes:
3
+ *
4
+ * short-circuit (first `Err` wins) — {@link combine} / {@link combineTuple}
5
+ * accumulate expected failures — {@link validateAll} / {@link validateTuple}
6
+ *
7
+ * The accumulate pair collects every failure into a readonly array by
8
+ * default, or folds them with an explicit `combineErrors` when given one.
9
+ */
10
+ import type { InferErr, InferOk } from "./internal/infer.js";
11
+ import type { Result } from "./types.js";
12
+ /**
13
+ * Combines a homogeneous array of results into a single result holding an
14
+ * array of the `Ok` values, in input order. Short-circuits on the first `Err`
15
+ * (first failure wins). For heterogeneous tuples that preserve per-index
16
+ * types, use {@link combineTuple}.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * combine([ok(1), ok(2)]); // Ok([1, 2])
21
+ * combine([ok(1), err("e")]); // Err("e")
22
+ * ```
23
+ */
24
+ export declare const combine: <T, E>(results: readonly Result<T, E>[]) => Result<T[], E>;
25
+ type AnyResult = Result<unknown, unknown>;
26
+ /** Positionally preserved `Ok` payloads for a tuple of results. */
27
+ type OkTuple<R extends readonly unknown[]> = {
28
+ [K in keyof R]: InferOk<R[K]>;
29
+ };
30
+ /**
31
+ * The element check lives in the RETURN type, never in the parameter
32
+ * constraint. A `readonly Result<unknown, unknown>[]` constraint contextually
33
+ * types the arguments, which widens `ok(1)`'s defaulted `E = never` — and
34
+ * `err(e)`'s `T = never` — all the way to `unknown`. Holding the parameter at
35
+ * a bare `R` keeps both channels precise for inline literals, so call sites
36
+ * need neither `as const` nor hoisted intermediates.
37
+ */
38
+ type CombineTuple<R extends readonly unknown[]> = R[number] extends AnyResult ? Result<OkTuple<R>, InferErr<R[number]>> : never;
39
+ /**
40
+ * Restores the "every element is a Result" check the parameter constraint used
41
+ * to provide. Resolves to `[]` for a well-formed tuple and to a one-element
42
+ * tuple otherwise, so a bad call fails at the call site (with the message
43
+ * visible in signature help) instead of silently yielding `never`.
44
+ */
45
+ type TupleGuard<R extends readonly unknown[]> = R[number] extends AnyResult ? [] : [error: "expected an array of Result values"];
46
+ /**
47
+ * Heterogeneous tuple combine — like {@link combine} but preserves each
48
+ * branch's `Ok` type by position, so the result destructures type-safely.
49
+ * Short-circuits on the first `Err` in input order (neverthrow-style).
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * const r = combineTuple([ok(1), ok("x")]);
54
+ * // Result<readonly [number, string], never> — no `as const` needed
55
+ * if (isOk(r)) {
56
+ * const [n, s] = r.value; // typed per position
57
+ * }
58
+ * ```
59
+ */
60
+ export declare const combineTuple: <const R extends readonly unknown[]>(results: R, ..._guard: TupleGuard<R>) => CombineTuple<R>;
61
+ /**
62
+ * Accumulate independent validation failures. Returns `Ok<T[]>` only when
63
+ * every input is `Ok`. Without a combiner, failures are collected into a
64
+ * readonly array; with `combineErrors` they are folded into a single `E`.
65
+ *
66
+ * Unlike {@link combine}, this does **not** short-circuit on first failure —
67
+ * use for independent checks where you want to report all problems at once.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * const checks: Result<string, string[]>[] = [ok("Ada"), err(["age required"])];
72
+ *
73
+ * validateAll(checks);
74
+ * // Result<string[], readonly string[][]>
75
+ *
76
+ * validateAll(checks, (left, right) => [...left, ...right]);
77
+ * // Result<string[], string[]>
78
+ * ```
79
+ */
80
+ export declare function validateAll<T, E>(results: readonly Result<T, E>[]): Result<T[], readonly E[]>;
81
+ export declare function validateAll<T, E>(results: readonly Result<T, E>[], combineErrors: (left: E, right: E) => E): Result<T[], E>;
82
+ /**
83
+ * Tuple-preserving variant of {@link validateAll}. Heterogeneous input tuple
84
+ * → preserved `Ok` tuple shape. Without a combiner, the error union is
85
+ * collected into a readonly array; with `combineErrors`, all inputs must
86
+ * share the error type `E` and failures fold into a single `E`.
87
+ *
88
+ * Like {@link combineTuple}, the element check lives in the return type, so
89
+ * inline literals keep their precise error types without `as const`.
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * const name: Result<string, string[]> = ok("Ada");
94
+ * const age: Result<number, string[]> = ok(36);
95
+ *
96
+ * validateTuple([name, age]);
97
+ * // Result<readonly [string, number], readonly string[][]>
98
+ *
99
+ * validateTuple([name, age], (l, r) => [...l, ...r]);
100
+ * // Result<readonly [string, number], string[]>
101
+ * ```
102
+ */
103
+ export declare function validateTuple<const R extends readonly unknown[]>(results: R, ..._guard: TupleGuard<R>): R[number] extends AnyResult ? Result<OkTuple<R>, readonly InferErr<R[number]>[]> : never;
104
+ export declare function validateTuple<const R extends readonly unknown[], E = InferErr<R[number]>>(results: R, combineErrors: (left: E, right: E) => E, ..._guard: TupleGuard<R>): R[number] extends AnyResult ? Result<OkTuple<R>, E> : never;
105
+ export {};
@@ -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,38 +18,34 @@ 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) ? ok(fn(result.value)) : err(result.error)
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) ? err(fn(result.error)) : ok(result.value)
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) : err(result.error)
37
+ (result, fn) => isOk(result) ? fn(result.value) : mkErr(result.error)
32
38
  );
33
39
  var unwrapOr = dual(
34
40
  2,
35
41
  (result, defaultValue) => isOk(result) ? result.value : defaultValue
36
42
  );
37
- function trySync(fn, onThrow) {
43
+ function fromThrowable(fn, onThrow) {
38
44
  return (...args) => {
39
45
  try {
40
- return ok(fn(...args));
46
+ return mkOk(fn(...args));
41
47
  } catch (error) {
42
- return err(onThrow(error));
48
+ return mkErr(onThrow(error));
43
49
  }
44
50
  };
45
51
  }
@@ -59,11 +65,11 @@ var sequenceSettled = (settled) => {
59
65
  const values = [];
60
66
  for (const result of settled) {
61
67
  if (isErr(result)) {
62
- return err(result.error);
68
+ return mkErr(result.error);
63
69
  }
64
70
  values.push(result.value);
65
71
  }
66
- return ok(values);
72
+ return mkOk(values);
67
73
  };
68
74
  var ResultAsync = class _ResultAsync {
69
75
  constructor(run) {
@@ -100,9 +106,9 @@ var ResultAsync = class _ResultAsync {
100
106
  static fromPromise(promise, onReject) {
101
107
  return new _ResultAsync(async () => {
102
108
  try {
103
- return ok(await promise);
109
+ return mkOk(await promise);
104
110
  } catch (error) {
105
- return err(onReject(error));
111
+ return mkErr(onReject(error));
106
112
  }
107
113
  });
108
114
  }
@@ -116,7 +122,7 @@ var ResultAsync = class _ResultAsync {
116
122
  * ```
117
123
  */
118
124
  static fromSafePromise(promise) {
119
- return new _ResultAsync(async () => ok(await promise));
125
+ return new _ResultAsync(async () => mkOk(await promise));
120
126
  }
121
127
  /**
122
128
  * Defers work until {@link resolve}. Unlike {@link fromPromise}, the factory
@@ -134,21 +140,13 @@ var ResultAsync = class _ResultAsync {
134
140
  return new _ResultAsync(fn);
135
141
  }
136
142
  static ok(value) {
137
- return new _ResultAsync(async () => ok(value));
143
+ return new _ResultAsync(async () => mkOk(value));
138
144
  }
139
145
  static of(value) {
140
146
  return _ResultAsync.ok(value);
141
147
  }
142
- /**
143
- * Lifts an error into an `Err` async result.
144
- *
145
- * @example
146
- * ```ts
147
- * const r = ResultAsync.err({ kind: "not_found" as const });
148
- * ```
149
- */
150
148
  static err(error) {
151
- return new _ResultAsync(async () => err(error));
149
+ return new _ResultAsync(async () => mkErr(error));
152
150
  }
153
151
  /**
154
152
  * Lifts an existing `Promise<Result<T, E>>` (e.g. from interop code) into a
@@ -166,7 +164,7 @@ var ResultAsync = class _ResultAsync {
166
164
  try {
167
165
  return await promise;
168
166
  } catch (error) {
169
- return err(mapDefect(error));
167
+ return mkErr(mapDefect(error));
170
168
  }
171
169
  });
172
170
  }
@@ -188,11 +186,11 @@ var ResultAsync = class _ResultAsync {
188
186
  for (const ra of results) {
189
187
  const result = await ra.resolve();
190
188
  if (isErr(result)) {
191
- return err(result.error);
189
+ return mkErr(result.error);
192
190
  }
193
191
  values.push(result.value);
194
192
  }
195
- return ok(values);
193
+ return mkOk(values);
196
194
  });
197
195
  }
198
196
  /**
@@ -204,7 +202,7 @@ var ResultAsync = class _ResultAsync {
204
202
  *
205
203
  * @example
206
204
  * ```ts
207
- * const combined = ResultAsync.combineTuple([loadCfg(), loadCatalog()] as const);
205
+ * const combined = ResultAsync.combineTuple([loadCfg(), loadCatalog()]);
208
206
  * // ResultAsync<readonly [Cfg, Catalog], CfgError | CatalogError>
209
207
  * const r = await combined;
210
208
  * if (isOk(r)) {
@@ -212,7 +210,7 @@ var ResultAsync = class _ResultAsync {
212
210
  * }
213
211
  * ```
214
212
  */
215
- static combineTuple(results) {
213
+ static combineTuple(results, ..._guard) {
216
214
  return _ResultAsync.combine(
217
215
  results
218
216
  );
@@ -227,12 +225,14 @@ var ResultAsync = class _ResultAsync {
227
225
  * const combined = ResultAsync.combineTupleParallel([
228
226
  * loadProfile(id),
229
227
  * loadMetrics(id),
230
- * ] as const);
228
+ * ]);
231
229
  * ```
232
230
  */
233
- static combineTupleParallel(results) {
231
+ static combineTupleParallel(results, ..._guard) {
234
232
  return new _ResultAsync(
235
- async () => sequenceSettled(await Promise.all(results.map((ra) => ra.resolve())))
233
+ async () => sequenceSettled(
234
+ await Promise.all(results.map((ra) => ra.resolve()))
235
+ )
236
236
  );
237
237
  }
238
238
  /**
@@ -258,6 +258,18 @@ var ResultAsync = class _ResultAsync {
258
258
  mapErr(fn) {
259
259
  return new _ResultAsync(async () => mapErr(await this.resolve(), fn));
260
260
  }
261
+ /**
262
+ * Transforms both tracks in one step — the async mirror of the sync
263
+ * `bimap`. Exactly one of `onOk` / `onErr` runs.
264
+ *
265
+ * @example
266
+ * ```ts
267
+ * load(id).bimap(toDto, (e): AppError => ({ kind: "load", cause: e }));
268
+ * ```
269
+ */
270
+ bimap(onOk, onErr) {
271
+ return new _ResultAsync(async () => bimap(await this.resolve(), onOk, onErr));
272
+ }
261
273
  /**
262
274
  * Canonical bind — chains a step that itself returns a `ResultAsync` or sync
263
275
  * `Result`, short-circuiting on `Err`. Error types accumulate (`E | F`).
@@ -426,12 +438,12 @@ var ResultAsync = class _ResultAsync {
426
438
  var combine = (results) => {
427
439
  const values = [];
428
440
  for (const result of results) {
429
- if (isErr(result)) return err(result.error);
441
+ if (isErr(result)) return mkErr(result.error);
430
442
  values.push(result.value);
431
443
  }
432
- return ok(values);
444
+ return mkOk(values);
433
445
  };
434
- var combineTuple = (results) => (
446
+ var combineTuple = (results, ..._guard) => (
435
447
  // Runtime identical to combine; the cast restores per-index tuple types.
436
448
  combine(results)
437
449
  );
@@ -443,7 +455,7 @@ var CompatResult = class _CompatResult {
443
455
  }
444
456
  inner;
445
457
  static fromThrowable(fn, onThrow) {
446
- const wrapped = trySync(fn, onThrow);
458
+ const wrapped = fromThrowable(fn, onThrow);
447
459
  return (...args) => new _CompatResult(wrapped(...args));
448
460
  }
449
461
  static combine(results) {
@@ -498,8 +510,8 @@ var CompatResult = class _CompatResult {
498
510
  }
499
511
  };
500
512
  var Result = CompatResult;
501
- var ok2 = (value) => new CompatResult(ok(value));
502
- var err2 = (error) => new CompatResult(err(error));
513
+ var ok = (value) => new CompatResult(mkOk(value));
514
+ var err = (error) => new CompatResult(mkErr(error));
503
515
  var CompatResultAsync = class _CompatResultAsync {
504
516
  constructor(inner) {
505
517
  this.inner = inner;
@@ -626,11 +638,11 @@ exports.CompatResult = CompatResult;
626
638
  exports.CompatResultAsync = CompatResultAsync;
627
639
  exports.Result = Result;
628
640
  exports.ResultAsync = CompatResultAsync;
629
- exports.err = err2;
641
+ exports.err = err;
630
642
  exports.errAsync = errAsync;
631
643
  exports.fromPromise = fromPromise;
632
644
  exports.fromSafePromise = fromSafePromise;
633
- exports.ok = ok2;
645
+ exports.ok = ok;
634
646
  exports.okAsync = okAsync;
635
647
  //# sourceMappingURL=neverthrow.cjs.map
636
648
  //# sourceMappingURL=neverthrow.cjs.map