unthrown 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +176 -24
- package/dist/index.d.cts +167 -22
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +167 -22
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +174 -25
- package/dist/index.mjs.map +1 -1
- package/docs/index.md +299 -95
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -39,6 +39,23 @@ type ResultMethods<T, E> = {
|
|
|
39
39
|
* @param f - the side effect (its return value is ignored).
|
|
40
40
|
*/
|
|
41
41
|
tap(f: (value: T) => void): Result$1<T, E>;
|
|
42
|
+
/**
|
|
43
|
+
* Run a **failable** side effect on the success value, keeping the original
|
|
44
|
+
* value but threading the effect's error.
|
|
45
|
+
*
|
|
46
|
+
* @remarks
|
|
47
|
+
* This is to {@link ResultMethods.tap | tap} what
|
|
48
|
+
* {@link ResultMethods.flatMap | flatMap} is to {@link ResultMethods.map | map}:
|
|
49
|
+
* `f` returns a `Result`, but its **success value is discarded** — on success
|
|
50
|
+
* the original value flows through (`Result<T, E | E2>`), while an `Err` (or
|
|
51
|
+
* `Defect`) from `f` short-circuits. Runs only on `Ok`; `Err` and `Defect` pass
|
|
52
|
+
* through. If `f` throws, the throw becomes a `Defect`. Use it for a validation
|
|
53
|
+
* or write whose _result_ matters but whose _value_ you don't need.
|
|
54
|
+
*
|
|
55
|
+
* @typeParam E2 - the error type the effect may introduce.
|
|
56
|
+
* @param f - the failable side effect; its `Ok` value is ignored.
|
|
57
|
+
*/
|
|
58
|
+
flatTap<E2>(f: (value: T) => Result$1<unknown, E2>): Result$1<T, E | E2>;
|
|
42
59
|
/**
|
|
43
60
|
* Replace the success value with a constant `value`.
|
|
44
61
|
*
|
|
@@ -172,10 +189,10 @@ type ResultMethods<T, E> = {
|
|
|
172
189
|
*
|
|
173
190
|
* @throws Re-throws on a `Defect`.
|
|
174
191
|
*/
|
|
175
|
-
getOrUndefined(): T | undefined; /** Whether this result is `Ok`. */
|
|
176
|
-
isOk():
|
|
177
|
-
isErr():
|
|
178
|
-
isDefect():
|
|
192
|
+
getOrUndefined(): T | undefined; /** Whether this result is `Ok` — narrows `this` to its {@link OkView} on `true`. */
|
|
193
|
+
isOk(): this is OkView<T, E>; /** Whether this result is `Err` — narrows `this` to its {@link ErrView} on `true`. */
|
|
194
|
+
isErr(): this is ErrView<E, T>; /** Whether this result is a `Defect` — narrows `this` to its {@link DefectView} on `true`. */
|
|
195
|
+
isDefect(): this is DefectView<T, E>; /** Lift this synchronous `Result` into an {@link AsyncResult}. */
|
|
179
196
|
toAsync(): AsyncResult<T, E>;
|
|
180
197
|
};
|
|
181
198
|
/** The `Ok` variant of a {@link Result}: a success carrying a `value`. */
|
|
@@ -258,7 +275,8 @@ type Awaitable<T> = {
|
|
|
258
275
|
* {@link fromPromise} forces. To do further async work, re-enter through a
|
|
259
276
|
* qualified boundary and compose it: `ar.flatMap((v) => fromPromise(work(v),
|
|
260
277
|
* qualify))`. The eliminators (`unwrap`, …) return promises; the binds
|
|
261
|
-
* (`flatMap`, `orElse`, `recoverDefect`) additionally accept an
|
|
278
|
+
* (`flatMap`, `flatTap`, `orElse`, `recoverDefect`) additionally accept an
|
|
279
|
+
* `AsyncResult`.
|
|
262
280
|
*
|
|
263
281
|
* To pattern-match an `AsyncResult`, `await` it first: `match(await ar)`.
|
|
264
282
|
*
|
|
@@ -272,7 +290,13 @@ type AsyncResult<T, E> = Awaitable<Result$1<T, E>> & {
|
|
|
272
290
|
* (never a raw `Promise`); a throw becomes a `Defect`.
|
|
273
291
|
*/
|
|
274
292
|
flatMap<U, E2>(f: (value: T) => Result$1<U, E2> | AsyncResult<U, E2>): AsyncResult<U, E | E2>; /** Asynchronous `tap`. `f` is synchronous; a throw becomes a `Defect`. */
|
|
275
|
-
tap(f: (value: T) => void): AsyncResult<T, E>;
|
|
293
|
+
tap(f: (value: T) => void): AsyncResult<T, E>;
|
|
294
|
+
/**
|
|
295
|
+
* Asynchronous `flatTap` — a failable tap that keeps the original value. `f`
|
|
296
|
+
* may return a `Result` **or** an `AsyncResult`; its `Ok` value is discarded,
|
|
297
|
+
* an `Err`/`Defect` short-circuits, and a throw becomes a `Defect`.
|
|
298
|
+
*/
|
|
299
|
+
flatTap<E2>(f: (value: T) => Result$1<unknown, E2> | AsyncResult<unknown, E2>): AsyncResult<T, E | E2>; /** Asynchronous `as`. */
|
|
276
300
|
as<U>(value: U): AsyncResult<U, E>; /** Asynchronous `mapErr`. `f` is synchronous; a throw becomes a `Defect`. */
|
|
277
301
|
mapErr<E2>(f: (error: E) => E2): AsyncResult<T, E2>; /** Asynchronous `orElse`. `f` may return a `Result` or an `AsyncResult`. */
|
|
278
302
|
orElse<U, E2>(f: (error: E) => Result$1<U, E2> | AsyncResult<U, E2>): AsyncResult<T | U, E2>; /** Asynchronous `recover`. `f` is synchronous; a throw becomes a `Defect`. */
|
|
@@ -310,6 +334,18 @@ type ErrOf<R> = R extends {
|
|
|
310
334
|
readonly tag: "Err";
|
|
311
335
|
readonly error: infer E;
|
|
312
336
|
} ? E : never;
|
|
337
|
+
/**
|
|
338
|
+
* Extract the success type `T` from an {@link AsyncResult}.
|
|
339
|
+
*
|
|
340
|
+
* @typeParam R - the `AsyncResult` type to inspect.
|
|
341
|
+
*/
|
|
342
|
+
type AsyncOkOf<R> = R extends AsyncResult<infer T, unknown> ? T : never;
|
|
343
|
+
/**
|
|
344
|
+
* Extract the error type `E` from an {@link AsyncResult}.
|
|
345
|
+
*
|
|
346
|
+
* @typeParam R - the `AsyncResult` type to inspect.
|
|
347
|
+
*/
|
|
348
|
+
type AsyncErrOf<R> = R extends AsyncResult<unknown, infer E> ? E : never;
|
|
313
349
|
//#endregion
|
|
314
350
|
//#region src/constructors.d.ts
|
|
315
351
|
/**
|
|
@@ -449,9 +485,16 @@ declare function fromNullable<T, E>(value: T | null | undefined, onAbsent: () =>
|
|
|
449
485
|
* {@link Defect} (via {@link defect}) — there is no path that leaves `unknown`
|
|
450
486
|
* in `E`. A throw inside `qualify` itself is treated as a `Defect`.
|
|
451
487
|
*
|
|
488
|
+
* The modeled error type is `Exclude<R, Defect>` — the `Defect` arm of
|
|
489
|
+
* `qualify`'s return is **subtracted** from `E`, never inferred into it. So a
|
|
490
|
+
* `qualify` that returns *only* `defect(cause)` yields `E = never` (a defect is
|
|
491
|
+
* out-of-band and must not pollute the error channel); reach for
|
|
492
|
+
* {@link fromSafePromise} when every failure is a defect.
|
|
493
|
+
*
|
|
452
494
|
* @typeParam A - the wrapped function's argument tuple.
|
|
453
495
|
* @typeParam T - the wrapped function's return type.
|
|
454
|
-
* @typeParam
|
|
496
|
+
* @typeParam R - `qualify`'s return type; the modeled error `E` is
|
|
497
|
+
* `Exclude<R, Defect>` (its `Defect` arm, if any, is subtracted).
|
|
455
498
|
* @param fn - the throwing function to wrap.
|
|
456
499
|
* @param qualify - triages a thrown cause into `E` or a `Defect`.
|
|
457
500
|
* @returns a function with the same arguments returning `Result<T, E>`.
|
|
@@ -463,7 +506,7 @@ declare function fromNullable<T, E>(value: T | null | undefined, onAbsent: () =>
|
|
|
463
506
|
* parse("{}").unwrap();
|
|
464
507
|
* ```
|
|
465
508
|
*/
|
|
466
|
-
declare function fromThrowable<A extends unknown[], T,
|
|
509
|
+
declare function fromThrowable<A extends unknown[], T, R>(fn: (...args: A) => T, qualify: (cause: unknown) => R): (...args: A) => Result$1<T, Exclude<R, Defect>>;
|
|
467
510
|
/**
|
|
468
511
|
* Wrap a `Promise` (or a thunk producing one) as an {@link AsyncResult}, forcing
|
|
469
512
|
* every rejection to be triaged.
|
|
@@ -474,8 +517,14 @@ declare function fromThrowable<A extends unknown[], T, E>(fn: (...args: A) => T,
|
|
|
474
517
|
* `await`-ing it always yields a `Result`. A throw inside `qualify` is itself a
|
|
475
518
|
* `Defect`.
|
|
476
519
|
*
|
|
520
|
+
* The modeled error type is `Exclude<R, Defect>` — the `Defect` arm of
|
|
521
|
+
* `qualify`'s return is **subtracted** from `E`, never inferred into it. So a
|
|
522
|
+
* `qualify` that returns *only* `defect(cause)` yields `E = never`; when every
|
|
523
|
+
* rejection is a defect, prefer {@link fromSafePromise}.
|
|
524
|
+
*
|
|
477
525
|
* @typeParam T - the resolved value type.
|
|
478
|
-
* @typeParam
|
|
526
|
+
* @typeParam R - `qualify`'s return type; the modeled error `E` is
|
|
527
|
+
* `Exclude<R, Defect>` (its `Defect` arm, if any, is subtracted).
|
|
479
528
|
* @param promise - the promise, or a thunk returning one.
|
|
480
529
|
* @param qualify - triages a rejection cause into `E` or a `Defect`.
|
|
481
530
|
*
|
|
@@ -487,7 +536,7 @@ declare function fromThrowable<A extends unknown[], T, E>(fn: (...args: A) => T,
|
|
|
487
536
|
* );
|
|
488
537
|
* ```
|
|
489
538
|
*/
|
|
490
|
-
declare function fromPromise<T,
|
|
539
|
+
declare function fromPromise<T, R>(promise: Promise<T> | (() => Promise<T>), qualify: (cause: unknown) => R): AsyncResult<T, Exclude<R, Defect>>;
|
|
491
540
|
/**
|
|
492
541
|
* Wrap a `Promise` asserted **not** to fail in any modeled way: any rejection
|
|
493
542
|
* becomes a `Defect`.
|
|
@@ -502,25 +551,96 @@ declare function fromPromise<T, E>(promise: Promise<T> | (() => Promise<T>), qua
|
|
|
502
551
|
*/
|
|
503
552
|
declare function fromSafePromise<T>(promise: Promise<T> | (() => Promise<T>)): AsyncResult<T, never>;
|
|
504
553
|
/**
|
|
505
|
-
*
|
|
554
|
+
* The success channel of {@link all} / {@link allAsync}: a **positional tuple**
|
|
555
|
+
* for a fixed-length input (including the empty tuple), or a homogeneous
|
|
556
|
+
* **array** for a dynamic one.
|
|
557
|
+
*
|
|
558
|
+
* @remarks
|
|
559
|
+
* The split keys off the input's `length`: a fixed tuple has a literal length
|
|
560
|
+
* (`number extends Rs["length"]` is false → keep the positional `Ts`), while a
|
|
561
|
+
* general array has `length: number` (→ collapse to `Ts[number][]`). Checking
|
|
562
|
+
* length rather than `Rs extends [unknown, ...unknown[]]` keeps `all([])` typed
|
|
563
|
+
* as `Result<[], …>` instead of `Result<never[], …>`.
|
|
564
|
+
*
|
|
565
|
+
* @typeParam Rs - the tuple/array of input `Result` types.
|
|
566
|
+
* @typeParam Ts - per-element extracted success types (`OkOf` for `all`,
|
|
567
|
+
* `AsyncOkOf` for `allAsync`).
|
|
568
|
+
* @internal
|
|
569
|
+
*/
|
|
570
|
+
type AllOk<Rs extends readonly unknown[], Ts extends readonly unknown[]> = number extends Rs["length"] ? Ts[number][] : Ts;
|
|
571
|
+
/** A record of `Result`s — the input to {@link allFromDict}. */
|
|
572
|
+
type ResultRecord = Record<string, Result$1<unknown, unknown>>;
|
|
573
|
+
/** A record of `AsyncResult`s — the input to {@link allFromDictAsync}. */
|
|
574
|
+
type AsyncResultRecord = Record<string, AsyncResult<unknown, unknown>>;
|
|
575
|
+
/**
|
|
576
|
+
* Collect a tuple/array of {@link Result}s into a single `Result` of all their
|
|
506
577
|
* success values.
|
|
507
578
|
*
|
|
508
579
|
* @remarks
|
|
509
580
|
* Short-circuits on the **first** `Err` (later entries are not inspected for
|
|
510
581
|
* their error); any `Defect` present **dominates**, winning even over an earlier
|
|
511
|
-
* `Err`.
|
|
512
|
-
* `Result<[number, string],
|
|
513
|
-
*
|
|
514
|
-
* @
|
|
515
|
-
* @param results - the results to combine.
|
|
582
|
+
* `Err`. A **fixed tuple** keeps its positional types — `all([ok(1), ok("a")])`
|
|
583
|
+
* is `Result<[number, string], …>` — while a **dynamic array** `Result<T, E>[]`
|
|
584
|
+
* collapses to `Result<T[], E>` with no cast. For a **record** keyed by name,
|
|
585
|
+
* use {@link allFromDict}.
|
|
516
586
|
*
|
|
517
587
|
* @example
|
|
518
588
|
* ```ts
|
|
519
589
|
* import { all, ok } from "unthrown";
|
|
520
|
-
* all([ok(1), ok("a"), ok(true)]).unwrap(); // [1, "a", true]
|
|
590
|
+
* all([ok(1), ok("a"), ok(true)]).unwrap(); // [1, "a", true] (typed [number, string, boolean])
|
|
591
|
+
* all([ok(1), ok(2)] as Result<number, never>[]).unwrap(); // number[]
|
|
592
|
+
* ```
|
|
593
|
+
*/
|
|
594
|
+
declare function all<Rs extends readonly Result$1<unknown, unknown>[]>(results: readonly [...Rs]): Result$1<AllOk<Rs, { [K in keyof Rs]: OkOf<Rs[K]> }>, ErrOf<Rs[number]>>;
|
|
595
|
+
/**
|
|
596
|
+
* Collect a **record** of {@link Result}s into a single `Result` of a record of
|
|
597
|
+
* their success values — `allFromDict({ a: Result<A, E>, b: Result<B, E> })` is
|
|
598
|
+
* `Result<{ a: A; b: B }, E>`. The named counterpart of {@link all}, for
|
|
599
|
+
* parallel work you'd rather not tuple.
|
|
600
|
+
*
|
|
601
|
+
* @remarks
|
|
602
|
+
* Same folding rules as {@link all}: first `Err` short-circuits, any `Defect`
|
|
603
|
+
* dominates. This is **not** error accumulation.
|
|
604
|
+
*
|
|
605
|
+
* @example
|
|
606
|
+
* ```ts
|
|
607
|
+
* import { allFromDict, ok } from "unthrown";
|
|
608
|
+
* allFromDict({ id: ok(1), name: ok("ada") }).unwrap(); // { id: 1, name: "ada" }
|
|
609
|
+
* ```
|
|
610
|
+
*/
|
|
611
|
+
declare function allFromDict<R extends ResultRecord>(results: R): Result$1<{ [K in keyof R]: OkOf<R[K]> }, ErrOf<R[keyof R]>>;
|
|
612
|
+
/**
|
|
613
|
+
* The asynchronous counterpart of {@link all}: combine a tuple/array of
|
|
614
|
+
* {@link AsyncResult}s into one `AsyncResult` of all their success values.
|
|
615
|
+
*
|
|
616
|
+
* @remarks
|
|
617
|
+
* The inputs are resolved **concurrently** (order preserved); the resolved
|
|
618
|
+
* `Result`s are then folded with the same rules as {@link all} — first `Err`
|
|
619
|
+
* short-circuits, any `Defect` dominates. As ever, the returned `AsyncResult`'s
|
|
620
|
+
* internal promise never rejects. For a **record**, use {@link allFromDictAsync}.
|
|
621
|
+
*
|
|
622
|
+
* @example
|
|
623
|
+
* ```ts
|
|
624
|
+
* import { allAsync, fromSafePromise } from "unthrown";
|
|
625
|
+
* await allAsync([fromSafePromise(a()), fromSafePromise(b())]);
|
|
521
626
|
* ```
|
|
522
627
|
*/
|
|
523
|
-
declare function
|
|
628
|
+
declare function allAsync<Rs extends readonly AsyncResult<unknown, unknown>[]>(results: readonly [...Rs]): AsyncResult<AllOk<Rs, { [K in keyof Rs]: AsyncOkOf<Rs[K]> }>, AsyncErrOf<Rs[number]>>;
|
|
629
|
+
/**
|
|
630
|
+
* The asynchronous counterpart of {@link allFromDict}: combine a record of
|
|
631
|
+
* {@link AsyncResult}s into one `AsyncResult` of a record of their values.
|
|
632
|
+
*
|
|
633
|
+
* @remarks
|
|
634
|
+
* Resolved concurrently (order preserved), folded with the {@link all} rules,
|
|
635
|
+
* and the internal promise never rejects.
|
|
636
|
+
*
|
|
637
|
+
* @example
|
|
638
|
+
* ```ts
|
|
639
|
+
* import { allFromDictAsync, fromSafePromise } from "unthrown";
|
|
640
|
+
* await allFromDictAsync({ a: fromSafePromise(a()), b: fromSafePromise(b()) });
|
|
641
|
+
* ```
|
|
642
|
+
*/
|
|
643
|
+
declare function allFromDictAsync<R extends AsyncResultRecord>(results: R): AsyncResult<{ [K in keyof R]: AsyncOkOf<R[K]> }, AsyncErrOf<R[keyof R]>>;
|
|
524
644
|
//#endregion
|
|
525
645
|
//#region src/facade.d.ts
|
|
526
646
|
/**
|
|
@@ -528,7 +648,9 @@ declare function all<Rs extends readonly Result$1<unknown, unknown>[]>(results:
|
|
|
528
648
|
* discoverable namespace: {@link Result.ok}, {@link Result.err},
|
|
529
649
|
* {@link Result.defect}, {@link Result.fromNullable}, {@link Result.fromThrowable},
|
|
530
650
|
* {@link Result.fromPromise}, {@link Result.fromSafePromise}, {@link Result.all},
|
|
531
|
-
* {@link Result.
|
|
651
|
+
* {@link Result.allAsync}, {@link Result.allFromDict},
|
|
652
|
+
* {@link Result.allFromDictAsync}, {@link Result.isOk}, {@link Result.isErr},
|
|
653
|
+
* {@link Result.isDefect}.
|
|
532
654
|
*
|
|
533
655
|
* @remarks
|
|
534
656
|
* Purely additive sugar — each member **is** the corresponding free function.
|
|
@@ -551,6 +673,9 @@ declare const Result: {
|
|
|
551
673
|
readonly fromPromise: typeof fromPromise;
|
|
552
674
|
readonly fromSafePromise: typeof fromSafePromise;
|
|
553
675
|
readonly all: typeof all;
|
|
676
|
+
readonly allAsync: typeof allAsync;
|
|
677
|
+
readonly allFromDict: typeof allFromDict;
|
|
678
|
+
readonly allFromDictAsync: typeof allFromDictAsync;
|
|
554
679
|
readonly isOk: typeof isOk;
|
|
555
680
|
readonly isErr: typeof isErr;
|
|
556
681
|
readonly isDefect: typeof isDefect;
|
|
@@ -592,8 +717,26 @@ type TaggedErrorConstructor<Tag extends string> = {
|
|
|
592
717
|
* field in the payload is forwarded to `Error`. The `_tag` always reflects
|
|
593
718
|
* `tag` and cannot be overridden by the payload.
|
|
594
719
|
*
|
|
720
|
+
* `_tag` is the discriminant used by {@link matchTags}; `Error.name` is the
|
|
721
|
+
* human-facing label in stack traces and logs. By default they coincide, but
|
|
722
|
+
* they can be **decoupled** with `options.name` — so a tag can be namespaced for
|
|
723
|
+
* collision-safety (`"@my-lib/RetryableError"`) without that slash-prefixed
|
|
724
|
+
* string leaking into `Error.name`:
|
|
725
|
+
*
|
|
726
|
+
* ```ts
|
|
727
|
+
* class RetryableError extends TaggedError("@my-lib/RetryableError", {
|
|
728
|
+
* name: "RetryableError",
|
|
729
|
+
* })<{ message: string }> {}
|
|
730
|
+
*
|
|
731
|
+
* const e = new RetryableError({ message: "boom" });
|
|
732
|
+
* e._tag; // "@my-lib/RetryableError" — namespaced discriminant
|
|
733
|
+
* e.name; // "RetryableError" — clean display name
|
|
734
|
+
* ```
|
|
735
|
+
*
|
|
595
736
|
* @typeParam Tag - the string literal discriminant.
|
|
596
|
-
* @param tag - the discriminant value
|
|
737
|
+
* @param tag - the discriminant value; also the default error `name`.
|
|
738
|
+
* @param options - optional overrides. `options.name` sets `Error.name`
|
|
739
|
+
* independently of `tag` (defaults to `tag`).
|
|
597
740
|
*
|
|
598
741
|
* @example
|
|
599
742
|
* ```ts
|
|
@@ -604,7 +747,9 @@ type TaggedErrorConstructor<Tag extends string> = {
|
|
|
604
747
|
* new HttpError({ status: 500 }).status; // 500
|
|
605
748
|
* ```
|
|
606
749
|
*/
|
|
607
|
-
declare function TaggedError<Tag extends string>(tag: Tag
|
|
750
|
+
declare function TaggedError<Tag extends string>(tag: Tag, options?: {
|
|
751
|
+
readonly name?: string;
|
|
752
|
+
}): TaggedErrorConstructor<Tag>;
|
|
608
753
|
/**
|
|
609
754
|
* The handler object {@link matchTags} requires: a branch per error tag, plus
|
|
610
755
|
* `Ok` and `Defect`. Miss a tag and it will not compile — the exhaustiveness is
|
|
@@ -659,5 +804,5 @@ declare function matchTags<T, E extends {
|
|
|
659
804
|
_tag: string;
|
|
660
805
|
}, R>(result: AsyncResult<T, E>, handlers: TagHandlers<T, E, R>): Promise<R>;
|
|
661
806
|
//#endregion
|
|
662
|
-
export { type AsyncResult, type Awaitable, type Defect, type DefectView, type ErrOf, type ErrView, type OkOf, type OkView, Result, type TagHandlers, TaggedError, type TaggedErrorConstructor, type TaggedErrorInstance, UnwrapError, all, defect, err, fromNullable, fromPromise, fromSafePromise, fromThrowable, isDefect, isErr, isOk, matchTags, ok };
|
|
807
|
+
export { type AsyncErrOf, type AsyncOkOf, type AsyncResult, type Awaitable, type Defect, type DefectView, type ErrOf, type ErrView, type OkOf, type OkView, Result, type TagHandlers, TaggedError, type TaggedErrorConstructor, type TaggedErrorInstance, UnwrapError, all, allAsync, allFromDict, allFromDictAsync, defect, err, fromNullable, fromPromise, fromSafePromise, fromThrowable, isDefect, isErr, isOk, matchTags, ok };
|
|
663
808
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/constructors.ts","../src/core.ts","../src/defect.ts","../src/interop.ts","../src/facade.ts","../src/tagged.ts"],"mappings":";;AAWA;;;;;;;;KAAY,aAAA;EAqB6B;;;;;;;;;EAXvC,GAAA,IAAO,CAAA,GAAI,KAAA,EAAO,CAAA,KAAM,CAAA,GAAI,QAAA,CAAO,CAAA,EAAG,CAAA;EAoBV;;;;;;;;;;EAT5B,OAAA,QAAe,CAAA,GAAI,KAAA,EAAO,CAAA,KAAM,QAAA,CAAO,CAAA,EAAG,EAAA,IAAM,QAAA,CAAO,CAAA,EAAG,CAAA,GAAI,EAAA;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/constructors.ts","../src/core.ts","../src/defect.ts","../src/interop.ts","../src/facade.ts","../src/tagged.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -56,6 +56,15 @@ var Res = class {
|
|
|
56
56
|
return defectRes(cause);
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
+
flatTap(f) {
|
|
60
|
+
if (this.tag !== "Ok") return this;
|
|
61
|
+
try {
|
|
62
|
+
const r = f(this.value);
|
|
63
|
+
return r.tag === "Ok" ? this : r;
|
|
64
|
+
} catch (cause) {
|
|
65
|
+
return defectRes(cause);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
59
68
|
as(value) {
|
|
60
69
|
if (this.tag !== "Ok") return this;
|
|
61
70
|
return okRes(value);
|
|
@@ -243,6 +252,17 @@ var AsyncRes = class AsyncRes {
|
|
|
243
252
|
}
|
|
244
253
|
}));
|
|
245
254
|
}
|
|
255
|
+
flatTap(f) {
|
|
256
|
+
return new AsyncRes(this.promise.then(async (r) => {
|
|
257
|
+
if (r.tag !== "Ok") return r;
|
|
258
|
+
try {
|
|
259
|
+
const inner = await f(r.value);
|
|
260
|
+
return inner.tag === "Ok" ? r : inner;
|
|
261
|
+
} catch (cause) {
|
|
262
|
+
return defectRes(cause);
|
|
263
|
+
}
|
|
264
|
+
}));
|
|
265
|
+
}
|
|
246
266
|
as(value) {
|
|
247
267
|
return new AsyncRes(this.promise.then((r) => r.tag === "Ok" ? okRes(value) : r));
|
|
248
268
|
}
|
|
@@ -465,9 +485,16 @@ function fromNullable(value, onAbsent) {
|
|
|
465
485
|
* {@link Defect} (via {@link defect}) — there is no path that leaves `unknown`
|
|
466
486
|
* in `E`. A throw inside `qualify` itself is treated as a `Defect`.
|
|
467
487
|
*
|
|
488
|
+
* The modeled error type is `Exclude<R, Defect>` — the `Defect` arm of
|
|
489
|
+
* `qualify`'s return is **subtracted** from `E`, never inferred into it. So a
|
|
490
|
+
* `qualify` that returns *only* `defect(cause)` yields `E = never` (a defect is
|
|
491
|
+
* out-of-band and must not pollute the error channel); reach for
|
|
492
|
+
* {@link fromSafePromise} when every failure is a defect.
|
|
493
|
+
*
|
|
468
494
|
* @typeParam A - the wrapped function's argument tuple.
|
|
469
495
|
* @typeParam T - the wrapped function's return type.
|
|
470
|
-
* @typeParam
|
|
496
|
+
* @typeParam R - `qualify`'s return type; the modeled error `E` is
|
|
497
|
+
* `Exclude<R, Defect>` (its `Defect` arm, if any, is subtracted).
|
|
471
498
|
* @param fn - the throwing function to wrap.
|
|
472
499
|
* @param qualify - triages a thrown cause into `E` or a `Defect`.
|
|
473
500
|
* @returns a function with the same arguments returning `Result<T, E>`.
|
|
@@ -480,11 +507,12 @@ function fromNullable(value, onAbsent) {
|
|
|
480
507
|
* ```
|
|
481
508
|
*/
|
|
482
509
|
function fromThrowable(fn, qualify) {
|
|
510
|
+
const triage = qualify;
|
|
483
511
|
return (...args) => {
|
|
484
512
|
try {
|
|
485
513
|
return ok(fn(...args));
|
|
486
514
|
} catch (cause) {
|
|
487
|
-
return qualifyToResult(cause,
|
|
515
|
+
return qualifyToResult(cause, triage);
|
|
488
516
|
}
|
|
489
517
|
};
|
|
490
518
|
}
|
|
@@ -498,8 +526,14 @@ function fromThrowable(fn, qualify) {
|
|
|
498
526
|
* `await`-ing it always yields a `Result`. A throw inside `qualify` is itself a
|
|
499
527
|
* `Defect`.
|
|
500
528
|
*
|
|
529
|
+
* The modeled error type is `Exclude<R, Defect>` — the `Defect` arm of
|
|
530
|
+
* `qualify`'s return is **subtracted** from `E`, never inferred into it. So a
|
|
531
|
+
* `qualify` that returns *only* `defect(cause)` yields `E = never`; when every
|
|
532
|
+
* rejection is a defect, prefer {@link fromSafePromise}.
|
|
533
|
+
*
|
|
501
534
|
* @typeParam T - the resolved value type.
|
|
502
|
-
* @typeParam
|
|
535
|
+
* @typeParam R - `qualify`'s return type; the modeled error `E` is
|
|
536
|
+
* `Exclude<R, Defect>` (its `Defect` arm, if any, is subtracted).
|
|
503
537
|
* @param promise - the promise, or a thunk returning one.
|
|
504
538
|
* @param qualify - triages a rejection cause into `E` or a `Defect`.
|
|
505
539
|
*
|
|
@@ -512,7 +546,8 @@ function fromThrowable(fn, qualify) {
|
|
|
512
546
|
* ```
|
|
513
547
|
*/
|
|
514
548
|
function fromPromise(promise, qualify) {
|
|
515
|
-
|
|
549
|
+
const triage = qualify;
|
|
550
|
+
return new AsyncRes((typeof promise === "function" ? Promise.resolve().then(promise) : promise).then((value) => okRes(value), (cause) => qualifyToResult(cause, triage)));
|
|
516
551
|
}
|
|
517
552
|
/**
|
|
518
553
|
* Wrap a `Promise` asserted **not** to fail in any modeled way: any rejection
|
|
@@ -538,34 +573,124 @@ function qualifyToResult(cause, qualify) {
|
|
|
538
573
|
}
|
|
539
574
|
}
|
|
540
575
|
/**
|
|
541
|
-
*
|
|
576
|
+
* Fold an array of settled `Result`s: first `Err` wins, any `Defect` dominates,
|
|
577
|
+
* else `Ok` of the values array.
|
|
578
|
+
*
|
|
579
|
+
* @internal
|
|
580
|
+
*/
|
|
581
|
+
function foldArray(results) {
|
|
582
|
+
let firstErr;
|
|
583
|
+
let firstDefect;
|
|
584
|
+
const values = [];
|
|
585
|
+
for (const r of results) if (r.tag === "Defect") firstDefect ??= r;
|
|
586
|
+
else if (r.tag === "Err") firstErr ??= r;
|
|
587
|
+
else values.push(r.value);
|
|
588
|
+
return firstDefect ?? firstErr ?? ok(values);
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Fold a record of settled `Result`s with the same rules, else `Ok` of the
|
|
592
|
+
* record of values. Keys are written with `Object.defineProperty` so a
|
|
593
|
+
* caller-supplied `"__proto__"` key cannot pollute the prototype.
|
|
594
|
+
*
|
|
595
|
+
* @internal
|
|
596
|
+
*/
|
|
597
|
+
function foldRecord(results) {
|
|
598
|
+
let firstErr;
|
|
599
|
+
let firstDefect;
|
|
600
|
+
const values = {};
|
|
601
|
+
for (const [key, r] of Object.entries(results)) if (r.tag === "Defect") firstDefect ??= r;
|
|
602
|
+
else if (r.tag === "Err") firstErr ??= r;
|
|
603
|
+
else Object.defineProperty(values, key, {
|
|
604
|
+
value: r.value,
|
|
605
|
+
enumerable: true,
|
|
606
|
+
writable: true,
|
|
607
|
+
configurable: true
|
|
608
|
+
});
|
|
609
|
+
return firstDefect ?? firstErr ?? ok(values);
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Collect a tuple/array of {@link Result}s into a single `Result` of all their
|
|
542
613
|
* success values.
|
|
543
614
|
*
|
|
544
615
|
* @remarks
|
|
545
616
|
* Short-circuits on the **first** `Err` (later entries are not inspected for
|
|
546
617
|
* their error); any `Defect` present **dominates**, winning even over an earlier
|
|
547
|
-
* `Err`.
|
|
548
|
-
* `Result<[number, string],
|
|
549
|
-
*
|
|
550
|
-
* @
|
|
551
|
-
* @param results - the results to combine.
|
|
618
|
+
* `Err`. A **fixed tuple** keeps its positional types — `all([ok(1), ok("a")])`
|
|
619
|
+
* is `Result<[number, string], …>` — while a **dynamic array** `Result<T, E>[]`
|
|
620
|
+
* collapses to `Result<T[], E>` with no cast. For a **record** keyed by name,
|
|
621
|
+
* use {@link allFromDict}.
|
|
552
622
|
*
|
|
553
623
|
* @example
|
|
554
624
|
* ```ts
|
|
555
625
|
* import { all, ok } from "unthrown";
|
|
556
|
-
* all([ok(1), ok("a"), ok(true)]).unwrap(); // [1, "a", true]
|
|
626
|
+
* all([ok(1), ok("a"), ok(true)]).unwrap(); // [1, "a", true] (typed [number, string, boolean])
|
|
627
|
+
* all([ok(1), ok(2)] as Result<number, never>[]).unwrap(); // number[]
|
|
557
628
|
* ```
|
|
558
629
|
*/
|
|
559
630
|
function all(results) {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
631
|
+
return foldArray(results);
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Collect a **record** of {@link Result}s into a single `Result` of a record of
|
|
635
|
+
* their success values — `allFromDict({ a: Result<A, E>, b: Result<B, E> })` is
|
|
636
|
+
* `Result<{ a: A; b: B }, E>`. The named counterpart of {@link all}, for
|
|
637
|
+
* parallel work you'd rather not tuple.
|
|
638
|
+
*
|
|
639
|
+
* @remarks
|
|
640
|
+
* Same folding rules as {@link all}: first `Err` short-circuits, any `Defect`
|
|
641
|
+
* dominates. This is **not** error accumulation.
|
|
642
|
+
*
|
|
643
|
+
* @example
|
|
644
|
+
* ```ts
|
|
645
|
+
* import { allFromDict, ok } from "unthrown";
|
|
646
|
+
* allFromDict({ id: ok(1), name: ok("ada") }).unwrap(); // { id: 1, name: "ada" }
|
|
647
|
+
* ```
|
|
648
|
+
*/
|
|
649
|
+
function allFromDict(results) {
|
|
650
|
+
return foldRecord(results);
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* The asynchronous counterpart of {@link all}: combine a tuple/array of
|
|
654
|
+
* {@link AsyncResult}s into one `AsyncResult` of all their success values.
|
|
655
|
+
*
|
|
656
|
+
* @remarks
|
|
657
|
+
* The inputs are resolved **concurrently** (order preserved); the resolved
|
|
658
|
+
* `Result`s are then folded with the same rules as {@link all} — first `Err`
|
|
659
|
+
* short-circuits, any `Defect` dominates. As ever, the returned `AsyncResult`'s
|
|
660
|
+
* internal promise never rejects. For a **record**, use {@link allFromDictAsync}.
|
|
661
|
+
*
|
|
662
|
+
* @example
|
|
663
|
+
* ```ts
|
|
664
|
+
* import { allAsync, fromSafePromise } from "unthrown";
|
|
665
|
+
* await allAsync([fromSafePromise(a()), fromSafePromise(b())]);
|
|
666
|
+
* ```
|
|
667
|
+
*/
|
|
668
|
+
function allAsync(results) {
|
|
669
|
+
return new AsyncRes(Promise.all(results).then((resolved) => foldArray(resolved)));
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* The asynchronous counterpart of {@link allFromDict}: combine a record of
|
|
673
|
+
* {@link AsyncResult}s into one `AsyncResult` of a record of their values.
|
|
674
|
+
*
|
|
675
|
+
* @remarks
|
|
676
|
+
* Resolved concurrently (order preserved), folded with the {@link all} rules,
|
|
677
|
+
* and the internal promise never rejects.
|
|
678
|
+
*
|
|
679
|
+
* @example
|
|
680
|
+
* ```ts
|
|
681
|
+
* import { allFromDictAsync, fromSafePromise } from "unthrown";
|
|
682
|
+
* await allFromDictAsync({ a: fromSafePromise(a()), b: fromSafePromise(b()) });
|
|
683
|
+
* ```
|
|
684
|
+
*/
|
|
685
|
+
function allFromDictAsync(results) {
|
|
686
|
+
const entries = Object.entries(results);
|
|
687
|
+
return new AsyncRes(Promise.all(entries.map(([, ar]) => ar)).then((resolved) => {
|
|
688
|
+
const byKey = Object.create(null);
|
|
689
|
+
entries.forEach(([key], i) => {
|
|
690
|
+
byKey[key] = resolved[i];
|
|
691
|
+
});
|
|
692
|
+
return foldRecord(byKey);
|
|
693
|
+
}));
|
|
569
694
|
}
|
|
570
695
|
//#endregion
|
|
571
696
|
//#region src/facade.ts
|
|
@@ -574,7 +699,9 @@ function all(results) {
|
|
|
574
699
|
* discoverable namespace: {@link Result.ok}, {@link Result.err},
|
|
575
700
|
* {@link Result.defect}, {@link Result.fromNullable}, {@link Result.fromThrowable},
|
|
576
701
|
* {@link Result.fromPromise}, {@link Result.fromSafePromise}, {@link Result.all},
|
|
577
|
-
* {@link Result.
|
|
702
|
+
* {@link Result.allAsync}, {@link Result.allFromDict},
|
|
703
|
+
* {@link Result.allFromDictAsync}, {@link Result.isOk}, {@link Result.isErr},
|
|
704
|
+
* {@link Result.isDefect}.
|
|
578
705
|
*
|
|
579
706
|
* @remarks
|
|
580
707
|
* Purely additive sugar — each member **is** the corresponding free function.
|
|
@@ -597,6 +724,9 @@ const Result = {
|
|
|
597
724
|
fromPromise,
|
|
598
725
|
fromSafePromise,
|
|
599
726
|
all,
|
|
727
|
+
allAsync,
|
|
728
|
+
allFromDict,
|
|
729
|
+
allFromDictAsync,
|
|
600
730
|
isOk,
|
|
601
731
|
isErr,
|
|
602
732
|
isDefect
|
|
@@ -613,8 +743,26 @@ const Result = {
|
|
|
613
743
|
* field in the payload is forwarded to `Error`. The `_tag` always reflects
|
|
614
744
|
* `tag` and cannot be overridden by the payload.
|
|
615
745
|
*
|
|
746
|
+
* `_tag` is the discriminant used by {@link matchTags}; `Error.name` is the
|
|
747
|
+
* human-facing label in stack traces and logs. By default they coincide, but
|
|
748
|
+
* they can be **decoupled** with `options.name` — so a tag can be namespaced for
|
|
749
|
+
* collision-safety (`"@my-lib/RetryableError"`) without that slash-prefixed
|
|
750
|
+
* string leaking into `Error.name`:
|
|
751
|
+
*
|
|
752
|
+
* ```ts
|
|
753
|
+
* class RetryableError extends TaggedError("@my-lib/RetryableError", {
|
|
754
|
+
* name: "RetryableError",
|
|
755
|
+
* })<{ message: string }> {}
|
|
756
|
+
*
|
|
757
|
+
* const e = new RetryableError({ message: "boom" });
|
|
758
|
+
* e._tag; // "@my-lib/RetryableError" — namespaced discriminant
|
|
759
|
+
* e.name; // "RetryableError" — clean display name
|
|
760
|
+
* ```
|
|
761
|
+
*
|
|
616
762
|
* @typeParam Tag - the string literal discriminant.
|
|
617
|
-
* @param tag - the discriminant value
|
|
763
|
+
* @param tag - the discriminant value; also the default error `name`.
|
|
764
|
+
* @param options - optional overrides. `options.name` sets `Error.name`
|
|
765
|
+
* independently of `tag` (defaults to `tag`).
|
|
618
766
|
*
|
|
619
767
|
* @example
|
|
620
768
|
* ```ts
|
|
@@ -625,14 +773,15 @@ const Result = {
|
|
|
625
773
|
* new HttpError({ status: 500 }).status; // 500
|
|
626
774
|
* ```
|
|
627
775
|
*/
|
|
628
|
-
function TaggedError(tag) {
|
|
776
|
+
function TaggedError(tag, options) {
|
|
777
|
+
const displayName = options?.name ?? tag;
|
|
629
778
|
class TaggedErrorBase extends Error {
|
|
630
779
|
_tag;
|
|
631
780
|
constructor(props) {
|
|
632
781
|
super(typeof props?.["message"] === "string" ? props["message"] : void 0);
|
|
633
782
|
if (props) Object.assign(this, props);
|
|
634
783
|
this._tag = tag;
|
|
635
|
-
this.name =
|
|
784
|
+
this.name = displayName;
|
|
636
785
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
637
786
|
}
|
|
638
787
|
}
|
|
@@ -650,6 +799,6 @@ function matchTags(result, handlers) {
|
|
|
650
799
|
});
|
|
651
800
|
}
|
|
652
801
|
//#endregion
|
|
653
|
-
export { Result, TaggedError, UnwrapError, all, defect, err, fromNullable, fromPromise, fromSafePromise, fromThrowable, isDefect, isErr, isOk, matchTags, ok };
|
|
802
|
+
export { Result, TaggedError, UnwrapError, all, allAsync, allFromDict, allFromDictAsync, defect, err, fromNullable, fromPromise, fromSafePromise, fromThrowable, isDefect, isErr, isOk, matchTags, ok };
|
|
654
803
|
|
|
655
804
|
//# sourceMappingURL=index.mjs.map
|