@nlozgachev/pipelined 0.42.0 → 0.44.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/README.md +10 -10
- package/dist/InternalTypes-7o9-yrHq.d.ts +118 -0
- package/dist/InternalTypes-BL23H8Qr.d.mts +118 -0
- package/dist/{Task-BprUabHP.d.mts → Validation-DM2eh6wj.d.ts} +877 -113
- package/dist/{Task-Dt3ZMen6.d.ts → Validation-Dz70wtcG.d.mts} +877 -113
- package/dist/{chunk-GBB6LVLI.mjs → chunk-74JKKJ4R.mjs} +0 -4
- package/dist/{chunk-6VYLZTAM.mjs → chunk-LKTOK5IT.mjs} +157 -69
- package/dist/{chunk-OAP765G3.mjs → chunk-ND476266.mjs} +179 -134
- package/dist/{chunk-F6SBU7GB.mjs → chunk-X6XQX3OZ.mjs} +3 -3
- package/dist/composition.d.mts +45 -44
- package/dist/composition.d.ts +45 -44
- package/dist/composition.js +2 -2
- package/dist/composition.mjs +2 -2
- package/dist/core.d.mts +11 -813
- package/dist/core.d.ts +11 -813
- package/dist/core.js +176 -132
- package/dist/core.mjs +2 -2
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +332 -203
- package/dist/index.mjs +5 -7
- package/dist/types.d.mts +112 -17
- package/dist/types.d.ts +112 -17
- package/dist/types.js +2 -7
- package/dist/types.mjs +3 -5
- package/dist/utils.d.mts +345 -89
- package/dist/utils.d.ts +345 -89
- package/dist/utils.js +429 -107
- package/dist/utils.mjs +3 -3
- package/package.json +6 -6
- package/dist/Duration-BTeT9D-q.d.mts +0 -127
- package/dist/Duration-BTeT9D-q.d.ts +0 -127
|
@@ -1,57 +1,5 @@
|
|
|
1
|
-
import { D as
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
declare const _deferred: unique symbol;
|
|
5
|
-
/**
|
|
6
|
-
* A nominally typed, one-shot async value that supports `await` but enforces infallibility.
|
|
7
|
-
*
|
|
8
|
-
* Two design choices work together to make the guarantee structural rather than documentary:
|
|
9
|
-
*
|
|
10
|
-
* - The phantom `[_deferred]` symbol makes the type **nominal**: only values produced by
|
|
11
|
-
* `Deferred.fromPromise` satisfy it. A plain object `{ then: ... }` does not.
|
|
12
|
-
* - The single-parameter `.then()` **excludes rejection handlers** by construction. There is
|
|
13
|
-
* no second argument to pass, so chaining and `.catch()` are impossible.
|
|
14
|
-
*
|
|
15
|
-
* This makes `Deferred<A>` the natural return type for `Task<A>`, which is guaranteed to
|
|
16
|
-
* never reject.
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```ts
|
|
20
|
-
* const value = await Deferred.fromPromise(Promise.resolve(42));
|
|
21
|
-
* // value === 42
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
type Deferred<A> = {
|
|
25
|
-
readonly [_deferred]: A;
|
|
26
|
-
readonly then: (onfulfilled: (value: A) => unknown) => void;
|
|
27
|
-
};
|
|
28
|
-
declare namespace Deferred {
|
|
29
|
-
/**
|
|
30
|
-
* Wraps a `Promise` into a `Deferred`, structurally excluding rejection handlers,
|
|
31
|
-
* `.catch()`, `.finally()`, and chainable `.then()`.
|
|
32
|
-
*
|
|
33
|
-
* **Precondition**: `p` must never reject. If `p` rejects, the returned `Deferred` will
|
|
34
|
-
* never resolve — `await`-ing it will hang indefinitely. Use `TaskResult.tryCatch` to
|
|
35
|
-
* handle operations that may fail before converting to a `Deferred`.
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```ts
|
|
39
|
-
* const d = Deferred.fromPromise(Promise.resolve("hello"));
|
|
40
|
-
* const value = await d; // "hello"
|
|
41
|
-
* ```
|
|
42
|
-
*/
|
|
43
|
-
const fromPromise: <A>(p: Promise<A>) => Deferred<A>;
|
|
44
|
-
/**
|
|
45
|
-
* Converts a `Deferred` back into a `Promise`.
|
|
46
|
-
*
|
|
47
|
-
* @example
|
|
48
|
-
* ```ts
|
|
49
|
-
* const p = Deferred.toPromise(Deferred.fromPromise(Promise.resolve(42)));
|
|
50
|
-
* // p is Promise<42>
|
|
51
|
-
* ```
|
|
52
|
-
*/
|
|
53
|
-
const toPromise: <A>(d: Deferred<A>) => Promise<A>;
|
|
54
|
-
}
|
|
1
|
+
import { g as WithKind, n as WithValue, d as WithError, T as Thenable, D as Deferred, N as NonEmptyArr, e as WithErrors } from './InternalTypes-7o9-yrHq.js';
|
|
2
|
+
import { Duration } from './types.js';
|
|
55
3
|
|
|
56
4
|
/**
|
|
57
5
|
* A function that checks whether two values of type `A` are equal.
|
|
@@ -140,60 +88,6 @@ declare namespace Equality {
|
|
|
140
88
|
const and: <A>(eq2: Equality<A>) => (eq1: Equality<A>) => Equality<A>;
|
|
141
89
|
}
|
|
142
90
|
|
|
143
|
-
type WithKind<K extends string> = {
|
|
144
|
-
readonly kind: K;
|
|
145
|
-
};
|
|
146
|
-
type WithValue<T> = {
|
|
147
|
-
readonly value: T;
|
|
148
|
-
};
|
|
149
|
-
type WithError<T> = {
|
|
150
|
-
readonly error: T;
|
|
151
|
-
};
|
|
152
|
-
type WithErrors<T> = {
|
|
153
|
-
readonly errors: NonEmptyList<T>;
|
|
154
|
-
};
|
|
155
|
-
type WithFirst<T> = {
|
|
156
|
-
readonly first: T;
|
|
157
|
-
};
|
|
158
|
-
type WithSecond<T> = {
|
|
159
|
-
readonly second: T;
|
|
160
|
-
};
|
|
161
|
-
type WithLog<T> = {
|
|
162
|
-
readonly log: ReadonlyArray<T>;
|
|
163
|
-
};
|
|
164
|
-
/** Retry policy for `Op.interpret`. */
|
|
165
|
-
type RetryOptions<E> = {
|
|
166
|
-
readonly attempts: number;
|
|
167
|
-
readonly backoff?: Duration | ((attempt: number) => Duration);
|
|
168
|
-
readonly when?: (error: E) => boolean;
|
|
169
|
-
};
|
|
170
|
-
/** Timeout policy for `Op.interpret`. Wraps the entire retry sequence. */
|
|
171
|
-
type TimeoutOptions<E> = {
|
|
172
|
-
readonly duration: Duration;
|
|
173
|
-
readonly onTimeout: () => E;
|
|
174
|
-
};
|
|
175
|
-
type WithTimeout<E> = {
|
|
176
|
-
readonly timeout?: TimeoutOptions<E>;
|
|
177
|
-
};
|
|
178
|
-
type WithDuration = {
|
|
179
|
-
readonly duration: Duration;
|
|
180
|
-
};
|
|
181
|
-
type WithN = {
|
|
182
|
-
readonly n: number;
|
|
183
|
-
};
|
|
184
|
-
type WithConcurrency = {
|
|
185
|
-
readonly concurrency?: number;
|
|
186
|
-
};
|
|
187
|
-
type WithSize = {
|
|
188
|
-
readonly size?: number;
|
|
189
|
-
};
|
|
190
|
-
type WithCooldown = {
|
|
191
|
-
readonly cooldown?: Duration;
|
|
192
|
-
};
|
|
193
|
-
type WithMinInterval = {
|
|
194
|
-
readonly minInterval?: Duration;
|
|
195
|
-
};
|
|
196
|
-
|
|
197
91
|
type Some<A> = WithKind<"Some"> & WithValue<A>;
|
|
198
92
|
type None = WithKind<"None">;
|
|
199
93
|
/**
|
|
@@ -809,13 +703,552 @@ declare namespace Result {
|
|
|
809
703
|
const struct: <E, R extends Record<string, any>>(fields: { [K in keyof R]: Result<E, R[K]>; }) => Result<E, R>;
|
|
810
704
|
}
|
|
811
705
|
|
|
706
|
+
/**
|
|
707
|
+
* A Task that resolves to an optional value.
|
|
708
|
+
* Combines async operations with the Maybe type for values that may not exist.
|
|
709
|
+
*
|
|
710
|
+
* @example
|
|
711
|
+
* ```ts
|
|
712
|
+
* const findUser = (id: string): Task.Maybe<User> =>
|
|
713
|
+
* Task.Maybe.tryCatch(() => db.users.findById(id));
|
|
714
|
+
*
|
|
715
|
+
* pipe(
|
|
716
|
+
* findUser("123"),
|
|
717
|
+
* Task.Maybe.map(user => user.name),
|
|
718
|
+
* Task.Maybe.getOrElse(() => "Unknown")
|
|
719
|
+
* )();
|
|
720
|
+
* ```
|
|
721
|
+
*/
|
|
722
|
+
type TaskMaybe<A> = Task<Maybe<A>>;
|
|
723
|
+
declare namespace TaskMaybe {
|
|
724
|
+
/**
|
|
725
|
+
* Wraps a value in a Some inside a Task.
|
|
726
|
+
*/
|
|
727
|
+
const some: <A>(value: A) => TaskMaybe<A>;
|
|
728
|
+
/**
|
|
729
|
+
* Creates a Task.Maybe that resolves to None.
|
|
730
|
+
*/
|
|
731
|
+
const none: <A = never>() => TaskMaybe<A>;
|
|
732
|
+
/**
|
|
733
|
+
* Lifts an Option into a Task.Maybe.
|
|
734
|
+
*/
|
|
735
|
+
const fromMaybe: <A>(option: Maybe<A>) => TaskMaybe<A>;
|
|
736
|
+
/**
|
|
737
|
+
* Creates a Task.Maybe from a nullable value.
|
|
738
|
+
* Returns Some if the value is not null or undefined, None otherwise.
|
|
739
|
+
*/
|
|
740
|
+
const fromNullable: <A>(value: A | null | undefined) => TaskMaybe<A>;
|
|
741
|
+
/**
|
|
742
|
+
* Creates a Task.Maybe from a Result.
|
|
743
|
+
* Ok becomes Some, Error becomes None (the error value is discarded).
|
|
744
|
+
*/
|
|
745
|
+
const fromResult: <E, A>(result: Result<E, A>) => TaskMaybe<A>;
|
|
746
|
+
/**
|
|
747
|
+
* Lifts a Task into a Task.Maybe by wrapping its result in Some.
|
|
748
|
+
*/
|
|
749
|
+
const fromTask: <A>(task: Task<A>) => TaskMaybe<A>;
|
|
750
|
+
/**
|
|
751
|
+
* Creates a Task.Maybe from a Promise-returning function.
|
|
752
|
+
* Returns Some if the promise resolves, None if it rejects.
|
|
753
|
+
* The factory optionally receives an `AbortSignal` forwarded from the call site.
|
|
754
|
+
*
|
|
755
|
+
* @example
|
|
756
|
+
* ```ts
|
|
757
|
+
* const fetchUser = Task.Maybe.tryCatch((signal) =>
|
|
758
|
+
* fetch("/user/1", { signal }).then(r => r.json())
|
|
759
|
+
* );
|
|
760
|
+
* ```
|
|
761
|
+
*/
|
|
762
|
+
const tryCatch: <A>(f: (signal?: AbortSignal) => Thenable<A>) => TaskMaybe<A>;
|
|
763
|
+
/**
|
|
764
|
+
* Transforms the value inside a Task.Maybe.
|
|
765
|
+
*/
|
|
766
|
+
const map: <A, B>(f: (a: A) => B) => (data: TaskMaybe<A>) => TaskMaybe<B>;
|
|
767
|
+
/**
|
|
768
|
+
* Chains Task.Maybe computations. If the first resolves to Some, passes the
|
|
769
|
+
* value to f. If the first resolves to None, propagates None.
|
|
770
|
+
*
|
|
771
|
+
* @example
|
|
772
|
+
* ```ts
|
|
773
|
+
* pipe(
|
|
774
|
+
* findUser("123"),
|
|
775
|
+
* Task.Maybe.chain(user => findOrg(user.orgId))
|
|
776
|
+
* )();
|
|
777
|
+
* ```
|
|
778
|
+
*/
|
|
779
|
+
const chain: <A, B>(f: (a: A) => TaskMaybe<B>) => (data: TaskMaybe<A>) => TaskMaybe<B>;
|
|
780
|
+
/**
|
|
781
|
+
* Applies a function wrapped in a Task.Maybe to a value wrapped in a Task.Maybe.
|
|
782
|
+
* Both Tasks run in parallel.
|
|
783
|
+
*/
|
|
784
|
+
const ap: <A>(arg: TaskMaybe<A>) => <B>(data: TaskMaybe<(a: A) => B>) => TaskMaybe<B>;
|
|
785
|
+
/**
|
|
786
|
+
* Extracts a value from a Task.Maybe by providing handlers for both cases.
|
|
787
|
+
*/
|
|
788
|
+
const fold: <A, B>(onNone: () => B, onSome: (a: A) => B) => (data: TaskMaybe<A>) => Task<B>;
|
|
789
|
+
/**
|
|
790
|
+
* Pattern matches on a Task.Maybe, returning a Task of the result.
|
|
791
|
+
*
|
|
792
|
+
* @example
|
|
793
|
+
* ```ts
|
|
794
|
+
* pipe(
|
|
795
|
+
* findUser("123"),
|
|
796
|
+
* Task.Maybe.match({
|
|
797
|
+
* some: user => `Hello, ${user.name}`,
|
|
798
|
+
* none: () => "User not found"
|
|
799
|
+
* })
|
|
800
|
+
* )();
|
|
801
|
+
* ```
|
|
802
|
+
*/
|
|
803
|
+
const match: <A, B>(cases: {
|
|
804
|
+
none: () => B;
|
|
805
|
+
some: (a: A) => B;
|
|
806
|
+
}) => (data: TaskMaybe<A>) => Task<B>;
|
|
807
|
+
/**
|
|
808
|
+
* Returns the value or a default if the Task.Maybe resolves to None.
|
|
809
|
+
* The default can be a different type, widening the result to `Task<A | B>`.
|
|
810
|
+
*/
|
|
811
|
+
const getOrElse: <A, B>(defaultValue: () => B) => (data: TaskMaybe<A>) => Task<A | B>;
|
|
812
|
+
/**
|
|
813
|
+
* Executes a side effect on the value without changing the Task.Maybe.
|
|
814
|
+
* Useful for logging or debugging.
|
|
815
|
+
*/
|
|
816
|
+
const tap: <A>(f: (a: A) => void) => (data: TaskMaybe<A>) => TaskMaybe<A>;
|
|
817
|
+
/**
|
|
818
|
+
* Filters the value inside a Task.Maybe. Returns None if the predicate fails.
|
|
819
|
+
*/
|
|
820
|
+
const filter: <A>(predicate: (a: A) => boolean) => (data: TaskMaybe<A>) => TaskMaybe<A>;
|
|
821
|
+
/**
|
|
822
|
+
* Converts a Task.Maybe to a Task.Result, using onNone to produce the error value.
|
|
823
|
+
*
|
|
824
|
+
* @example
|
|
825
|
+
* ```ts
|
|
826
|
+
* pipe(
|
|
827
|
+
* findUser("123"),
|
|
828
|
+
* Task.Maybe.toResult(() => "User not found")
|
|
829
|
+
* );
|
|
830
|
+
* ```
|
|
831
|
+
*/
|
|
832
|
+
const toResult: <E>(onNone: () => E) => <A>(data: TaskMaybe<A>) => Task.Result<E, A>;
|
|
833
|
+
/**
|
|
834
|
+
* Lifts a Task.Maybe value into an accumulator object.
|
|
835
|
+
*
|
|
836
|
+
* @example
|
|
837
|
+
* ```ts
|
|
838
|
+
* pipe(Task.Maybe.some(42), Task.Maybe.bindTo("value")); // Task.Maybe({ value: 42 })
|
|
839
|
+
* ```
|
|
840
|
+
*/
|
|
841
|
+
const bindTo: <K extends string>(key: K) => <A>(data: TaskMaybe<A>) => TaskMaybe<{ [P in K]: A; }>;
|
|
842
|
+
/**
|
|
843
|
+
* Evaluates a new Task.Maybe using the current accumulator and attaches the output to a new key.
|
|
844
|
+
*
|
|
845
|
+
* @example
|
|
846
|
+
* ```ts
|
|
847
|
+
* pipe(
|
|
848
|
+
* Task.Maybe.some({ a: 1 }),
|
|
849
|
+
* Task.Maybe.bind("b", ({ a }) => Task.Maybe.some(a + 1))
|
|
850
|
+
* ); // Task.Maybe({ a: 1, b: 2 })
|
|
851
|
+
* ```
|
|
852
|
+
*/
|
|
853
|
+
const bind: <K extends string, A, B>(key: K, f: (a: A) => TaskMaybe<B>) => (data: TaskMaybe<A>) => TaskMaybe<A & { [P in K]: B; }>;
|
|
854
|
+
/**
|
|
855
|
+
* Recovers from a None state by providing a fallback Task.Maybe.
|
|
856
|
+
*
|
|
857
|
+
* @example
|
|
858
|
+
* ```ts
|
|
859
|
+
* pipe(
|
|
860
|
+
* Task.Maybe.none(),
|
|
861
|
+
* Task.Maybe.recover(() => Task.Maybe.some(42))
|
|
862
|
+
* ); // Task.Maybe(42)
|
|
863
|
+
* ```
|
|
864
|
+
*/
|
|
865
|
+
const recover: <A, B>(fallback: () => TaskMaybe<B>) => (data: TaskMaybe<A>) => TaskMaybe<A | B>;
|
|
866
|
+
/**
|
|
867
|
+
* Combines a record of Task.Maybes into a single Task.Maybe of a record.
|
|
868
|
+
* Evaluates fields in parallel and returns None if any task resolves to None.
|
|
869
|
+
*
|
|
870
|
+
* @example
|
|
871
|
+
* ```ts
|
|
872
|
+
* Task.Maybe.struct({
|
|
873
|
+
* name: Task.Maybe.some("Alice"),
|
|
874
|
+
* age: Task.Maybe.some(30)
|
|
875
|
+
* }); // Task.Maybe({ name: "Alice", age: 30 })
|
|
876
|
+
* ```
|
|
877
|
+
*/
|
|
878
|
+
const struct: <R extends Record<string, any>>(fields: { [K in keyof R]: TaskMaybe<R[K]>; }) => TaskMaybe<R>;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
/**
|
|
882
|
+
* A Task that can fail with an error of type E or succeed with a value of type A.
|
|
883
|
+
* Combines async operations with typed error handling.
|
|
884
|
+
*
|
|
885
|
+
* @example
|
|
886
|
+
* ```ts
|
|
887
|
+
* const fetchUser = (id: string): Task.Result<Error, User> =>
|
|
888
|
+
* Task.Result.tryCatch(
|
|
889
|
+
* (signal) => fetch(`/users/${id}`, { signal }).then(r => r.json()),
|
|
890
|
+
* (e) => new Error(`Failed to fetch user: ${e}`)
|
|
891
|
+
* );
|
|
892
|
+
* ```
|
|
893
|
+
*/
|
|
894
|
+
type TaskResult<E, A> = Task<Result<E, A>>;
|
|
895
|
+
declare namespace TaskResult {
|
|
896
|
+
/**
|
|
897
|
+
* Wraps a value in a successful Task.Result.
|
|
898
|
+
*/
|
|
899
|
+
const ok: <E, A>(value: A) => TaskResult<E, A>;
|
|
900
|
+
/**
|
|
901
|
+
* Creates a failed Task.Result with the given error.
|
|
902
|
+
*/
|
|
903
|
+
const err: <E, A>(error: E) => TaskResult<E, A>;
|
|
904
|
+
/**
|
|
905
|
+
* Creates a Task.Result from a nullable value.
|
|
906
|
+
* Returns Ok if the value is not null or undefined, err from onNull otherwise.
|
|
907
|
+
*/
|
|
908
|
+
const fromNullable: <E>(onNull: () => E) => <A>(value: A | null | undefined) => TaskResult<E, A>;
|
|
909
|
+
/**
|
|
910
|
+
* Creates a Task.Result from a Maybe.
|
|
911
|
+
* Some becomes Ok, None becomes err from onNone.
|
|
912
|
+
*/
|
|
913
|
+
const fromMaybe: <E>(onNone: () => E) => <A>(maybe: Maybe<A>) => TaskResult<E, A>;
|
|
914
|
+
/**
|
|
915
|
+
* Lifts a Result into a Task.Result.
|
|
916
|
+
*/
|
|
917
|
+
const fromResult: <E, A>(result: Result<E, A>) => TaskResult<E, A>;
|
|
918
|
+
/**
|
|
919
|
+
* Wraps a Promise-returning function of any arguments, returning a new function
|
|
920
|
+
* that catches rejections and returns a Task.Result.
|
|
921
|
+
*/
|
|
922
|
+
const fromThrowable: <Args extends readonly unknown[], A, E>(f: (...args: Args) => Promise<A>, onError: (e: unknown) => E) => (...args: Args) => TaskResult<E, A>;
|
|
923
|
+
/**
|
|
924
|
+
* Creates a Task.Result from a function that may throw.
|
|
925
|
+
* Catches any errors and transforms them using the onError function.
|
|
926
|
+
* The factory optionally receives an `AbortSignal` forwarded from the call site.
|
|
927
|
+
*
|
|
928
|
+
* @example
|
|
929
|
+
* ```ts
|
|
930
|
+
* const fetchUser = (id: string): Task.Result<string, User> =>
|
|
931
|
+
* Task.Result.tryCatch(
|
|
932
|
+
* (signal) => fetch(`/users/${id}`, { signal }).then(r => r.json()),
|
|
933
|
+
* String
|
|
934
|
+
* );
|
|
935
|
+
* ```
|
|
936
|
+
*/
|
|
937
|
+
const tryCatch: <E, A>(f: (signal?: AbortSignal) => Thenable<A>, onError: (e: unknown) => E) => TaskResult<E, A>;
|
|
938
|
+
/**
|
|
939
|
+
* Transforms the success value inside a Task.Result.
|
|
940
|
+
*/
|
|
941
|
+
const map: <E, A, B>(f: (a: A) => B) => (data: TaskResult<E, A>) => TaskResult<E, B>;
|
|
942
|
+
/**
|
|
943
|
+
* Transforms the error value inside a Task.Result.
|
|
944
|
+
*/
|
|
945
|
+
const mapError: <E, F, A>(f: (e: E) => F) => (data: TaskResult<E, A>) => TaskResult<F, A>;
|
|
946
|
+
/**
|
|
947
|
+
* Chains Task.Result computations. If the first succeeds, passes the value to f.
|
|
948
|
+
* If the first fails, propagates the error.
|
|
949
|
+
*/
|
|
950
|
+
const chain: <E, A, B>(f: (a: A) => TaskResult<E, B>) => (data: TaskResult<E, A>) => TaskResult<E, B>;
|
|
951
|
+
/**
|
|
952
|
+
* Extracts the value from a Task.Result by providing handlers for both cases.
|
|
953
|
+
*/
|
|
954
|
+
const fold: <E, A, B>(onErr: (e: E) => B, onOk: (a: A) => B) => (data: TaskResult<E, A>) => Task<B>;
|
|
955
|
+
/**
|
|
956
|
+
* Pattern matches on a Task.Result, returning a Task of the result.
|
|
957
|
+
*/
|
|
958
|
+
const match: <E, A, B>(cases: {
|
|
959
|
+
err: (e: E) => B;
|
|
960
|
+
ok: (a: A) => B;
|
|
961
|
+
}) => (data: TaskResult<E, A>) => Task<B>;
|
|
962
|
+
/**
|
|
963
|
+
* Recovers from an error by providing a fallback Task.Result.
|
|
964
|
+
* The fallback can produce a different success type, widening the result to `Task.Result<E, A | B>`.
|
|
965
|
+
*/
|
|
966
|
+
const recover: <E, A, B>(fallback: (e: E) => TaskResult<E, B>) => (data: TaskResult<E, A>) => TaskResult<E, A | B>;
|
|
967
|
+
/**
|
|
968
|
+
* Returns the success value or a default value if the Task.Result is an error.
|
|
969
|
+
* The default can be a different type, widening the result to `Task<A | B>`.
|
|
970
|
+
*/
|
|
971
|
+
const getOrElse: <E, A, B>(defaultValue: () => B) => (data: TaskResult<E, A>) => Task<A | B>;
|
|
972
|
+
/**
|
|
973
|
+
* Executes a side effect on the success value without changing the Task.Result.
|
|
974
|
+
* Useful for logging or debugging.
|
|
975
|
+
*/
|
|
976
|
+
const tap: <E, A>(f: (a: A) => void) => (data: TaskResult<E, A>) => TaskResult<E, A>;
|
|
977
|
+
/**
|
|
978
|
+
* Executes a side effect on the error value without changing the Task.Result.
|
|
979
|
+
* Useful for logging or reporting async errors.
|
|
980
|
+
*
|
|
981
|
+
* @example
|
|
982
|
+
* ```ts
|
|
983
|
+
* pipe(
|
|
984
|
+
* fetchUser(id),
|
|
985
|
+
* Task.Result.tapError(e => console.error("fetch failed:", e)),
|
|
986
|
+
* Task.Result.chain(saveToCache),
|
|
987
|
+
* )
|
|
988
|
+
* ```
|
|
989
|
+
*/
|
|
990
|
+
const tapError: <E, A>(f: (e: E) => void) => (data: TaskResult<E, A>) => TaskResult<E, A>;
|
|
991
|
+
/**
|
|
992
|
+
* Applies a function wrapped in a Task.Result to a value wrapped in a Task.Result.
|
|
993
|
+
* Both Tasks run in parallel.
|
|
994
|
+
*/
|
|
995
|
+
const ap: <E, A>(arg: TaskResult<E, A>) => <B>(data: TaskResult<E, (a: A) => B>) => TaskResult<E, B>;
|
|
996
|
+
/**
|
|
997
|
+
* Executes a `Task.Result` with an optional signal, returning `Promise<Result<E, A>>`.
|
|
998
|
+
* Use as a terminal step in a `pipe` chain.
|
|
999
|
+
*
|
|
1000
|
+
* @example
|
|
1001
|
+
* ```ts
|
|
1002
|
+
* const controller = new AbortController();
|
|
1003
|
+
* const result = await pipe(
|
|
1004
|
+
* fetchUser("42"),
|
|
1005
|
+
* Task.Result.chain(user => fetchPosts(user.id)),
|
|
1006
|
+
* Task.Result.run(controller.signal),
|
|
1007
|
+
* );
|
|
1008
|
+
* if (Result.isOk(result)) render(result.value);
|
|
1009
|
+
* ```
|
|
1010
|
+
*/
|
|
1011
|
+
const run: (signal?: AbortSignal) => <E, A>(task: TaskResult<E, A>) => Deferred<Result<E, A>>;
|
|
1012
|
+
/**
|
|
1013
|
+
* Converts a Task.Result value into an object containing a single property.
|
|
1014
|
+
* Initiates the pipeline accumulator record.
|
|
1015
|
+
*
|
|
1016
|
+
* @example
|
|
1017
|
+
* ```ts
|
|
1018
|
+
* pipe(Task.Result.ok(42), Task.Result.bindTo("value")); // Task.Result({ value: 42 })
|
|
1019
|
+
* ```
|
|
1020
|
+
*/
|
|
1021
|
+
const bindTo: <K extends string>(key: K) => <E, A>(data: TaskResult<E, A>) => TaskResult<E, { [P in K]: A; }>;
|
|
1022
|
+
/**
|
|
1023
|
+
* Evaluates a new Task.Result using the current accumulator and attaches the output to a new key.
|
|
1024
|
+
*
|
|
1025
|
+
* @example
|
|
1026
|
+
* ```ts
|
|
1027
|
+
* pipe(
|
|
1028
|
+
* Task.Result.ok({ a: 1 }),
|
|
1029
|
+
* Task.Result.bind("b", ({ a }) => Task.Result.ok(a + 1))
|
|
1030
|
+
* ); // Task.Result({ a: 1, b: 2 })
|
|
1031
|
+
* ```
|
|
1032
|
+
*/
|
|
1033
|
+
const bind: <K extends string, E, A, B>(key: K, f: (a: A) => TaskResult<E, B>) => (data: TaskResult<E, A>) => TaskResult<E, A & { [P in K]: B; }>;
|
|
1034
|
+
/**
|
|
1035
|
+
* Combines a record of Task.Results into a single Task.Result of a record.
|
|
1036
|
+
* Evaluates all tasks in parallel, forwarding the AbortSignal down to each sub-task.
|
|
1037
|
+
* Returns the first Err encountered in key order.
|
|
1038
|
+
*
|
|
1039
|
+
* @example
|
|
1040
|
+
* ```ts
|
|
1041
|
+
* Task.Result.struct({
|
|
1042
|
+
* name: Task.Result.ok("Alice"),
|
|
1043
|
+
* age: Task.Result.ok(30)
|
|
1044
|
+
* }); // Task.Result({ name: "Alice", age: 30 })
|
|
1045
|
+
* ```
|
|
1046
|
+
*/
|
|
1047
|
+
const struct: <E, R extends Record<string, any>>(fields: { [K in keyof R]: TaskResult<E, R[K]>; }) => TaskResult<E, R>;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
/**
|
|
1051
|
+
* A Task that resolves to a Validation — combining async operations with
|
|
1052
|
+
* error accumulation. Unlike Task.Result, multiple failures are collected
|
|
1053
|
+
* rather than short-circuiting on the first error.
|
|
1054
|
+
*
|
|
1055
|
+
* @example
|
|
1056
|
+
* ```ts
|
|
1057
|
+
* const validateName = (name: string): Task.Validation<string, string> =>
|
|
1058
|
+
* name.length > 0
|
|
1059
|
+
* ? Task.Validation.passed(name)
|
|
1060
|
+
* : Task.Validation.failed("Name is required");
|
|
1061
|
+
*
|
|
1062
|
+
* // Accumulate errors from multiple async validations using ap
|
|
1063
|
+
* pipe(
|
|
1064
|
+
* Task.Validation.passed((name: string) => (age: number) => ({ name, age })),
|
|
1065
|
+
* Task.Validation.ap(validateName("")),
|
|
1066
|
+
* Task.Validation.ap(validateAge(-1))
|
|
1067
|
+
* )();
|
|
1068
|
+
* // Failed(["Name is required", "Age must be positive"])
|
|
1069
|
+
* ```
|
|
1070
|
+
*/
|
|
1071
|
+
type TaskValidation<E, A> = Task<Validation<E, A>>;
|
|
1072
|
+
declare namespace TaskValidation {
|
|
1073
|
+
/**
|
|
1074
|
+
* Wraps a value in a passed Task.Validation.
|
|
1075
|
+
*/
|
|
1076
|
+
const passed: <E, A>(value: A) => TaskValidation<E, A>;
|
|
1077
|
+
/**
|
|
1078
|
+
* Creates a failed Task.Validation with a single error.
|
|
1079
|
+
*/
|
|
1080
|
+
const failed: <E, A>(error: E) => TaskValidation<E, A>;
|
|
1081
|
+
/**
|
|
1082
|
+
* Creates a failed Task.Validation from multiple errors.
|
|
1083
|
+
*/
|
|
1084
|
+
const failedAll: <E, A>(errors: NonEmptyArr<E>) => TaskValidation<E, A>;
|
|
1085
|
+
/**
|
|
1086
|
+
* Lifts a Validation into a Task.Validation.
|
|
1087
|
+
*/
|
|
1088
|
+
const fromValidation: <E, A>(validation: Validation<E, A>) => TaskValidation<E, A>;
|
|
1089
|
+
/**
|
|
1090
|
+
* Creates a Task.Validation from a nullable value.
|
|
1091
|
+
* If the value is null or undefined, returns Failed with the error from onNull.
|
|
1092
|
+
* Otherwise, returns Passed.
|
|
1093
|
+
*/
|
|
1094
|
+
const fromNullable: <E>(onNull: () => E) => <A>(value: A | null | undefined) => TaskValidation<E, A>;
|
|
1095
|
+
/**
|
|
1096
|
+
* Creates a Task.Validation from a Maybe.
|
|
1097
|
+
* Some becomes Passed, None becomes Failed with the error from onNone.
|
|
1098
|
+
*/
|
|
1099
|
+
const fromMaybe: <E>(onNone: () => E) => <A>(maybe: Maybe<A>) => TaskValidation<E, A>;
|
|
1100
|
+
/**
|
|
1101
|
+
* Creates a Task.Validation from a Result.
|
|
1102
|
+
* Ok becomes Passed, Err(e) becomes Failed([e]).
|
|
1103
|
+
*/
|
|
1104
|
+
const fromResult: <E, A>(result: Result<E, A>) => TaskValidation<E, A>;
|
|
1105
|
+
/**
|
|
1106
|
+
* Creates a Task.Validation from a Promise-returning function.
|
|
1107
|
+
* Catches any errors and transforms them using the onError function.
|
|
1108
|
+
* The factory optionally receives an `AbortSignal` forwarded from the call site.
|
|
1109
|
+
*
|
|
1110
|
+
* @example
|
|
1111
|
+
* ```ts
|
|
1112
|
+
* const fetchUser = (id: string): Task.Validation<string, User> =>
|
|
1113
|
+
* Task.Validation.tryCatch(
|
|
1114
|
+
* (signal) => fetch(`/users/${id}`, { signal }).then(r => r.json()),
|
|
1115
|
+
* e => `Failed to fetch user: ${e}`
|
|
1116
|
+
* );
|
|
1117
|
+
* ```
|
|
1118
|
+
*/
|
|
1119
|
+
const tryCatch: <E, A>(f: (signal?: AbortSignal) => Thenable<A>, onError: (e: unknown) => E) => TaskValidation<E, A>;
|
|
1120
|
+
/**
|
|
1121
|
+
* Transforms the success value inside a Task.Validation.
|
|
1122
|
+
*/
|
|
1123
|
+
const map: <E, A, B>(f: (a: A) => B) => (data: TaskValidation<E, A>) => TaskValidation<E, B>;
|
|
1124
|
+
/**
|
|
1125
|
+
* Applies a function wrapped in a Task.Validation to a value wrapped in a
|
|
1126
|
+
* Task.Validation. Both Tasks run in parallel and errors from both sides
|
|
1127
|
+
* are accumulated.
|
|
1128
|
+
*
|
|
1129
|
+
* @example
|
|
1130
|
+
* ```ts
|
|
1131
|
+
* pipe(
|
|
1132
|
+
* Task.Validation.passed((name: string) => (age: number) => ({ name, age })),
|
|
1133
|
+
* Task.Validation.ap(validateName(name)),
|
|
1134
|
+
* Task.Validation.ap(validateAge(age))
|
|
1135
|
+
* )();
|
|
1136
|
+
* ```
|
|
1137
|
+
*/
|
|
1138
|
+
const ap: <E, A>(arg: TaskValidation<E, A>) => <B>(data: TaskValidation<E, (a: A) => B>) => TaskValidation<E, B>;
|
|
1139
|
+
/**
|
|
1140
|
+
* Extracts a value from a Task.Validation by providing handlers for both cases.
|
|
1141
|
+
*/
|
|
1142
|
+
const fold: <E, A, B>(onFailed: (errors: NonEmptyArr<E>) => B, onPassed: (a: A) => B) => (data: TaskValidation<E, A>) => Task<B>;
|
|
1143
|
+
/**
|
|
1144
|
+
* Pattern matches on a Task.Validation, returning a Task of the result.
|
|
1145
|
+
*
|
|
1146
|
+
* @example
|
|
1147
|
+
* ```ts
|
|
1148
|
+
* pipe(
|
|
1149
|
+
* validateForm(input),
|
|
1150
|
+
* Task.Validation.match({
|
|
1151
|
+
* passed: data => save(data),
|
|
1152
|
+
* failed: errors => showErrors(errors)
|
|
1153
|
+
* })
|
|
1154
|
+
* )();
|
|
1155
|
+
* ```
|
|
1156
|
+
*/
|
|
1157
|
+
const match: <E, A, B>(cases: {
|
|
1158
|
+
passed: (a: A) => B;
|
|
1159
|
+
failed: (errors: NonEmptyArr<E>) => B;
|
|
1160
|
+
}) => (data: TaskValidation<E, A>) => Task<B>;
|
|
1161
|
+
/**
|
|
1162
|
+
* Returns the success value or a default value if the Task.Validation is failed.
|
|
1163
|
+
* The default can be a different type, widening the result to `Task<A | B>`.
|
|
1164
|
+
*/
|
|
1165
|
+
const getOrElse: <E, A, B>(defaultValue: () => B) => (data: TaskValidation<E, A>) => Task<A | B>;
|
|
1166
|
+
/**
|
|
1167
|
+
* Executes a side effect on the success value without changing the Task.Validation.
|
|
1168
|
+
* Useful for logging or debugging.
|
|
1169
|
+
*/
|
|
1170
|
+
const tap: <E, A>(f: (a: A) => void) => (data: TaskValidation<E, A>) => TaskValidation<E, A>;
|
|
1171
|
+
/**
|
|
1172
|
+
* Recovers from a Failed state by providing a fallback Task.Validation.
|
|
1173
|
+
* The fallback receives the accumulated error list so callers can inspect which errors occurred.
|
|
1174
|
+
* The fallback can produce a different success type, widening the result to `Task.Validation<E, A | B>`.
|
|
1175
|
+
*/
|
|
1176
|
+
const recover: <E, A, B>(fallback: (errors: NonEmptyArr<E>) => TaskValidation<E, B>) => (data: TaskValidation<E, A>) => TaskValidation<E, A | B>;
|
|
1177
|
+
/**
|
|
1178
|
+
* Runs two Task.Validations concurrently and combines their results into a tuple.
|
|
1179
|
+
* If both are Passed, returns Passed with both values. If either fails, accumulates
|
|
1180
|
+
* errors from both sides.
|
|
1181
|
+
*
|
|
1182
|
+
* @example
|
|
1183
|
+
* ```ts
|
|
1184
|
+
* await Task.Validation.product(
|
|
1185
|
+
* validateName(form.name),
|
|
1186
|
+
* validateAge(form.age),
|
|
1187
|
+
* )(); // Passed(["Alice", 30]) or Failed([...errors])
|
|
1188
|
+
* ```
|
|
1189
|
+
*/
|
|
1190
|
+
const product: <E, A, B>(first: TaskValidation<E, A>, second: TaskValidation<E, B>) => TaskValidation<E, readonly [A, B]>;
|
|
1191
|
+
/**
|
|
1192
|
+
* Runs all Task.Validations concurrently and collects results.
|
|
1193
|
+
* If all are Passed, returns Passed with all values as an array.
|
|
1194
|
+
* If any fail, returns Failed with all accumulated errors.
|
|
1195
|
+
*
|
|
1196
|
+
* @example
|
|
1197
|
+
* ```ts
|
|
1198
|
+
* await Task.Validation.productAll([
|
|
1199
|
+
* validateName(form.name),
|
|
1200
|
+
* validateEmail(form.email),
|
|
1201
|
+
* validateAge(form.age),
|
|
1202
|
+
* ])(); // Passed([name, email, age]) or Failed([...all errors])
|
|
1203
|
+
* ```
|
|
1204
|
+
*/
|
|
1205
|
+
const productAll: <E, A>(data: NonEmptyArr<TaskValidation<E, A>>) => TaskValidation<E, readonly A[]>;
|
|
1206
|
+
/**
|
|
1207
|
+
* Transforms all accumulated errors inside a Task.Validation.
|
|
1208
|
+
*
|
|
1209
|
+
* @example
|
|
1210
|
+
* ```ts
|
|
1211
|
+
* pipe(
|
|
1212
|
+
* Task.Validation.failed("oops"),
|
|
1213
|
+
* Task.Validation.mapError(e => e.toUpperCase())
|
|
1214
|
+
* ); // Task.Validation(Failed(["OOPS"]))
|
|
1215
|
+
* ```
|
|
1216
|
+
*/
|
|
1217
|
+
const mapError: <E, F, A>(f: (e: E) => F) => (data: TaskValidation<E, A>) => TaskValidation<F, A>;
|
|
1218
|
+
/**
|
|
1219
|
+
* Executes a side effect on the accumulated errors without changing the Task.Validation.
|
|
1220
|
+
*
|
|
1221
|
+
* @example
|
|
1222
|
+
* ```ts
|
|
1223
|
+
* pipe(
|
|
1224
|
+
* Task.Validation.failed("invalid name"),
|
|
1225
|
+
* Task.Validation.tapError(errs => logger.error(errs))
|
|
1226
|
+
* );
|
|
1227
|
+
* ```
|
|
1228
|
+
*/
|
|
1229
|
+
const tapError: <E, A>(f: (errors: NonEmptyArr<E>) => void) => (data: TaskValidation<E, A>) => TaskValidation<E, A>;
|
|
1230
|
+
/**
|
|
1231
|
+
* Combines a record of Task.Validations into a single Task.Validation of a record.
|
|
1232
|
+
* Evaluates fields in parallel and accumulates all validation errors.
|
|
1233
|
+
*
|
|
1234
|
+
* @example
|
|
1235
|
+
* ```ts
|
|
1236
|
+
* Task.Validation.struct({
|
|
1237
|
+
* name: Task.Validation.passed("Alice"),
|
|
1238
|
+
* age: Task.Validation.passed(30)
|
|
1239
|
+
* }); // Task.Validation({ name: "Alice", age: 30 })
|
|
1240
|
+
* ```
|
|
1241
|
+
*/
|
|
1242
|
+
const struct: <E, R extends Record<string, any>>(fields: { [K in keyof R]: TaskValidation<E, R[K]>; }) => TaskValidation<E, R>;
|
|
1243
|
+
}
|
|
1244
|
+
|
|
812
1245
|
/**
|
|
813
1246
|
* A lazy async computation that always resolves.
|
|
814
1247
|
*
|
|
815
1248
|
* Two guarantees:
|
|
816
1249
|
* - **Lazy** — nothing starts until you call it.
|
|
817
1250
|
* - **Infallible** — it never rejects. If failure is possible, encode it in the
|
|
818
|
-
* return type using `
|
|
1251
|
+
* return type using `Task.Result<E, A>` instead.
|
|
819
1252
|
*
|
|
820
1253
|
* An optional `AbortSignal` can be passed at the call site. Combinators like
|
|
821
1254
|
* `retry`, `pollUntil`, and `timeout` thread it automatically to every inner
|
|
@@ -872,7 +1305,7 @@ declare namespace Task {
|
|
|
872
1305
|
* const getTimestamp = Task.from(() => Promise.resolve(Date.now()));
|
|
873
1306
|
* ```
|
|
874
1307
|
*/
|
|
875
|
-
const from: <A>(f: (signal?: AbortSignal) =>
|
|
1308
|
+
const from: <A>(f: (signal?: AbortSignal) => Thenable<A>) => Task<A>;
|
|
876
1309
|
/**
|
|
877
1310
|
* Creates a Task from a lazy synchronous thunk.
|
|
878
1311
|
* Unlike `Task.resolve(f())`, `fromSync` does not evaluate `f` until the Task is called.
|
|
@@ -1052,7 +1485,7 @@ declare namespace Task {
|
|
|
1052
1485
|
* pipe(
|
|
1053
1486
|
* heavyComputation,
|
|
1054
1487
|
* Task.timeout(Duration.seconds(5), () => "timed out"),
|
|
1055
|
-
*
|
|
1488
|
+
* Task.Result.chain(processResult)
|
|
1056
1489
|
* );
|
|
1057
1490
|
* ```
|
|
1058
1491
|
*/
|
|
@@ -1078,7 +1511,7 @@ declare namespace Task {
|
|
|
1078
1511
|
* await poll();
|
|
1079
1512
|
* ```
|
|
1080
1513
|
*/
|
|
1081
|
-
const abortable: <A>(factory: (signal: AbortSignal) =>
|
|
1514
|
+
const abortable: <A>(factory: (signal: AbortSignal) => Thenable<A>) => {
|
|
1082
1515
|
task: Task<A>;
|
|
1083
1516
|
abort: () => void;
|
|
1084
1517
|
};
|
|
@@ -1117,6 +1550,337 @@ declare namespace Task {
|
|
|
1117
1550
|
* ```
|
|
1118
1551
|
*/
|
|
1119
1552
|
const bind: <K extends string, A, B>(key: K, f: (a: A) => Task<B>) => (data: Task<A>) => Task<A & { [P in K]: B; }>;
|
|
1553
|
+
type Maybe<A> = TaskMaybe<A>;
|
|
1554
|
+
const Maybe: typeof TaskMaybe;
|
|
1555
|
+
type Result<E, A> = TaskResult<E, A>;
|
|
1556
|
+
const Result: typeof TaskResult;
|
|
1557
|
+
type Validation<E, A> = TaskValidation<E, A>;
|
|
1558
|
+
const Validation: typeof TaskValidation;
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
type Passed<A> = WithKind<"Passed"> & WithValue<A>;
|
|
1562
|
+
type Failed<E> = WithKind<"Failed"> & WithErrors<E>;
|
|
1563
|
+
/**
|
|
1564
|
+
* Validation represents a value that is either passed with a success value,
|
|
1565
|
+
* or failed with accumulated errors.
|
|
1566
|
+
* Unlike Result, Validation can accumulate multiple errors instead of short-circuiting.
|
|
1567
|
+
*
|
|
1568
|
+
* Use Validation when you need to collect all errors (e.g., form validation).
|
|
1569
|
+
* Use Result when you want to fail fast on the first error.
|
|
1570
|
+
*
|
|
1571
|
+
* @example
|
|
1572
|
+
* ```ts
|
|
1573
|
+
* const validateName = (name: string): Validation<string, string> =>
|
|
1574
|
+
* name.length > 0 ? Validation.passed(name) : Validation.failed("Name is required");
|
|
1575
|
+
*
|
|
1576
|
+
* const validateAge = (age: number): Validation<string, number> =>
|
|
1577
|
+
* age >= 0 ? Validation.passed(age) : Validation.failed("Age must be positive");
|
|
1578
|
+
*
|
|
1579
|
+
* // Accumulates all errors using ap
|
|
1580
|
+
* pipe(
|
|
1581
|
+
* Validation.passed((name: string) => (age: number) => ({ name, age })),
|
|
1582
|
+
* Validation.ap(validateName("")),
|
|
1583
|
+
* Validation.ap(validateAge(-1))
|
|
1584
|
+
* );
|
|
1585
|
+
* // Failed(["Name is required", "Age must be positive"])
|
|
1586
|
+
* ```
|
|
1587
|
+
*/
|
|
1588
|
+
type Validation<E, A> = Passed<A> | Failed<E>;
|
|
1589
|
+
declare namespace Validation {
|
|
1590
|
+
/**
|
|
1591
|
+
* Wraps a value in a passed Validation.
|
|
1592
|
+
*
|
|
1593
|
+
* @example
|
|
1594
|
+
* ```ts
|
|
1595
|
+
* Validation.passed(42); // Passed(42)
|
|
1596
|
+
* ```
|
|
1597
|
+
*/
|
|
1598
|
+
const passed: <E, A>(value: A) => Validation<E, A>;
|
|
1599
|
+
/**
|
|
1600
|
+
* Creates a failed Validation from a single error.
|
|
1601
|
+
*
|
|
1602
|
+
* @example
|
|
1603
|
+
* ```ts
|
|
1604
|
+
* Validation.failed("Invalid input");
|
|
1605
|
+
* ```
|
|
1606
|
+
*/
|
|
1607
|
+
const failed: <E>(error: E) => Failed<E>;
|
|
1608
|
+
/**
|
|
1609
|
+
* Creates a failed Validation from multiple errors.
|
|
1610
|
+
*
|
|
1611
|
+
* @example
|
|
1612
|
+
* ```ts
|
|
1613
|
+
* Validation.failedAll(["Invalid input"]);
|
|
1614
|
+
* ```
|
|
1615
|
+
*/
|
|
1616
|
+
const failedAll: <E>(errors: NonEmptyArr<E>) => Failed<E>;
|
|
1617
|
+
/**
|
|
1618
|
+
* Type guard that checks if a Validation is passed.
|
|
1619
|
+
*/
|
|
1620
|
+
const isPassed: <E, A>(data: Validation<E, A>) => data is Passed<A>;
|
|
1621
|
+
/**
|
|
1622
|
+
* Type guard that checks if a Validation is failed.
|
|
1623
|
+
*/
|
|
1624
|
+
const isFailed: <E, A>(data: Validation<E, A>) => data is Failed<E>;
|
|
1625
|
+
/**
|
|
1626
|
+
* Creates a Validation from a predicate applied to a value.
|
|
1627
|
+
* Returns Passed if the predicate passes, Failed from `onFalse` otherwise.
|
|
1628
|
+
*
|
|
1629
|
+
* @example
|
|
1630
|
+
* ```ts
|
|
1631
|
+
* const validateName = Validation.fromPredicate(
|
|
1632
|
+
* (s: string) => s.length > 0,
|
|
1633
|
+
* () => "Name is required"
|
|
1634
|
+
* );
|
|
1635
|
+
*
|
|
1636
|
+
* validateName("Alice"); // Passed("Alice")
|
|
1637
|
+
* validateName(""); // Failed(["Name is required"])
|
|
1638
|
+
* ```
|
|
1639
|
+
*/
|
|
1640
|
+
const fromPredicate: <E, A>(pred: (a: A) => boolean, onFalse: (a: A) => E) => (a: A) => Validation<E, A>;
|
|
1641
|
+
/**
|
|
1642
|
+
* Creates a Validation from a nullable value.
|
|
1643
|
+
* If the value is null or undefined, returns Failed with the error from onNull.
|
|
1644
|
+
* Otherwise, returns Passed.
|
|
1645
|
+
*
|
|
1646
|
+
* @example
|
|
1647
|
+
* ```ts
|
|
1648
|
+
* pipe(null, Validation.fromNullable(() => "is null")); // Failed(["is null"])
|
|
1649
|
+
* pipe(42, Validation.fromNullable(() => "is null")); // Passed(42)
|
|
1650
|
+
* ```
|
|
1651
|
+
*/
|
|
1652
|
+
const fromNullable: <E>(onNull: () => E) => <A>(value: A | null | undefined) => Validation<E, A>;
|
|
1653
|
+
/**
|
|
1654
|
+
* Creates a Validation from a Maybe.
|
|
1655
|
+
* If the Maybe is None, returns Failed with the error from onNone.
|
|
1656
|
+
* Otherwise, returns Passed.
|
|
1657
|
+
*
|
|
1658
|
+
* @example
|
|
1659
|
+
* ```ts
|
|
1660
|
+
* pipe(Maybe.none(), Validation.fromMaybe(() => "is none")); // Failed(["is none"])
|
|
1661
|
+
* pipe(Maybe.some(42), Validation.fromMaybe(() => "is none")); // Passed(42)
|
|
1662
|
+
* ```
|
|
1663
|
+
*/
|
|
1664
|
+
const fromMaybe: <E>(onNone: () => E) => <A>(maybe: Maybe<A>) => Validation<E, A>;
|
|
1665
|
+
/**
|
|
1666
|
+
* Transforms the success value inside a Validation.
|
|
1667
|
+
*
|
|
1668
|
+
* @example
|
|
1669
|
+
* ```ts
|
|
1670
|
+
* pipe(Validation.passed(5), Validation.map(n => n * 2)); // Passed(10)
|
|
1671
|
+
* pipe(Validation.failed("oops"), Validation.map(n => n * 2)); // Failed(["oops"])
|
|
1672
|
+
* ```
|
|
1673
|
+
*/
|
|
1674
|
+
const map: <A, B>(f: (a: A) => B) => <E>(data: Validation<E, A>) => Validation<E, B>;
|
|
1675
|
+
/**
|
|
1676
|
+
* Transforms the error list inside a Validation.
|
|
1677
|
+
*
|
|
1678
|
+
* @example
|
|
1679
|
+
* ```ts
|
|
1680
|
+
* pipe(Validation.failed("oops"), Validation.mapError(e => e.toUpperCase())); // Failed(["OOPS"])
|
|
1681
|
+
* ```
|
|
1682
|
+
*/
|
|
1683
|
+
const mapError: <E, F, A>(f: (e: E) => F) => (data: Validation<E, A>) => Validation<F, A>;
|
|
1684
|
+
/**
|
|
1685
|
+
* Applies a function wrapped in a Validation to a value wrapped in a Validation.
|
|
1686
|
+
* Accumulates errors from both sides.
|
|
1687
|
+
*
|
|
1688
|
+
* @example
|
|
1689
|
+
* ```ts
|
|
1690
|
+
* const add = (a: number) => (b: number) => a + b;
|
|
1691
|
+
* pipe(
|
|
1692
|
+
* Validation.passed(add),
|
|
1693
|
+
* Validation.ap(Validation.passed(5)),
|
|
1694
|
+
* Validation.ap(Validation.passed(3))
|
|
1695
|
+
* ); // Passed(8)
|
|
1696
|
+
*
|
|
1697
|
+
* pipe(
|
|
1698
|
+
* Validation.passed(add),
|
|
1699
|
+
* Validation.ap(Validation.failed<string, number>("bad a")),
|
|
1700
|
+
* Validation.ap(Validation.failed<string, number>("bad b"))
|
|
1701
|
+
* ); // Failed(["bad a", "bad b"])
|
|
1702
|
+
* ```
|
|
1703
|
+
*/
|
|
1704
|
+
const ap: <E, A>(arg: Validation<E, A>) => <B>(data: Validation<E, (a: A) => B>) => Validation<E, B>;
|
|
1705
|
+
/**
|
|
1706
|
+
* Extracts the value from a Validation by providing handlers for both cases.
|
|
1707
|
+
*
|
|
1708
|
+
* @example
|
|
1709
|
+
* ```ts
|
|
1710
|
+
* pipe(
|
|
1711
|
+
* Validation.passed(42),
|
|
1712
|
+
* Validation.fold(
|
|
1713
|
+
* errors => `Errors: ${errors.join(", ")}`,
|
|
1714
|
+
* value => `Value: ${value}`
|
|
1715
|
+
* )
|
|
1716
|
+
* );
|
|
1717
|
+
* ```
|
|
1718
|
+
*/
|
|
1719
|
+
const fold: <E, A, B>(onFailed: (errors: NonEmptyArr<E>) => B, onPassed: (a: A) => B) => (data: Validation<E, A>) => B;
|
|
1720
|
+
/**
|
|
1721
|
+
* Pattern matches on a Validation, returning the result of the matching case.
|
|
1722
|
+
*
|
|
1723
|
+
* @example
|
|
1724
|
+
* ```ts
|
|
1725
|
+
* pipe(
|
|
1726
|
+
* validation,
|
|
1727
|
+
* Validation.match({
|
|
1728
|
+
* passed: value => `Got ${value}`,
|
|
1729
|
+
* failed: errors => `Failed: ${errors.join(", ")}`
|
|
1730
|
+
* })
|
|
1731
|
+
* );
|
|
1732
|
+
* ```
|
|
1733
|
+
*/
|
|
1734
|
+
const match: <E, A, B>(cases: {
|
|
1735
|
+
passed: (a: A) => B;
|
|
1736
|
+
failed: (errors: NonEmptyArr<E>) => B;
|
|
1737
|
+
}) => (data: Validation<E, A>) => B;
|
|
1738
|
+
/**
|
|
1739
|
+
* Returns the success value or a default value if the Validation is failed.
|
|
1740
|
+
* The default can be a different type, widening the result to `A | B`.
|
|
1741
|
+
*
|
|
1742
|
+
* @example
|
|
1743
|
+
* ```ts
|
|
1744
|
+
* pipe(Validation.passed(5), Validation.getOrElse(() => 0)); // 5
|
|
1745
|
+
* pipe(Validation.failed("oops"), Validation.getOrElse(() => 0)); // 0
|
|
1746
|
+
* pipe(Validation.failed("oops"), Validation.getOrElse(() => null)); // null — typed as number | null
|
|
1747
|
+
* ```
|
|
1748
|
+
*/
|
|
1749
|
+
const getOrElse: <E, A, B>(defaultValue: () => B) => (data: Validation<E, A>) => A | B;
|
|
1750
|
+
/**
|
|
1751
|
+
* Executes a side effect on the success value without changing the Validation.
|
|
1752
|
+
*
|
|
1753
|
+
* @example
|
|
1754
|
+
* ```ts
|
|
1755
|
+
* pipe(
|
|
1756
|
+
* Validation.passed(5),
|
|
1757
|
+
* Validation.tap(n => console.log("Value:", n)),
|
|
1758
|
+
* Validation.map(n => n * 2)
|
|
1759
|
+
* );
|
|
1760
|
+
* ```
|
|
1761
|
+
*/
|
|
1762
|
+
const tap: <E, A>(f: (a: A) => void) => (data: Validation<E, A>) => Validation<E, A>;
|
|
1763
|
+
/**
|
|
1764
|
+
* Executes a side effect on the accumulated errors without changing the Validation.
|
|
1765
|
+
* Useful for logging or reporting validation failures.
|
|
1766
|
+
*
|
|
1767
|
+
* @example
|
|
1768
|
+
* ```ts
|
|
1769
|
+
* pipe(
|
|
1770
|
+
* Validation.failed("Name required"),
|
|
1771
|
+
* Validation.tapError(errors => console.error("validation failed:", errors)),
|
|
1772
|
+
* Validation.map(toUser)
|
|
1773
|
+
* );
|
|
1774
|
+
* ```
|
|
1775
|
+
*/
|
|
1776
|
+
const tapError: <E, A>(f: (errors: NonEmptyArr<E>) => void) => (data: Validation<E, A>) => Validation<E, A>;
|
|
1777
|
+
/**
|
|
1778
|
+
* Recovers from a Failed state by providing a fallback Validation.
|
|
1779
|
+
* The fallback receives the accumulated error list so callers can inspect which errors occurred.
|
|
1780
|
+
* The fallback can produce a different success type, widening the result to `Validation<E, A | B>`.
|
|
1781
|
+
*/
|
|
1782
|
+
const recover: <E, A, B>(fallback: (errors: NonEmptyArr<E>) => Validation<E, B>) => (data: Validation<E, A>) => Validation<E, A | B>;
|
|
1783
|
+
/**
|
|
1784
|
+
* Recovers from a Failed state unless `isBlocked` returns true for any of the accumulated errors.
|
|
1785
|
+
* The fallback can produce a different success type, widening the result to `Validation<E, A | B>`.
|
|
1786
|
+
*
|
|
1787
|
+
* @example
|
|
1788
|
+
* ```ts
|
|
1789
|
+
* pipe(
|
|
1790
|
+
* Validation.failed("field-error"),
|
|
1791
|
+
* Validation.recoverUnless(e => e === "fatal", () => Validation.passed(0))
|
|
1792
|
+
* ); // Passed(0)
|
|
1793
|
+
* ```
|
|
1794
|
+
*/
|
|
1795
|
+
const recoverUnless: <E, A, B>(isBlocked: (e: E) => boolean, fallback: () => Validation<E, B>) => (data: Validation<E, A>) => Validation<E, A | B>;
|
|
1796
|
+
/**
|
|
1797
|
+
* Converts a Validation to a Result.
|
|
1798
|
+
* Passed becomes Ok, Failed becomes Err with the accumulated error list.
|
|
1799
|
+
*
|
|
1800
|
+
* @example
|
|
1801
|
+
* ```ts
|
|
1802
|
+
* Validation.toResult(Validation.passed(42)); // Ok(42)
|
|
1803
|
+
* Validation.toResult(Validation.failed("oops")); // Err(["oops"])
|
|
1804
|
+
* ```
|
|
1805
|
+
*/
|
|
1806
|
+
const toResult: <E, A>(data: Validation<E, A>) => Result<NonEmptyArr<E>, A>;
|
|
1807
|
+
/**
|
|
1808
|
+
* Converts a Validation to a Maybe. `Passed` becomes `Some`; `Failed` becomes `None`
|
|
1809
|
+
* (errors are discarded).
|
|
1810
|
+
*
|
|
1811
|
+
* @example
|
|
1812
|
+
* ```ts
|
|
1813
|
+
* Validation.toMaybe(Validation.passed(42)); // Some(42)
|
|
1814
|
+
* Validation.toMaybe(Validation.failed("bad")); // None
|
|
1815
|
+
* ```
|
|
1816
|
+
*/
|
|
1817
|
+
const toMaybe: <E, A>(data: Validation<E, A>) => Maybe<A>;
|
|
1818
|
+
/**
|
|
1819
|
+
* Converts a `Result` to a `Validation`. `Ok` becomes `Passed`; `Err(e)` becomes `Failed([e])`.
|
|
1820
|
+
*
|
|
1821
|
+
* Useful when bridging from error-short-circuiting `Result` pipelines into
|
|
1822
|
+
* error-accumulating `Validation` pipelines.
|
|
1823
|
+
*
|
|
1824
|
+
* @example
|
|
1825
|
+
* ```ts
|
|
1826
|
+
* Validation.fromResult(Result.ok(42)); // Passed(42)
|
|
1827
|
+
* Validation.fromResult(Result.err("bad")); // Failed(["bad"])
|
|
1828
|
+
* ```
|
|
1829
|
+
*/
|
|
1830
|
+
const fromResult: <E, A>(data: Result<E, A>) => Validation<E, A>;
|
|
1831
|
+
/**
|
|
1832
|
+
* Combines two independent Validation instances into a tuple.
|
|
1833
|
+
* If both are Passed, returns Passed with both values as a tuple.
|
|
1834
|
+
* If either is Failed, accumulates errors from both sides.
|
|
1835
|
+
*
|
|
1836
|
+
* @example
|
|
1837
|
+
* ```ts
|
|
1838
|
+
* Validation.product(
|
|
1839
|
+
* Validation.passed("alice"),
|
|
1840
|
+
* Validation.passed(30)
|
|
1841
|
+
* ); // Passed(["alice", 30])
|
|
1842
|
+
*
|
|
1843
|
+
* Validation.product(
|
|
1844
|
+
* Validation.failed("Name required"),
|
|
1845
|
+
* Validation.failed("Age must be >= 0")
|
|
1846
|
+
* ); // Failed(["Name required", "Age must be >= 0"])
|
|
1847
|
+
* ```
|
|
1848
|
+
*/
|
|
1849
|
+
const product: <E, A, B>(first: Validation<E, A>, second: Validation<E, B>) => Validation<E, readonly [A, B]>;
|
|
1850
|
+
/**
|
|
1851
|
+
* Combines a non-empty list of Validation instances, accumulating all errors.
|
|
1852
|
+
* If all are Passed, returns Passed with all values collected into an array.
|
|
1853
|
+
* If any are Failed, returns Failed with all accumulated errors.
|
|
1854
|
+
*
|
|
1855
|
+
* @example
|
|
1856
|
+
* ```ts
|
|
1857
|
+
* Validation.productAll([
|
|
1858
|
+
* validateName(name),
|
|
1859
|
+
* validateEmail(email),
|
|
1860
|
+
* validateAge(age)
|
|
1861
|
+
* ]);
|
|
1862
|
+
* // Passed([name, email, age]) or Failed([...all errors])
|
|
1863
|
+
* ```
|
|
1864
|
+
*/
|
|
1865
|
+
const productAll: <E, A>(data: NonEmptyArr<Validation<E, A>>) => Validation<E, readonly A[]>;
|
|
1866
|
+
/**
|
|
1867
|
+
* Combines a record of Validations into a single Validation of a record.
|
|
1868
|
+
* Accumulates all failed branches' errors.
|
|
1869
|
+
*
|
|
1870
|
+
* @example
|
|
1871
|
+
* ```ts
|
|
1872
|
+
* Validation.struct({
|
|
1873
|
+
* name: Validation.passed("Alice"),
|
|
1874
|
+
* age: Validation.passed(30)
|
|
1875
|
+
* }); // Passed({ name: "Alice", age: 30 })
|
|
1876
|
+
*
|
|
1877
|
+
* Validation.struct({
|
|
1878
|
+
* name: Validation.failed("Name required"),
|
|
1879
|
+
* age: Validation.failed("Age must be >= 0")
|
|
1880
|
+
* }); // Failed(["Name required", "Age must be >= 0"])
|
|
1881
|
+
* ```
|
|
1882
|
+
*/
|
|
1883
|
+
const struct: <E, R extends Record<string, any>>(fields: { [K in keyof R]: Validation<E, R[K]>; }) => Validation<E, R>;
|
|
1120
1884
|
}
|
|
1121
1885
|
|
|
1122
|
-
export {
|
|
1886
|
+
export { Equality as E, type Failed as F, Maybe as M, type None as N, type Ok as O, type Passed as P, Result as R, type Some as S, Task as T, Validation as V, type Err as a, Ordering as b, TaskMaybe as c, TaskResult as d, TaskValidation as e };
|