@nlozgachev/pipelined 0.12.0 → 0.14.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/LICENCE +28 -0
- package/README.md +1 -1
- package/{types/src/Types/NonEmptyList.d.ts → dist/NonEmptyList-BlGFjor5.d.mts} +4 -3
- package/dist/NonEmptyList-BlGFjor5.d.ts +30 -0
- package/dist/Task-Bd3gXPRQ.d.mts +677 -0
- package/dist/Task-BjAkkD6t.d.ts +677 -0
- package/dist/chunk-4TXC322E.mjs +136 -0
- package/dist/chunk-BYWKZLHM.mjs +10 -0
- package/dist/chunk-DBIC62UV.mjs +6 -0
- package/dist/chunk-FAZN3IWZ.mjs +554 -0
- package/dist/chunk-QPTGO5AS.mjs +150 -0
- package/dist/chunk-UV2HMF2A.mjs +514 -0
- package/dist/composition.d.mts +495 -0
- package/dist/composition.d.ts +495 -0
- package/dist/composition.js +188 -0
- package/dist/composition.mjs +58 -0
- package/dist/core.d.mts +2170 -0
- package/dist/core.d.ts +2170 -0
- package/dist/core.js +698 -0
- package/dist/core.mjs +42 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1421 -0
- package/dist/index.mjs +120 -0
- package/dist/types.d.mts +54 -0
- package/{types/src/Types/Brand.d.ts → dist/types.d.ts} +6 -4
- package/dist/types.js +41 -0
- package/dist/types.mjs +10 -0
- package/dist/utils.d.mts +1285 -0
- package/dist/utils.d.ts +1285 -0
- package/dist/utils.js +722 -0
- package/dist/utils.mjs +18 -0
- package/package.json +64 -69
- package/esm/mod.js +0 -3
- package/esm/package.json +0 -3
- package/esm/src/Composition/compose.js +0 -3
- package/esm/src/Composition/converge.js +0 -3
- package/esm/src/Composition/curry.js +0 -42
- package/esm/src/Composition/flip.js +0 -20
- package/esm/src/Composition/flow.js +0 -8
- package/esm/src/Composition/fn.js +0 -85
- package/esm/src/Composition/index.js +0 -13
- package/esm/src/Composition/juxt.js +0 -3
- package/esm/src/Composition/memoize.js +0 -66
- package/esm/src/Composition/not.js +0 -25
- package/esm/src/Composition/on.js +0 -12
- package/esm/src/Composition/pipe.js +0 -3
- package/esm/src/Composition/tap.js +0 -33
- package/esm/src/Composition/uncurry.js +0 -32
- package/esm/src/Core/Deferred.js +0 -30
- package/esm/src/Core/InternalTypes.js +0 -1
- package/esm/src/Core/Lens.js +0 -98
- package/esm/src/Core/Logged.js +0 -111
- package/esm/src/Core/Option.js +0 -191
- package/esm/src/Core/Optional.js +0 -160
- package/esm/src/Core/Predicate.js +0 -133
- package/esm/src/Core/Reader.js +0 -134
- package/esm/src/Core/Refinement.js +0 -115
- package/esm/src/Core/RemoteData.js +0 -211
- package/esm/src/Core/Result.js +0 -170
- package/esm/src/Core/State.js +0 -181
- package/esm/src/Core/Task.js +0 -223
- package/esm/src/Core/TaskOption.js +0 -106
- package/esm/src/Core/TaskResult.js +0 -127
- package/esm/src/Core/TaskValidation.js +0 -128
- package/esm/src/Core/These.js +0 -245
- package/esm/src/Core/Tuple.js +0 -112
- package/esm/src/Core/Validation.js +0 -212
- package/esm/src/Core/index.js +0 -18
- package/esm/src/Types/Brand.js +0 -28
- package/esm/src/Types/NonEmptyList.js +0 -14
- package/esm/src/Types/index.js +0 -2
- package/esm/src/Utils/Arr.js +0 -570
- package/esm/src/Utils/Dict.js +0 -421
- package/esm/src/Utils/Num.js +0 -124
- package/esm/src/Utils/Rec.js +0 -241
- package/esm/src/Utils/Str.js +0 -134
- package/esm/src/Utils/Uniq.js +0 -265
- package/esm/src/Utils/index.js +0 -6
- package/script/mod.js +0 -19
- package/script/package.json +0 -3
- package/script/src/Composition/compose.js +0 -6
- package/script/src/Composition/converge.js +0 -6
- package/script/src/Composition/curry.js +0 -48
- package/script/src/Composition/flip.js +0 -24
- package/script/src/Composition/flow.js +0 -11
- package/script/src/Composition/fn.js +0 -98
- package/script/src/Composition/index.js +0 -29
- package/script/src/Composition/juxt.js +0 -6
- package/script/src/Composition/memoize.js +0 -71
- package/script/src/Composition/not.js +0 -29
- package/script/src/Composition/on.js +0 -16
- package/script/src/Composition/pipe.js +0 -6
- package/script/src/Composition/tap.js +0 -37
- package/script/src/Composition/uncurry.js +0 -38
- package/script/src/Core/Deferred.js +0 -33
- package/script/src/Core/InternalTypes.js +0 -2
- package/script/src/Core/Lens.js +0 -101
- package/script/src/Core/Logged.js +0 -114
- package/script/src/Core/Option.js +0 -194
- package/script/src/Core/Optional.js +0 -163
- package/script/src/Core/Predicate.js +0 -136
- package/script/src/Core/Reader.js +0 -137
- package/script/src/Core/Refinement.js +0 -118
- package/script/src/Core/RemoteData.js +0 -214
- package/script/src/Core/Result.js +0 -173
- package/script/src/Core/State.js +0 -184
- package/script/src/Core/Task.js +0 -226
- package/script/src/Core/TaskOption.js +0 -109
- package/script/src/Core/TaskResult.js +0 -130
- package/script/src/Core/TaskValidation.js +0 -131
- package/script/src/Core/These.js +0 -248
- package/script/src/Core/Tuple.js +0 -115
- package/script/src/Core/Validation.js +0 -215
- package/script/src/Core/index.js +0 -34
- package/script/src/Types/Brand.js +0 -31
- package/script/src/Types/NonEmptyList.js +0 -18
- package/script/src/Types/index.js +0 -18
- package/script/src/Utils/Arr.js +0 -573
- package/script/src/Utils/Dict.js +0 -424
- package/script/src/Utils/Num.js +0 -127
- package/script/src/Utils/Rec.js +0 -244
- package/script/src/Utils/Str.js +0 -137
- package/script/src/Utils/Uniq.js +0 -268
- package/script/src/Utils/index.js +0 -22
- package/types/mod.d.ts +0 -4
- package/types/mod.d.ts.map +0 -1
- package/types/src/Composition/compose.d.ts +0 -33
- package/types/src/Composition/compose.d.ts.map +0 -1
- package/types/src/Composition/converge.d.ts +0 -21
- package/types/src/Composition/converge.d.ts.map +0 -1
- package/types/src/Composition/curry.d.ts +0 -43
- package/types/src/Composition/curry.d.ts.map +0 -1
- package/types/src/Composition/flip.d.ts +0 -21
- package/types/src/Composition/flip.d.ts.map +0 -1
- package/types/src/Composition/flow.d.ts +0 -56
- package/types/src/Composition/flow.d.ts.map +0 -1
- package/types/src/Composition/fn.d.ts +0 -76
- package/types/src/Composition/fn.d.ts.map +0 -1
- package/types/src/Composition/index.d.ts +0 -14
- package/types/src/Composition/index.d.ts.map +0 -1
- package/types/src/Composition/juxt.d.ts +0 -18
- package/types/src/Composition/juxt.d.ts.map +0 -1
- package/types/src/Composition/memoize.d.ts +0 -46
- package/types/src/Composition/memoize.d.ts.map +0 -1
- package/types/src/Composition/not.d.ts +0 -26
- package/types/src/Composition/not.d.ts.map +0 -1
- package/types/src/Composition/on.d.ts +0 -13
- package/types/src/Composition/on.d.ts.map +0 -1
- package/types/src/Composition/pipe.d.ts +0 -56
- package/types/src/Composition/pipe.d.ts.map +0 -1
- package/types/src/Composition/tap.d.ts +0 -31
- package/types/src/Composition/tap.d.ts.map +0 -1
- package/types/src/Composition/uncurry.d.ts +0 -54
- package/types/src/Composition/uncurry.d.ts.map +0 -1
- package/types/src/Core/Deferred.d.ts +0 -49
- package/types/src/Core/Deferred.d.ts.map +0 -1
- package/types/src/Core/InternalTypes.d.ts +0 -23
- package/types/src/Core/InternalTypes.d.ts.map +0 -1
- package/types/src/Core/Lens.d.ts +0 -118
- package/types/src/Core/Lens.d.ts.map +0 -1
- package/types/src/Core/Logged.d.ts +0 -126
- package/types/src/Core/Logged.d.ts.map +0 -1
- package/types/src/Core/Option.d.ts +0 -209
- package/types/src/Core/Option.d.ts.map +0 -1
- package/types/src/Core/Optional.d.ts +0 -158
- package/types/src/Core/Optional.d.ts.map +0 -1
- package/types/src/Core/Predicate.d.ts +0 -161
- package/types/src/Core/Predicate.d.ts.map +0 -1
- package/types/src/Core/Reader.d.ts +0 -156
- package/types/src/Core/Reader.d.ts.map +0 -1
- package/types/src/Core/Refinement.d.ts +0 -138
- package/types/src/Core/Refinement.d.ts.map +0 -1
- package/types/src/Core/RemoteData.d.ts +0 -197
- package/types/src/Core/RemoteData.d.ts.map +0 -1
- package/types/src/Core/Result.d.ts +0 -182
- package/types/src/Core/Result.d.ts.map +0 -1
- package/types/src/Core/State.d.ts +0 -192
- package/types/src/Core/State.d.ts.map +0 -1
- package/types/src/Core/Task.d.ts +0 -219
- package/types/src/Core/Task.d.ts.map +0 -1
- package/types/src/Core/TaskOption.d.ts +0 -121
- package/types/src/Core/TaskOption.d.ts.map +0 -1
- package/types/src/Core/TaskResult.d.ts +0 -119
- package/types/src/Core/TaskResult.d.ts.map +0 -1
- package/types/src/Core/TaskValidation.d.ts +0 -144
- package/types/src/Core/TaskValidation.d.ts.map +0 -1
- package/types/src/Core/These.d.ts +0 -225
- package/types/src/Core/These.d.ts.map +0 -1
- package/types/src/Core/Tuple.d.ts +0 -129
- package/types/src/Core/Tuple.d.ts.map +0 -1
- package/types/src/Core/Validation.d.ts +0 -203
- package/types/src/Core/Validation.d.ts.map +0 -1
- package/types/src/Core/index.d.ts +0 -19
- package/types/src/Core/index.d.ts.map +0 -1
- package/types/src/Types/Brand.d.ts.map +0 -1
- package/types/src/Types/NonEmptyList.d.ts.map +0 -1
- package/types/src/Types/index.d.ts +0 -3
- package/types/src/Types/index.d.ts.map +0 -1
- package/types/src/Utils/Arr.d.ts +0 -403
- package/types/src/Utils/Arr.d.ts.map +0 -1
- package/types/src/Utils/Dict.d.ts +0 -310
- package/types/src/Utils/Dict.d.ts.map +0 -1
- package/types/src/Utils/Num.d.ts +0 -110
- package/types/src/Utils/Num.d.ts.map +0 -1
- package/types/src/Utils/Rec.d.ts +0 -159
- package/types/src/Utils/Rec.d.ts.map +0 -1
- package/types/src/Utils/Str.d.ts +0 -128
- package/types/src/Utils/Str.d.ts.map +0 -1
- package/types/src/Utils/Uniq.d.ts +0 -179
- package/types/src/Utils/Uniq.d.ts.map +0 -1
- package/types/src/Utils/index.d.ts +0 -7
- package/types/src/Utils/index.d.ts.map +0 -1
package/esm/src/Core/State.js
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
export var State;
|
|
2
|
-
(function (State) {
|
|
3
|
-
/**
|
|
4
|
-
* Lifts a pure value into a State computation. The state passes through unchanged.
|
|
5
|
-
*
|
|
6
|
-
* @example
|
|
7
|
-
* ```ts
|
|
8
|
-
* State.run(10)(State.resolve(42)); // [42, 10] — value 42, state unchanged
|
|
9
|
-
* ```
|
|
10
|
-
*/
|
|
11
|
-
State.resolve = (value) => (s) => [value, s];
|
|
12
|
-
/**
|
|
13
|
-
* Produces the current state as the value, without modifying it.
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```ts
|
|
17
|
-
* const readStack: State<string[], string[]> = State.get();
|
|
18
|
-
* State.run(["a", "b"])(readStack); // [["a", "b"], ["a", "b"]]
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
21
|
-
State.get = () => (s) => [s, s];
|
|
22
|
-
/**
|
|
23
|
-
* Reads a projection of the state without modifying it.
|
|
24
|
-
* Equivalent to `pipe(State.get(), State.map(f))` but more direct.
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```ts
|
|
28
|
-
* type AppState = { count: number; label: string };
|
|
29
|
-
* const readCount: State<AppState, number> = State.gets(s => s.count);
|
|
30
|
-
* State.run({ count: 5, label: "x" })(readCount); // [5, { count: 5, label: "x" }]
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
State.gets = (f) => (s) => [f(s), s];
|
|
34
|
-
/**
|
|
35
|
-
* Replaces the current state with a new value. Produces no meaningful value.
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```ts
|
|
39
|
-
* const reset: State<number, undefined> = State.put(0);
|
|
40
|
-
* State.run(99)(reset); // [undefined, 0]
|
|
41
|
-
* ```
|
|
42
|
-
*/
|
|
43
|
-
State.put = (newState) => (_s) => [undefined, newState];
|
|
44
|
-
/**
|
|
45
|
-
* Applies a function to the current state to produce the next state.
|
|
46
|
-
* Produces no meaningful value.
|
|
47
|
-
*
|
|
48
|
-
* @example
|
|
49
|
-
* ```ts
|
|
50
|
-
* const push = (item: string): State<string[], undefined> =>
|
|
51
|
-
* State.modify(stack => [...stack, item]);
|
|
52
|
-
*
|
|
53
|
-
* State.run(["a"])(push("b")); // [undefined, ["a", "b"]]
|
|
54
|
-
* ```
|
|
55
|
-
*/
|
|
56
|
-
State.modify = (f) => (s) => [undefined, f(s)];
|
|
57
|
-
/**
|
|
58
|
-
* Transforms the value produced by a State computation.
|
|
59
|
-
* The state transformation is unchanged.
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
|
-
* ```ts
|
|
63
|
-
* const readLength: State<string[], number> = pipe(
|
|
64
|
-
* State.get<string[]>(),
|
|
65
|
-
* State.map(stack => stack.length),
|
|
66
|
-
* );
|
|
67
|
-
*
|
|
68
|
-
* State.run(["a", "b", "c"])(readLength); // [3, ["a", "b", "c"]]
|
|
69
|
-
* ```
|
|
70
|
-
*/
|
|
71
|
-
State.map = (f) => (st) => (s) => {
|
|
72
|
-
const [a, s1] = st(s);
|
|
73
|
-
return [f(a), s1];
|
|
74
|
-
};
|
|
75
|
-
/**
|
|
76
|
-
* Sequences two State computations. The state output of the first is passed
|
|
77
|
-
* as the state input to the second.
|
|
78
|
-
*
|
|
79
|
-
* Data-last — the first computation is the data being piped.
|
|
80
|
-
*
|
|
81
|
-
* @example
|
|
82
|
-
* ```ts
|
|
83
|
-
* const push = (item: string): State<string[], undefined> =>
|
|
84
|
-
* State.modify(stack => [...stack, item]);
|
|
85
|
-
*
|
|
86
|
-
* const program = pipe(
|
|
87
|
-
* push("a"),
|
|
88
|
-
* State.chain(() => push("b")),
|
|
89
|
-
* State.chain(() => State.get<string[]>()),
|
|
90
|
-
* );
|
|
91
|
-
*
|
|
92
|
-
* State.evaluate([])(program); // ["a", "b"]
|
|
93
|
-
* ```
|
|
94
|
-
*/
|
|
95
|
-
State.chain = (f) => (st) => (s) => {
|
|
96
|
-
const [a, s1] = st(s);
|
|
97
|
-
return f(a)(s1);
|
|
98
|
-
};
|
|
99
|
-
/**
|
|
100
|
-
* Applies a function wrapped in a State to a value wrapped in a State.
|
|
101
|
-
* The function computation runs first; its output state is the input to the
|
|
102
|
-
* argument computation.
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* ```ts
|
|
106
|
-
* const addCounted = (n: number) => (m: number) => n + m;
|
|
107
|
-
* const program = pipe(
|
|
108
|
-
* State.resolve<number, typeof addCounted>(addCounted),
|
|
109
|
-
* State.ap(State.gets((s: number) => s * 2)),
|
|
110
|
-
* State.ap(State.gets((s: number) => s)),
|
|
111
|
-
* );
|
|
112
|
-
*
|
|
113
|
-
* State.evaluate(3)(program); // 6 + 3 = 9
|
|
114
|
-
* ```
|
|
115
|
-
*/
|
|
116
|
-
State.ap = (arg) => (fn) => (s) => {
|
|
117
|
-
const [f, s1] = fn(s);
|
|
118
|
-
const [a, s2] = arg(s1);
|
|
119
|
-
return [f(a), s2];
|
|
120
|
-
};
|
|
121
|
-
/**
|
|
122
|
-
* Runs a side effect on the produced value without changing the State computation.
|
|
123
|
-
*
|
|
124
|
-
* @example
|
|
125
|
-
* ```ts
|
|
126
|
-
* pipe(
|
|
127
|
-
* State.get<number>(),
|
|
128
|
-
* State.tap(n => console.log("current:", n)),
|
|
129
|
-
* State.chain(() => State.modify(n => n + 1)),
|
|
130
|
-
* );
|
|
131
|
-
* ```
|
|
132
|
-
*/
|
|
133
|
-
State.tap = (f) => (st) => (s) => {
|
|
134
|
-
const [a, s1] = st(s);
|
|
135
|
-
f(a);
|
|
136
|
-
return [a, s1];
|
|
137
|
-
};
|
|
138
|
-
/**
|
|
139
|
-
* Runs a State computation with an initial state, returning both the
|
|
140
|
-
* produced value and the final state as a pair.
|
|
141
|
-
*
|
|
142
|
-
* Data-last — the computation is the data being piped.
|
|
143
|
-
*
|
|
144
|
-
* @example
|
|
145
|
-
* ```ts
|
|
146
|
-
* const program = pipe(
|
|
147
|
-
* State.modify<number>(n => n + 1),
|
|
148
|
-
* State.chain(() => State.get<number>()),
|
|
149
|
-
* );
|
|
150
|
-
*
|
|
151
|
-
* State.run(0)(program); // [1, 1]
|
|
152
|
-
* ```
|
|
153
|
-
*/
|
|
154
|
-
State.run = (initialState) => (st) => st(initialState);
|
|
155
|
-
/**
|
|
156
|
-
* Runs a State computation with an initial state, returning only the
|
|
157
|
-
* produced value (discarding the final state).
|
|
158
|
-
*
|
|
159
|
-
* @example
|
|
160
|
-
* ```ts
|
|
161
|
-
* State.evaluate([])(pipe(
|
|
162
|
-
* State.modify<string[]>(s => [...s, "x"]),
|
|
163
|
-
* State.chain(() => State.get<string[]>()),
|
|
164
|
-
* )); // ["x"]
|
|
165
|
-
* ```
|
|
166
|
-
*/
|
|
167
|
-
State.evaluate = (initialState) => (st) => st(initialState)[0];
|
|
168
|
-
/**
|
|
169
|
-
* Runs a State computation with an initial state, returning only the
|
|
170
|
-
* final state (discarding the produced value).
|
|
171
|
-
*
|
|
172
|
-
* @example
|
|
173
|
-
* ```ts
|
|
174
|
-
* State.execute(0)(pipe(
|
|
175
|
-
* State.modify<number>(n => n + 10),
|
|
176
|
-
* State.chain(() => State.modify<number>(n => n * 2)),
|
|
177
|
-
* )); // 20
|
|
178
|
-
* ```
|
|
179
|
-
*/
|
|
180
|
-
State.execute = (initialState) => (st) => st(initialState)[1];
|
|
181
|
-
})(State || (State = {}));
|
package/esm/src/Core/Task.js
DELETED
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { Deferred } from "./Deferred.js";
|
|
2
|
-
import { Result } from "./Result.js";
|
|
3
|
-
// Internal helper — not exported. Runs a Task and converts the result to a Promise
|
|
4
|
-
// so that combinators can use Promise chaining (.then, Promise.all, Promise.race, etc.)
|
|
5
|
-
// internally without leaking that primitive through the public API.
|
|
6
|
-
const toPromise = (task) => Deferred.toPromise(task());
|
|
7
|
-
export var Task;
|
|
8
|
-
(function (Task) {
|
|
9
|
-
/**
|
|
10
|
-
* Creates a Task that immediately resolves to the given value.
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```ts
|
|
14
|
-
* const task = Task.resolve(42);
|
|
15
|
-
* const value = await task(); // 42
|
|
16
|
-
* ```
|
|
17
|
-
*/
|
|
18
|
-
Task.resolve = (value) => () => Deferred.fromPromise(Promise.resolve(value));
|
|
19
|
-
/**
|
|
20
|
-
* Creates a Task from a function that returns a Promise.
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* ```ts
|
|
24
|
-
* const getTimestamp = Task.from(() => Promise.resolve(Date.now()));
|
|
25
|
-
* ```
|
|
26
|
-
*/
|
|
27
|
-
Task.from = (f) => () => Deferred.fromPromise(f());
|
|
28
|
-
/**
|
|
29
|
-
* Transforms the value inside a Task.
|
|
30
|
-
*
|
|
31
|
-
* @example
|
|
32
|
-
* ```ts
|
|
33
|
-
* pipe(
|
|
34
|
-
* Task.resolve(5),
|
|
35
|
-
* Task.map(n => n * 2)
|
|
36
|
-
* )(); // Deferred<10>
|
|
37
|
-
* ```
|
|
38
|
-
*/
|
|
39
|
-
Task.map = (f) => (data) => Task.from(() => toPromise(data).then(f));
|
|
40
|
-
/**
|
|
41
|
-
* Chains Task computations. Passes the resolved value of the first Task to f.
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* ```ts
|
|
45
|
-
* const readUserId: Task<string> = Task.resolve(session.userId);
|
|
46
|
-
* const loadPrefs = (id: string): Task<Preferences> =>
|
|
47
|
-
* Task.resolve(prefsCache.get(id));
|
|
48
|
-
*
|
|
49
|
-
* pipe(
|
|
50
|
-
* readUserId,
|
|
51
|
-
* Task.chain(loadPrefs)
|
|
52
|
-
* )(); // Deferred<Preferences>
|
|
53
|
-
* ```
|
|
54
|
-
*/
|
|
55
|
-
Task.chain = (f) => (data) => Task.from(() => toPromise(data).then((a) => toPromise(f(a))));
|
|
56
|
-
/**
|
|
57
|
-
* Applies a function wrapped in a Task to a value wrapped in a Task.
|
|
58
|
-
* Both Tasks run in parallel.
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* ```ts
|
|
62
|
-
* const add = (a: number) => (b: number) => a + b;
|
|
63
|
-
* pipe(
|
|
64
|
-
* Task.resolve(add),
|
|
65
|
-
* Task.ap(Task.resolve(5)),
|
|
66
|
-
* Task.ap(Task.resolve(3))
|
|
67
|
-
* )(); // Deferred<8>
|
|
68
|
-
* ```
|
|
69
|
-
*/
|
|
70
|
-
Task.ap = (arg) => (data) => Task.from(() => Promise.all([
|
|
71
|
-
toPromise(data),
|
|
72
|
-
toPromise(arg),
|
|
73
|
-
]).then(([f, a]) => f(a)));
|
|
74
|
-
/**
|
|
75
|
-
* Executes a side effect on the value without changing the Task.
|
|
76
|
-
* Useful for logging or debugging.
|
|
77
|
-
*
|
|
78
|
-
* @example
|
|
79
|
-
* ```ts
|
|
80
|
-
* pipe(
|
|
81
|
-
* loadConfig,
|
|
82
|
-
* Task.tap(cfg => console.log("Config:", cfg)),
|
|
83
|
-
* Task.map(buildReport)
|
|
84
|
-
* );
|
|
85
|
-
* ```
|
|
86
|
-
*/
|
|
87
|
-
Task.tap = (f) => (data) => Task.from(() => toPromise(data).then((a) => {
|
|
88
|
-
f(a);
|
|
89
|
-
return a;
|
|
90
|
-
}));
|
|
91
|
-
/**
|
|
92
|
-
* Runs multiple Tasks in parallel and collects their results.
|
|
93
|
-
*
|
|
94
|
-
* @example
|
|
95
|
-
* ```ts
|
|
96
|
-
* Task.all([loadConfig, detectLocale, loadTheme])();
|
|
97
|
-
* // Deferred<[Config, string, Theme]>
|
|
98
|
-
* ```
|
|
99
|
-
*/
|
|
100
|
-
Task.all = (tasks) => Task.from(() => Promise.all(tasks.map((t) => toPromise(t))));
|
|
101
|
-
/**
|
|
102
|
-
* Delays the execution of a Task by the specified milliseconds.
|
|
103
|
-
* Useful for debouncing or rate limiting.
|
|
104
|
-
*
|
|
105
|
-
* @example
|
|
106
|
-
* ```ts
|
|
107
|
-
* pipe(
|
|
108
|
-
* Task.resolve(42),
|
|
109
|
-
* Task.delay(1000)
|
|
110
|
-
* )(); // Resolves after 1 second
|
|
111
|
-
* ```
|
|
112
|
-
*/
|
|
113
|
-
Task.delay = (ms) => (data) => Task.from(() => new Promise((resolve) => setTimeout(() => toPromise(data).then(resolve), ms)));
|
|
114
|
-
/**
|
|
115
|
-
* Runs a Task a fixed number of times sequentially, collecting all results into an array.
|
|
116
|
-
* An optional delay (ms) can be inserted between runs.
|
|
117
|
-
*
|
|
118
|
-
* @example
|
|
119
|
-
* ```ts
|
|
120
|
-
* pipe(
|
|
121
|
-
* pollSensor,
|
|
122
|
-
* Task.repeat({ times: 5, delay: 1000 })
|
|
123
|
-
* )(); // Task<Reading[]> — 5 readings, one per second
|
|
124
|
-
* ```
|
|
125
|
-
*/
|
|
126
|
-
Task.repeat = (options) => (task) => Task.from(() => {
|
|
127
|
-
const { times, delay: ms } = options;
|
|
128
|
-
if (times <= 0)
|
|
129
|
-
return Promise.resolve([]);
|
|
130
|
-
const results = [];
|
|
131
|
-
const wait = () => ms !== undefined && ms > 0 ? new Promise((r) => setTimeout(r, ms)) : Promise.resolve();
|
|
132
|
-
const run = (left) => toPromise(task).then((a) => {
|
|
133
|
-
results.push(a);
|
|
134
|
-
if (left <= 1)
|
|
135
|
-
return results;
|
|
136
|
-
return wait().then(() => run(left - 1));
|
|
137
|
-
});
|
|
138
|
-
return run(times);
|
|
139
|
-
});
|
|
140
|
-
/**
|
|
141
|
-
* Runs a Task repeatedly until the result satisfies a predicate, returning that result.
|
|
142
|
-
* An optional delay (ms) can be inserted between runs.
|
|
143
|
-
*
|
|
144
|
-
* @example
|
|
145
|
-
* ```ts
|
|
146
|
-
* pipe(
|
|
147
|
-
* checkStatus,
|
|
148
|
-
* Task.repeatUntil({ when: (s) => s === "ready", delay: 500 })
|
|
149
|
-
* )(); // polls every 500ms until status is "ready"
|
|
150
|
-
* ```
|
|
151
|
-
*/
|
|
152
|
-
Task.repeatUntil = (options) => (task) => Task.from(() => {
|
|
153
|
-
const { when: predicate, delay: ms } = options;
|
|
154
|
-
const wait = () => ms !== undefined && ms > 0 ? new Promise((r) => setTimeout(r, ms)) : Promise.resolve();
|
|
155
|
-
const run = () => toPromise(task).then((a) => {
|
|
156
|
-
if (predicate(a))
|
|
157
|
-
return a;
|
|
158
|
-
return wait().then(run);
|
|
159
|
-
});
|
|
160
|
-
return run();
|
|
161
|
-
});
|
|
162
|
-
/**
|
|
163
|
-
* Resolves with the value of the first Task to complete. All Tasks start
|
|
164
|
-
* immediately; the rest are abandoned once one resolves.
|
|
165
|
-
*
|
|
166
|
-
* @example
|
|
167
|
-
* ```ts
|
|
168
|
-
* const fast = Task.from(() => new Promise<string>(r => setTimeout(() => r("fast"), 10)));
|
|
169
|
-
* const slow = Task.from(() => new Promise<string>(r => setTimeout(() => r("slow"), 200)));
|
|
170
|
-
*
|
|
171
|
-
* await Task.race([fast, slow])(); // "fast"
|
|
172
|
-
* ```
|
|
173
|
-
*/
|
|
174
|
-
Task.race = (tasks) => Task.from(() => Promise.race(tasks.map(toPromise)));
|
|
175
|
-
/**
|
|
176
|
-
* Runs an array of Tasks one at a time in order, collecting all results.
|
|
177
|
-
* Each Task starts only after the previous one resolves.
|
|
178
|
-
*
|
|
179
|
-
* @example
|
|
180
|
-
* ```ts
|
|
181
|
-
* let log: number[] = [];
|
|
182
|
-
* const makeTask = (n: number) => Task.from(() => {
|
|
183
|
-
* log.push(n);
|
|
184
|
-
* return Promise.resolve(n);
|
|
185
|
-
* });
|
|
186
|
-
*
|
|
187
|
-
* await Task.sequential([makeTask(1), makeTask(2), makeTask(3)])();
|
|
188
|
-
* // log = [1, 2, 3] — tasks ran in order
|
|
189
|
-
* ```
|
|
190
|
-
*/
|
|
191
|
-
Task.sequential = (tasks) => Task.from(async () => {
|
|
192
|
-
const results = [];
|
|
193
|
-
for (const task of tasks) {
|
|
194
|
-
results.push(await toPromise(task));
|
|
195
|
-
}
|
|
196
|
-
return results;
|
|
197
|
-
});
|
|
198
|
-
/**
|
|
199
|
-
* Converts a `Task<A>` into a `Task<Result<E, A>>`, resolving to `Err` if the
|
|
200
|
-
* Task does not complete within the given time.
|
|
201
|
-
*
|
|
202
|
-
* @example
|
|
203
|
-
* ```ts
|
|
204
|
-
* pipe(
|
|
205
|
-
* heavyComputation,
|
|
206
|
-
* Task.timeout(5000, () => "timed out"),
|
|
207
|
-
* TaskResult.chain(processResult)
|
|
208
|
-
* );
|
|
209
|
-
* ```
|
|
210
|
-
*/
|
|
211
|
-
Task.timeout = (ms, onTimeout) => (task) => Task.from(() => {
|
|
212
|
-
let timerId;
|
|
213
|
-
return Promise.race([
|
|
214
|
-
toPromise(task).then((a) => {
|
|
215
|
-
clearTimeout(timerId);
|
|
216
|
-
return Result.ok(a);
|
|
217
|
-
}),
|
|
218
|
-
new Promise((resolve) => {
|
|
219
|
-
timerId = setTimeout(() => resolve(Result.err(onTimeout())), ms);
|
|
220
|
-
}),
|
|
221
|
-
]);
|
|
222
|
-
});
|
|
223
|
-
})(Task || (Task = {}));
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { Deferred } from "./Deferred.js";
|
|
2
|
-
import { Option } from "./Option.js";
|
|
3
|
-
import { Task } from "./Task.js";
|
|
4
|
-
export var TaskOption;
|
|
5
|
-
(function (TaskOption) {
|
|
6
|
-
/**
|
|
7
|
-
* Wraps a value in a Some inside a Task.
|
|
8
|
-
*/
|
|
9
|
-
TaskOption.some = (value) => Task.resolve(Option.some(value));
|
|
10
|
-
/**
|
|
11
|
-
* Creates a TaskOption that resolves to None.
|
|
12
|
-
*/
|
|
13
|
-
TaskOption.none = () => Task.resolve(Option.none());
|
|
14
|
-
/**
|
|
15
|
-
* Lifts an Option into a TaskOption.
|
|
16
|
-
*/
|
|
17
|
-
TaskOption.fromOption = (option) => Task.resolve(option);
|
|
18
|
-
/**
|
|
19
|
-
* Lifts a Task into a TaskOption by wrapping its result in Some.
|
|
20
|
-
*/
|
|
21
|
-
TaskOption.fromTask = (task) => Task.map(Option.some)(task);
|
|
22
|
-
/**
|
|
23
|
-
* Creates a TaskOption from a Promise-returning function.
|
|
24
|
-
* Returns Some if the promise resolves, None if it rejects.
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```ts
|
|
28
|
-
* const fetchUser = TaskOption.tryCatch(() =>
|
|
29
|
-
* fetch("/user/1").then(r => r.json())
|
|
30
|
-
* );
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
TaskOption.tryCatch = (f) => Task.from(() => f()
|
|
34
|
-
.then(Option.some)
|
|
35
|
-
.catch(() => Option.none()));
|
|
36
|
-
/**
|
|
37
|
-
* Transforms the value inside a TaskOption.
|
|
38
|
-
*/
|
|
39
|
-
TaskOption.map = (f) => (data) => Task.map(Option.map(f))(data);
|
|
40
|
-
/**
|
|
41
|
-
* Chains TaskOption computations. If the first resolves to Some, passes the
|
|
42
|
-
* value to f. If the first resolves to None, propagates None.
|
|
43
|
-
*
|
|
44
|
-
* @example
|
|
45
|
-
* ```ts
|
|
46
|
-
* pipe(
|
|
47
|
-
* findUser("123"),
|
|
48
|
-
* TaskOption.chain(user => findOrg(user.orgId))
|
|
49
|
-
* )();
|
|
50
|
-
* ```
|
|
51
|
-
*/
|
|
52
|
-
TaskOption.chain = (f) => (data) => Task.chain((option) => Option.isSome(option) ? f(option.value) : Task.resolve(Option.none()))(data);
|
|
53
|
-
/**
|
|
54
|
-
* Applies a function wrapped in a TaskOption to a value wrapped in a TaskOption.
|
|
55
|
-
* Both Tasks run in parallel.
|
|
56
|
-
*/
|
|
57
|
-
TaskOption.ap = (arg) => (data) => Task.from(() => Promise.all([
|
|
58
|
-
Deferred.toPromise(data()),
|
|
59
|
-
Deferred.toPromise(arg()),
|
|
60
|
-
]).then(([of_, oa]) => Option.ap(oa)(of_)));
|
|
61
|
-
/**
|
|
62
|
-
* Extracts a value from a TaskOption by providing handlers for both cases.
|
|
63
|
-
*/
|
|
64
|
-
TaskOption.fold = (onNone, onSome) => (data) => Task.map(Option.fold(onNone, onSome))(data);
|
|
65
|
-
/**
|
|
66
|
-
* Pattern matches on a TaskOption, returning a Task of the result.
|
|
67
|
-
*
|
|
68
|
-
* @example
|
|
69
|
-
* ```ts
|
|
70
|
-
* pipe(
|
|
71
|
-
* findUser("123"),
|
|
72
|
-
* TaskOption.match({
|
|
73
|
-
* some: user => `Hello, ${user.name}`,
|
|
74
|
-
* none: () => "User not found"
|
|
75
|
-
* })
|
|
76
|
-
* )();
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
|
-
TaskOption.match = (cases) => (data) => Task.map(Option.match(cases))(data);
|
|
80
|
-
/**
|
|
81
|
-
* Returns the value or a default if the TaskOption resolves to None.
|
|
82
|
-
* The default can be a different type, widening the result to `Task<A | B>`.
|
|
83
|
-
*/
|
|
84
|
-
TaskOption.getOrElse = (defaultValue) => (data) => Task.map(Option.getOrElse(defaultValue))(data);
|
|
85
|
-
/**
|
|
86
|
-
* Executes a side effect on the value without changing the TaskOption.
|
|
87
|
-
* Useful for logging or debugging.
|
|
88
|
-
*/
|
|
89
|
-
TaskOption.tap = (f) => (data) => Task.map(Option.tap(f))(data);
|
|
90
|
-
/**
|
|
91
|
-
* Filters the value inside a TaskOption. Returns None if the predicate fails.
|
|
92
|
-
*/
|
|
93
|
-
TaskOption.filter = (predicate) => (data) => Task.map(Option.filter(predicate))(data);
|
|
94
|
-
/**
|
|
95
|
-
* Converts a TaskOption to a TaskResult, using onNone to produce the error value.
|
|
96
|
-
*
|
|
97
|
-
* @example
|
|
98
|
-
* ```ts
|
|
99
|
-
* pipe(
|
|
100
|
-
* findUser("123"),
|
|
101
|
-
* TaskOption.toTaskResult(() => "User not found")
|
|
102
|
-
* );
|
|
103
|
-
* ```
|
|
104
|
-
*/
|
|
105
|
-
TaskOption.toTaskResult = (onNone) => (data) => Task.map(Option.toResult(onNone))(data);
|
|
106
|
-
})(TaskOption || (TaskOption = {}));
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { Deferred } from "./Deferred.js";
|
|
2
|
-
import { Result } from "./Result.js";
|
|
3
|
-
import { Task } from "./Task.js";
|
|
4
|
-
export var TaskResult;
|
|
5
|
-
(function (TaskResult) {
|
|
6
|
-
/**
|
|
7
|
-
* Wraps a value in a successful TaskResult.
|
|
8
|
-
*/
|
|
9
|
-
TaskResult.ok = (value) => Task.resolve(Result.ok(value));
|
|
10
|
-
/**
|
|
11
|
-
* Creates a failed TaskResult with the given error.
|
|
12
|
-
*/
|
|
13
|
-
TaskResult.err = (error) => Task.resolve(Result.err(error));
|
|
14
|
-
/**
|
|
15
|
-
* Creates a TaskResult from a function that may throw.
|
|
16
|
-
* Catches any errors and transforms them using the onError function.
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```ts
|
|
20
|
-
* const parseJson = (s: string): TaskResult<string, unknown> =>
|
|
21
|
-
* TaskResult.tryCatch(
|
|
22
|
-
* async () => JSON.parse(s),
|
|
23
|
-
* (e) => `Parse error: ${e}`
|
|
24
|
-
* );
|
|
25
|
-
* ```
|
|
26
|
-
*/
|
|
27
|
-
TaskResult.tryCatch = (f, onError) => Task.from(() => f()
|
|
28
|
-
.then(Result.ok)
|
|
29
|
-
.catch((e) => Result.err(onError(e))));
|
|
30
|
-
/**
|
|
31
|
-
* Transforms the success value inside a TaskResult.
|
|
32
|
-
*/
|
|
33
|
-
TaskResult.map = (f) => (data) => Task.map(Result.map(f))(data);
|
|
34
|
-
/**
|
|
35
|
-
* Transforms the error value inside a TaskResult.
|
|
36
|
-
*/
|
|
37
|
-
TaskResult.mapError = (f) => (data) => Task.map(Result.mapError(f))(data);
|
|
38
|
-
/**
|
|
39
|
-
* Chains TaskResult computations. If the first succeeds, passes the value to f.
|
|
40
|
-
* If the first fails, propagates the error.
|
|
41
|
-
*/
|
|
42
|
-
TaskResult.chain = (f) => (data) => Task.chain((result) => Result.isOk(result) ? f(result.value) : Task.resolve(Result.err(result.error)))(data);
|
|
43
|
-
/**
|
|
44
|
-
* Extracts the value from a TaskResult by providing handlers for both cases.
|
|
45
|
-
*/
|
|
46
|
-
TaskResult.fold = (onErr, onOk) => (data) => Task.map(Result.fold(onErr, onOk))(data);
|
|
47
|
-
/**
|
|
48
|
-
* Pattern matches on a TaskResult, returning a Task of the result.
|
|
49
|
-
*/
|
|
50
|
-
TaskResult.match = (cases) => (data) => Task.map(Result.match(cases))(data);
|
|
51
|
-
/**
|
|
52
|
-
* Recovers from an error by providing a fallback TaskResult.
|
|
53
|
-
* The fallback can produce a different success type, widening the result to `TaskResult<E, A | B>`.
|
|
54
|
-
*/
|
|
55
|
-
TaskResult.recover = (fallback) => (data) => Task.chain((result) => Result.isErr(result) ? fallback(result.error) : Task.resolve(result))(data);
|
|
56
|
-
/**
|
|
57
|
-
* Returns the success value or a default value if the TaskResult is an error.
|
|
58
|
-
* The default can be a different type, widening the result to `Task<A | B>`.
|
|
59
|
-
*/
|
|
60
|
-
TaskResult.getOrElse = (defaultValue) => (data) => Task.map(Result.getOrElse(defaultValue))(data);
|
|
61
|
-
/**
|
|
62
|
-
* Executes a side effect on the success value without changing the TaskResult.
|
|
63
|
-
* Useful for logging or debugging.
|
|
64
|
-
*/
|
|
65
|
-
TaskResult.tap = (f) => (data) => Task.map(Result.tap(f))(data);
|
|
66
|
-
/**
|
|
67
|
-
* Re-runs a TaskResult on `Err` with configurable attempts, backoff, and retry condition.
|
|
68
|
-
*
|
|
69
|
-
* @param options.attempts - Total number of attempts (1 = no retry, 3 = up to 3 tries)
|
|
70
|
-
* @param options.backoff - Fixed delay in ms, or a function `(attempt) => ms` for computed delay
|
|
71
|
-
* @param options.when - Only retry when this returns true; defaults to always retry on Err
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
|
-
* ```ts
|
|
75
|
-
* // Retry up to 3 times with exponential backoff
|
|
76
|
-
* pipe(
|
|
77
|
-
* fetchUser,
|
|
78
|
-
* TaskResult.retry({ attempts: 3, backoff: n => n * 1000 })
|
|
79
|
-
* );
|
|
80
|
-
*
|
|
81
|
-
* // Only retry on network errors, not auth errors
|
|
82
|
-
* pipe(
|
|
83
|
-
* fetchUser,
|
|
84
|
-
* TaskResult.retry({ attempts: 3, when: e => e instanceof NetworkError })
|
|
85
|
-
* );
|
|
86
|
-
* ```
|
|
87
|
-
*/
|
|
88
|
-
TaskResult.retry = (options) => (data) => Task.from(() => {
|
|
89
|
-
const { attempts, backoff, when: shouldRetry } = options;
|
|
90
|
-
const getDelay = (n) => backoff === undefined ? 0 : typeof backoff === "function" ? backoff(n) : backoff;
|
|
91
|
-
const run = (left) => Deferred.toPromise(data()).then((result) => {
|
|
92
|
-
if (Result.isOk(result))
|
|
93
|
-
return result;
|
|
94
|
-
if (left <= 1)
|
|
95
|
-
return result;
|
|
96
|
-
if (shouldRetry !== undefined && !shouldRetry(result.error)) {
|
|
97
|
-
return result;
|
|
98
|
-
}
|
|
99
|
-
const ms = getDelay(attempts - left + 1);
|
|
100
|
-
return (ms > 0 ? new Promise((r) => setTimeout(r, ms)) : Promise.resolve()).then(() => run(left - 1));
|
|
101
|
-
});
|
|
102
|
-
return run(attempts);
|
|
103
|
-
});
|
|
104
|
-
/**
|
|
105
|
-
* Fails a TaskResult with a typed error if it does not resolve within the given time.
|
|
106
|
-
*
|
|
107
|
-
* @example
|
|
108
|
-
* ```ts
|
|
109
|
-
* pipe(
|
|
110
|
-
* fetchUser,
|
|
111
|
-
* TaskResult.timeout(5000, () => new TimeoutError("fetch user timed out"))
|
|
112
|
-
* );
|
|
113
|
-
* ```
|
|
114
|
-
*/
|
|
115
|
-
TaskResult.timeout = (ms, onTimeout) => (data) => Task.from(() => {
|
|
116
|
-
let timerId;
|
|
117
|
-
return Promise.race([
|
|
118
|
-
Deferred.toPromise(data()).then((result) => {
|
|
119
|
-
clearTimeout(timerId);
|
|
120
|
-
return result;
|
|
121
|
-
}),
|
|
122
|
-
new Promise((resolve) => {
|
|
123
|
-
timerId = setTimeout(() => resolve(Result.err(onTimeout())), ms);
|
|
124
|
-
}),
|
|
125
|
-
]);
|
|
126
|
-
});
|
|
127
|
-
})(TaskResult || (TaskResult = {}));
|