@nlozgachev/pipelined 0.64.0 → 0.66.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 +52 -52
- package/dist/Core-6SkC-fh5.cjs +6227 -0
- package/dist/Core-D7_9dZpV.mjs +6090 -0
- package/dist/InternalTypes-B1Lh9uw_.d.cts +143 -0
- package/dist/InternalTypes-DzDey5Do.d.ts +143 -0
- package/dist/composition.cjs +724 -632
- package/dist/composition.d.cts +453 -446
- package/dist/composition.d.ts +453 -446
- package/dist/composition.mjs +695 -577
- package/dist/core.cjs +24 -6580
- package/dist/core.d.cts +3 -2627
- package/dist/core.d.ts +3 -2627
- package/dist/core.mjs +2 -6532
- package/dist/data.cjs +2930 -3682
- package/dist/data.d.cts +1250 -1228
- package/dist/data.d.ts +1250 -1228
- package/dist/data.mjs +2921 -3647
- package/dist/index-8A9NqJTq.d.cts +4420 -0
- package/dist/index-Bs8En5LJ.d.cts +238 -0
- package/dist/index-Bs8En5LJ.d.ts +238 -0
- package/dist/index-CY4ZLbjM.d.ts +4420 -0
- package/dist/index.cjs +69 -9607
- package/dist/index.d.cts +6 -7
- package/dist/index.d.ts +6 -7
- package/dist/index.mjs +5 -9517
- package/dist/types.cjs +195 -225
- package/dist/types.d.cts +2 -58
- package/dist/types.d.ts +2 -58
- package/dist/types.mjs +192 -196
- package/package.json +24 -15
- package/dist/Duration-DeyxG6VQ.d.cts +0 -181
- package/dist/Duration-DeyxG6VQ.d.ts +0 -181
- package/dist/InternalTypes-CCXa8Kvr.d.ts +0 -142
- package/dist/InternalTypes-GFn4RTwD.d.cts +0 -142
- package/dist/Task-9SJCMtG4.d.ts +0 -1748
- package/dist/Task-C_goFYQ1.d.cts +0 -1748
package/dist/composition.mjs
CHANGED
|
@@ -1,610 +1,728 @@
|
|
|
1
|
-
|
|
1
|
+
import { Duration } from "./types.mjs";
|
|
2
|
+
import { inspect } from "node:util";
|
|
3
|
+
//#region src/Composition/compose.ts
|
|
2
4
|
function compose(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
case 7: {
|
|
34
|
-
return function() {
|
|
35
|
-
return f0(f1(f2(f3(f4(f5(f6.apply(this, arguments)))))));
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
case 8: {
|
|
39
|
-
return function() {
|
|
40
|
-
return f0(f1(f2(f3(f4(f5(f6(f7.apply(this, arguments))))))));
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
case 9: {
|
|
44
|
-
return function() {
|
|
45
|
-
return f0(f1(f2(f3(f4(f5(f6(f7(f8.apply(this, arguments)))))))));
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
case 10: {
|
|
49
|
-
return function() {
|
|
50
|
-
return f0(f1(f2(f3(f4(f5(f6(f7(f8(f9.apply(this, arguments))))))))));
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
}
|
|
5
|
+
switch (arguments.length) {
|
|
6
|
+
case 1: return f0;
|
|
7
|
+
case 2: return function() {
|
|
8
|
+
return f0(f1.apply(this, arguments));
|
|
9
|
+
};
|
|
10
|
+
case 3: return function() {
|
|
11
|
+
return f0(f1(f2.apply(this, arguments)));
|
|
12
|
+
};
|
|
13
|
+
case 4: return function() {
|
|
14
|
+
return f0(f1(f2(f3.apply(this, arguments))));
|
|
15
|
+
};
|
|
16
|
+
case 5: return function() {
|
|
17
|
+
return f0(f1(f2(f3(f4.apply(this, arguments)))));
|
|
18
|
+
};
|
|
19
|
+
case 6: return function() {
|
|
20
|
+
return f0(f1(f2(f3(f4(f5.apply(this, arguments))))));
|
|
21
|
+
};
|
|
22
|
+
case 7: return function() {
|
|
23
|
+
return f0(f1(f2(f3(f4(f5(f6.apply(this, arguments)))))));
|
|
24
|
+
};
|
|
25
|
+
case 8: return function() {
|
|
26
|
+
return f0(f1(f2(f3(f4(f5(f6(f7.apply(this, arguments))))))));
|
|
27
|
+
};
|
|
28
|
+
case 9: return function() {
|
|
29
|
+
return f0(f1(f2(f3(f4(f5(f6(f7(f8.apply(this, arguments)))))))));
|
|
30
|
+
};
|
|
31
|
+
case 10: return function() {
|
|
32
|
+
return f0(f1(f2(f3(f4(f5(f6(f7(f8(f9.apply(this, arguments))))))))));
|
|
33
|
+
};
|
|
34
|
+
}
|
|
54
35
|
}
|
|
55
|
-
|
|
56
|
-
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/Composition/converge.ts
|
|
57
38
|
function converge(f, transformers) {
|
|
58
|
-
|
|
39
|
+
return (a) => f(...transformers.map((t) => t(a)));
|
|
59
40
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/Composition/curry.ts
|
|
43
|
+
/**
|
|
44
|
+
* Converts a multi-argument function into a curried function.
|
|
45
|
+
* The inverse of `uncurry`.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const add = (a: number, b: number) => a + b;
|
|
50
|
+
* const curriedAdd = curry(add);
|
|
51
|
+
* curriedAdd(1)(2); // 3
|
|
52
|
+
*
|
|
53
|
+
* // Partial application
|
|
54
|
+
* const addTen = curriedAdd(10);
|
|
55
|
+
* addTen(5); // 15
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @see {@link uncurry} for the inverse operation
|
|
59
|
+
* @see {@link curry3} for 3-argument functions
|
|
60
|
+
* @see {@link curry4} for 4-argument functions
|
|
61
|
+
*/
|
|
62
|
+
const curry = (f) => (a) => (b) => f(a, b);
|
|
63
|
+
/**
|
|
64
|
+
* Converts a 3-argument function into a curried function.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* const add3 = (a: number, b: number, c: number) => a + b + c;
|
|
69
|
+
* const curriedAdd3 = curry3(add3);
|
|
70
|
+
* curriedAdd3(1)(2)(3); // 6
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
const curry3 = (f) => (a) => (b) => (c) => f(a, b, c);
|
|
74
|
+
/**
|
|
75
|
+
* Converts a 4-argument function into a curried function.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* const add4 = (a: number, b: number, c: number, d: number) => a + b + c + d;
|
|
80
|
+
* const curriedAdd4 = curry4(add4);
|
|
81
|
+
* curriedAdd4(1)(2)(3)(4); // 10
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
const curry4 = (f) => (a) => (b) => (c) => (d) => f(a, b, c, d);
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/Composition/flip.ts
|
|
87
|
+
/**
|
|
88
|
+
* Flips the order of arguments for a curried binary function.
|
|
89
|
+
* Converts a data-last function to data-first.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* // Original data-last (for pipe)
|
|
94
|
+
* pipe(
|
|
95
|
+
* Maybe.make.some(5),
|
|
96
|
+
* Maybe.map(n => n * 2)
|
|
97
|
+
* ); // Some(10)
|
|
98
|
+
*
|
|
99
|
+
* // Flipped to data-first
|
|
100
|
+
* const mapFirst = flip(Maybe.map);
|
|
101
|
+
* mapFirst(Maybe.make.some(5))(n => n * 2); // Some(10)
|
|
102
|
+
* ```
|
|
103
|
+
*
|
|
104
|
+
* @see {@link uncurry} for converting curried functions to multi-argument functions
|
|
105
|
+
*/
|
|
106
|
+
const flip = (f) => (b) => (a) => f(a)(b);
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/Composition/flow.ts
|
|
70
109
|
function flow(ab, bc, cd, de, ef, fg, gh, hi, ij, jk) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
case 7: {
|
|
107
|
-
return function() {
|
|
108
|
-
return gh(fg(ef(de(cd(bc(ab.apply(this, arguments)))))));
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
case 8: {
|
|
112
|
-
return function() {
|
|
113
|
-
return hi(gh(fg(ef(de(cd(bc(ab.apply(this, arguments))))))));
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
case 9: {
|
|
117
|
-
return function() {
|
|
118
|
-
return ij(hi(gh(fg(ef(de(cd(bc(ab.apply(this, arguments)))))))));
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
case 10: {
|
|
122
|
-
return function() {
|
|
123
|
-
return jk(ij(hi(gh(fg(ef(de(cd(bc(ab.apply(this, arguments))))))))));
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
}
|
|
110
|
+
switch (arguments.length) {
|
|
111
|
+
case 0: return function(...args) {
|
|
112
|
+
return args[0];
|
|
113
|
+
};
|
|
114
|
+
case 1: return ab;
|
|
115
|
+
case 2: return function() {
|
|
116
|
+
return bc(ab.apply(this, arguments));
|
|
117
|
+
};
|
|
118
|
+
case 3: return function() {
|
|
119
|
+
return cd(bc(ab.apply(this, arguments)));
|
|
120
|
+
};
|
|
121
|
+
case 4: return function() {
|
|
122
|
+
return de(cd(bc(ab.apply(this, arguments))));
|
|
123
|
+
};
|
|
124
|
+
case 5: return function() {
|
|
125
|
+
return ef(de(cd(bc(ab.apply(this, arguments)))));
|
|
126
|
+
};
|
|
127
|
+
case 6: return function() {
|
|
128
|
+
return fg(ef(de(cd(bc(ab.apply(this, arguments))))));
|
|
129
|
+
};
|
|
130
|
+
case 7: return function() {
|
|
131
|
+
return gh(fg(ef(de(cd(bc(ab.apply(this, arguments)))))));
|
|
132
|
+
};
|
|
133
|
+
case 8: return function() {
|
|
134
|
+
return hi(gh(fg(ef(de(cd(bc(ab.apply(this, arguments))))))));
|
|
135
|
+
};
|
|
136
|
+
case 9: return function() {
|
|
137
|
+
return ij(hi(gh(fg(ef(de(cd(bc(ab.apply(this, arguments)))))))));
|
|
138
|
+
};
|
|
139
|
+
case 10: return function() {
|
|
140
|
+
return jk(ij(hi(gh(fg(ef(de(cd(bc(ab.apply(this, arguments))))))))));
|
|
141
|
+
};
|
|
142
|
+
}
|
|
127
143
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
return result;
|
|
144
|
+
const when$1 = (predicate, onTrue) => (a) => predicate(a) ? onTrue(a) : a;
|
|
145
|
+
const unless$1 = (predicate, onFalse) => (a) => predicate(a) ? a : onFalse(a);
|
|
146
|
+
const either$1 = (predicate, onTrue, onFalse) => (a) => predicate(a) ? onTrue(a) : onFalse(a);
|
|
147
|
+
const struct$1 = (fields) => (a) => {
|
|
148
|
+
const result = {};
|
|
149
|
+
for (const key of Object.keys(fields)) result[key] = fields[key](a);
|
|
150
|
+
return result;
|
|
137
151
|
};
|
|
138
|
-
function safe(...fns) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
return result;
|
|
151
|
-
};
|
|
152
|
+
function safe$1(...fns) {
|
|
153
|
+
return (a) => {
|
|
154
|
+
let result = a;
|
|
155
|
+
if (result === null || result === void 0) return result;
|
|
156
|
+
for (const fn of fns) {
|
|
157
|
+
result = fn(result);
|
|
158
|
+
if (result === null || result === void 0) return result;
|
|
159
|
+
}
|
|
160
|
+
return result;
|
|
161
|
+
};
|
|
152
162
|
}
|
|
153
|
-
function async(...fns) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return result;
|
|
160
|
-
};
|
|
163
|
+
function async$2(...fns) {
|
|
164
|
+
return async (a) => {
|
|
165
|
+
let result = await a;
|
|
166
|
+
for (const fn of fns) result = await fn(result);
|
|
167
|
+
return result;
|
|
168
|
+
};
|
|
161
169
|
}
|
|
162
|
-
flow.when = when;
|
|
163
|
-
flow.unless = unless;
|
|
164
|
-
flow.either = either;
|
|
165
|
-
flow.struct = struct;
|
|
166
|
-
flow.safe = safe;
|
|
167
|
-
flow.async = async;
|
|
170
|
+
flow.when = when$1;
|
|
171
|
+
flow.unless = unless$1;
|
|
172
|
+
flow.either = either$1;
|
|
173
|
+
flow.struct = struct$1;
|
|
174
|
+
flow.safe = safe$1;
|
|
175
|
+
flow.async = async$2;
|
|
168
176
|
flow.try = (f, onError) => (a) => {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
177
|
+
try {
|
|
178
|
+
return f(a);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
return onError(error, a);
|
|
181
|
+
}
|
|
174
182
|
};
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/Composition/fn.ts
|
|
185
|
+
/**
|
|
186
|
+
* Returns the value unchanged. The identity function.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```ts
|
|
190
|
+
* identity(42); // 42
|
|
191
|
+
* pipe(Maybe.make.some(5), Maybe.fold(() => 0, identity)); // 5
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
const identity = (a) => a;
|
|
195
|
+
/**
|
|
196
|
+
* Creates a function that always returns the given value, ignoring its argument.
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```ts
|
|
200
|
+
* const always42 = constant(42);
|
|
201
|
+
* always42(); // 42
|
|
202
|
+
* [1, 2, 3].map(constant("x")); // ["x", "x", "x"]
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
const constant = (a) => () => a;
|
|
206
|
+
/**
|
|
207
|
+
* Always returns `true`.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```ts
|
|
211
|
+
* constTrue(); // true
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
const constTrue = () => true;
|
|
215
|
+
/**
|
|
216
|
+
* Always returns `false`.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```ts
|
|
220
|
+
* constFalse(); // false
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
const constFalse = () => false;
|
|
224
|
+
/**
|
|
225
|
+
* Always returns `null`.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* ```ts
|
|
229
|
+
* constNull(); // null
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
232
|
+
const constNull = () => null;
|
|
233
|
+
/**
|
|
234
|
+
* Always returns `undefined`.
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```ts
|
|
238
|
+
* constUndefined(); // undefined
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
const constUndefined = () => void 0;
|
|
242
|
+
/**
|
|
243
|
+
* Always returns `void`.
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* ```ts
|
|
247
|
+
* constVoid(); // undefined
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
const constVoid = () => {};
|
|
251
|
+
/**
|
|
252
|
+
* Combines two predicates with logical AND.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```ts
|
|
256
|
+
* const isPositive = (n: number) => n > 0;
|
|
257
|
+
* const isEven = (n: number) => n % 2 === 0;
|
|
258
|
+
* const isPositiveEven = and(isPositive, isEven);
|
|
259
|
+
*
|
|
260
|
+
* isPositiveEven(4); // true
|
|
261
|
+
* isPositiveEven(-2); // false
|
|
262
|
+
* isPositiveEven(3); // false
|
|
263
|
+
* ```
|
|
264
|
+
*/
|
|
265
|
+
const and = (p1, p2) => (...args) => p1(...args) && p2(...args);
|
|
266
|
+
/**
|
|
267
|
+
* Combines two predicates with logical OR.
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```ts
|
|
271
|
+
* const isNegative = (n: number) => n < 0;
|
|
272
|
+
* const isZero = (n: number) => n === 0;
|
|
273
|
+
* const isNonPositive = or(isNegative, isZero);
|
|
274
|
+
*
|
|
275
|
+
* isNonPositive(-1); // true
|
|
276
|
+
* isNonPositive(0); // true
|
|
277
|
+
* isNonPositive(1); // false
|
|
278
|
+
* ```
|
|
279
|
+
*/
|
|
280
|
+
const or = (p1, p2) => (...args) => p1(...args) || p2(...args);
|
|
281
|
+
/**
|
|
282
|
+
* Creates a function that executes at most once.
|
|
283
|
+
* Subsequent calls return the cached result from the first execution.
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* ```ts
|
|
287
|
+
* let count = 0;
|
|
288
|
+
* const initOnce = once(() => { count++; return "initialized"; });
|
|
289
|
+
*
|
|
290
|
+
* initOnce(); // "initialized", count === 1
|
|
291
|
+
* initOnce(); // "initialized", count === 1 (not called again)
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
const once = (f) => {
|
|
295
|
+
let called = false;
|
|
296
|
+
let result;
|
|
297
|
+
return () => {
|
|
298
|
+
if (!called) {
|
|
299
|
+
result = f();
|
|
300
|
+
called = true;
|
|
301
|
+
}
|
|
302
|
+
return result;
|
|
303
|
+
};
|
|
184
304
|
};
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
305
|
+
/**
|
|
306
|
+
* Returns a fallback value if the input is null or undefined; otherwise returns the input value.
|
|
307
|
+
* Highly useful as a data-last default value step inside pipelines.
|
|
308
|
+
*
|
|
309
|
+
* @example
|
|
310
|
+
* ```ts
|
|
311
|
+
* const getName = flow(
|
|
312
|
+
* (u: { name?: string | null }) => u.name,
|
|
313
|
+
* defaultTo("Guest"),
|
|
314
|
+
* (name: string) => name.toUpperCase()
|
|
315
|
+
* ); // returns string
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
318
|
+
const defaultTo = (fallback) => (a) => a === null || a === void 0 ? fallback : a;
|
|
319
|
+
/**
|
|
320
|
+
* Converts a function taking multiple arguments into a function taking a single tuple argument.
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```ts
|
|
324
|
+
* const add = (a: number, b: number) => a + b;
|
|
325
|
+
* const addTuple = tuple(add);
|
|
326
|
+
* addTuple([2, 3]); // 5
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
const tuple = (f) => (args) => f(...args);
|
|
330
|
+
/**
|
|
331
|
+
* Converts a function taking a single tuple argument into a function taking multiple arguments.
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* ```ts
|
|
335
|
+
* const addTuple = ([a, b]: readonly [number, number]) => a + b;
|
|
336
|
+
* const add = untuple(addTuple);
|
|
337
|
+
* add(2, 3); // 5
|
|
338
|
+
* ```
|
|
339
|
+
*/
|
|
340
|
+
const untuple = (f) => (...args) => f(args);
|
|
341
|
+
//#endregion
|
|
342
|
+
//#region src/Composition/juxt.ts
|
|
203
343
|
function juxt(fns) {
|
|
204
|
-
|
|
344
|
+
return (a) => fns.map((f) => f(a));
|
|
205
345
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
346
|
+
//#endregion
|
|
347
|
+
//#region src/Composition/memoize.ts
|
|
348
|
+
/**
|
|
349
|
+
* Creates a memoized version of a function that caches results.
|
|
350
|
+
* Subsequent calls with the same argument return the cached result.
|
|
351
|
+
*
|
|
352
|
+
* By default, uses the argument directly as the cache key.
|
|
353
|
+
* For complex arguments, provide a custom `keyFn` to generate cache keys.
|
|
354
|
+
*
|
|
355
|
+
* @example
|
|
356
|
+
* ```ts
|
|
357
|
+
* // Basic usage
|
|
358
|
+
* const expensive = memoize((n: number) => {
|
|
359
|
+
* console.log("Computing...");
|
|
360
|
+
* return n * 2;
|
|
361
|
+
* });
|
|
362
|
+
*
|
|
363
|
+
* expensive(5); // logs "Computing...", returns 10
|
|
364
|
+
* expensive(5); // returns 10 (cached, no log)
|
|
365
|
+
* expensive(3); // logs "Computing...", returns 6
|
|
366
|
+
*
|
|
367
|
+
* // With custom key function for objects
|
|
368
|
+
* const fetchUser = memoize(
|
|
369
|
+
* (opts: { id: string }) => fetch(`/users/${opts.id}`),
|
|
370
|
+
* { key: (opts) => opts.id }
|
|
371
|
+
* );
|
|
372
|
+
* // With bounded cache size (LRU eviction)
|
|
373
|
+
* const bounded = memoize(
|
|
374
|
+
* (n: number) => n * 2,
|
|
375
|
+
* { maxSize: 100 }
|
|
376
|
+
* );
|
|
377
|
+
* ```
|
|
378
|
+
*/
|
|
379
|
+
const memoize = (f, options) => {
|
|
380
|
+
const cache = /* @__PURE__ */ new Map();
|
|
381
|
+
const keyFn = options?.key ?? ((a) => a);
|
|
382
|
+
const maxSize = options?.maxSize;
|
|
383
|
+
return (a) => {
|
|
384
|
+
const key = keyFn(a);
|
|
385
|
+
if (cache.has(key)) {
|
|
386
|
+
const cached = cache.get(key);
|
|
387
|
+
if (maxSize !== void 0) {
|
|
388
|
+
cache.delete(key);
|
|
389
|
+
cache.set(key, cached);
|
|
390
|
+
}
|
|
391
|
+
return cached;
|
|
392
|
+
}
|
|
393
|
+
const result = f(a);
|
|
394
|
+
cache.set(key, result);
|
|
395
|
+
if (maxSize !== void 0 && cache.size > maxSize) for (const k of cache.keys()) {
|
|
396
|
+
cache.delete(k);
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
return result;
|
|
400
|
+
};
|
|
232
401
|
};
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
402
|
+
/**
|
|
403
|
+
* Creates a memoized version of a function using WeakMap.
|
|
404
|
+
* Only works with object arguments, but allows garbage collection
|
|
405
|
+
* of cached values when keys are no longer referenced.
|
|
406
|
+
*
|
|
407
|
+
* @example
|
|
408
|
+
* ```ts
|
|
409
|
+
* type User = { id: number; name: string };
|
|
410
|
+
* const expensiveOperation = (u: User) => u.name.toUpperCase();
|
|
411
|
+
*
|
|
412
|
+
* const processUser = memoizeWeak((user: User) => {
|
|
413
|
+
* return expensiveOperation(user);
|
|
414
|
+
* });
|
|
415
|
+
*
|
|
416
|
+
* const user = { id: 1, name: "Alice" };
|
|
417
|
+
* processUser(user); // computed
|
|
418
|
+
* processUser(user); // cached
|
|
419
|
+
* // When `user` is garbage collected, cached result is too
|
|
420
|
+
* ```
|
|
421
|
+
*/
|
|
422
|
+
const memoizeWeak = (f) => {
|
|
423
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
424
|
+
return (a) => {
|
|
425
|
+
if (cache.has(a)) return cache.get(a);
|
|
426
|
+
const result = f(a);
|
|
427
|
+
cache.set(a, result);
|
|
428
|
+
return result;
|
|
429
|
+
};
|
|
243
430
|
};
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
431
|
+
//#endregion
|
|
432
|
+
//#region src/Composition/not.ts
|
|
433
|
+
/**
|
|
434
|
+
* Negates a predicate function.
|
|
435
|
+
* Returns a new predicate that returns true when the original returns false, and vice versa.
|
|
436
|
+
*
|
|
437
|
+
* @example
|
|
438
|
+
* ```ts
|
|
439
|
+
* const isEven = (n: number) => n % 2 === 0;
|
|
440
|
+
* const isOdd = not(isEven);
|
|
441
|
+
*
|
|
442
|
+
* isOdd(3); // true
|
|
443
|
+
* isOdd(4); // false
|
|
444
|
+
*
|
|
445
|
+
* // With array methods
|
|
446
|
+
* const numbers = [1, 2, 3, 4, 5];
|
|
447
|
+
* numbers.filter(not(isEven)); // [1, 3, 5]
|
|
448
|
+
*
|
|
449
|
+
* // In pipelines
|
|
450
|
+
* const users = [{ name: "Alice", isAdmin: false }, { name: "Bob", isAdmin: true }];
|
|
451
|
+
* const isAdmin = (u: { name: string; isAdmin: boolean }) => u.isAdmin;
|
|
452
|
+
* pipe(
|
|
453
|
+
* users,
|
|
454
|
+
* Arr.filter(not(isAdmin)),
|
|
455
|
+
* Arr.map((u: { name: string; isAdmin: boolean }) => u.name)
|
|
456
|
+
* );
|
|
457
|
+
* ```
|
|
458
|
+
*/
|
|
459
|
+
const not = (predicate) => (...args) => !predicate(...args);
|
|
460
|
+
//#endregion
|
|
461
|
+
//#region src/Composition/on.ts
|
|
462
|
+
/**
|
|
463
|
+
* Applies a projection to both arguments of a binary function before calling it.
|
|
464
|
+
* Most useful for building comparators and equality checks over projected values.
|
|
465
|
+
*
|
|
466
|
+
* @example
|
|
467
|
+
* ```ts
|
|
468
|
+
* const byLength = on((a: number, b: number) => a - b, (s: string) => s.length);
|
|
469
|
+
*
|
|
470
|
+
* ["banana", "fig", "apple"].sort(byLength); // ["fig", "apple", "banana"]
|
|
471
|
+
* ```
|
|
472
|
+
*/
|
|
473
|
+
const on = (f, g) => (a, b) => f(g(a), g(b));
|
|
474
|
+
//#endregion
|
|
475
|
+
//#region src/Composition/pipe.ts
|
|
252
476
|
function pipe(a, ab, bc, cd, de, ef, fg, gh, hi, ij, jk) {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
case 5: {
|
|
267
|
-
return de(cd(bc(ab(a))));
|
|
268
|
-
}
|
|
269
|
-
case 6: {
|
|
270
|
-
return ef(de(cd(bc(ab(a)))));
|
|
271
|
-
}
|
|
272
|
-
case 7: {
|
|
273
|
-
return fg(ef(de(cd(bc(ab(a))))));
|
|
274
|
-
}
|
|
275
|
-
case 8: {
|
|
276
|
-
return gh(fg(ef(de(cd(bc(ab(a)))))));
|
|
277
|
-
}
|
|
278
|
-
case 9: {
|
|
279
|
-
return hi(gh(fg(ef(de(cd(bc(ab(a))))))));
|
|
280
|
-
}
|
|
281
|
-
case 10: {
|
|
282
|
-
return ij(hi(gh(fg(ef(de(cd(bc(ab(a)))))))));
|
|
283
|
-
}
|
|
284
|
-
case 11: {
|
|
285
|
-
return jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))));
|
|
286
|
-
}
|
|
287
|
-
}
|
|
477
|
+
switch (arguments.length) {
|
|
478
|
+
case 1: return a;
|
|
479
|
+
case 2: return ab(a);
|
|
480
|
+
case 3: return bc(ab(a));
|
|
481
|
+
case 4: return cd(bc(ab(a)));
|
|
482
|
+
case 5: return de(cd(bc(ab(a))));
|
|
483
|
+
case 6: return ef(de(cd(bc(ab(a)))));
|
|
484
|
+
case 7: return fg(ef(de(cd(bc(ab(a))))));
|
|
485
|
+
case 8: return gh(fg(ef(de(cd(bc(ab(a)))))));
|
|
486
|
+
case 9: return hi(gh(fg(ef(de(cd(bc(ab(a))))))));
|
|
487
|
+
case 10: return ij(hi(gh(fg(ef(de(cd(bc(ab(a)))))))));
|
|
488
|
+
case 11: return jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))));
|
|
489
|
+
}
|
|
288
490
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
return result;
|
|
491
|
+
const when = (predicate, onTrue) => (a) => predicate(a) ? onTrue(a) : a;
|
|
492
|
+
const unless = (predicate, onFalse) => (a) => predicate(a) ? a : onFalse(a);
|
|
493
|
+
const either = (predicate, onTrue, onFalse) => (a) => predicate(a) ? onTrue(a) : onFalse(a);
|
|
494
|
+
const struct = (fields) => (a) => {
|
|
495
|
+
const result = {};
|
|
496
|
+
for (const key of Object.keys(fields)) result[key] = fields[key](a);
|
|
497
|
+
return result;
|
|
298
498
|
};
|
|
299
|
-
function
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
return result;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
return result;
|
|
499
|
+
function safe(a, ...fns) {
|
|
500
|
+
let result = a;
|
|
501
|
+
if (result === null || result === void 0) return result;
|
|
502
|
+
for (const fn of fns) {
|
|
503
|
+
result = fn(result);
|
|
504
|
+
if (result === null || result === void 0) return result;
|
|
505
|
+
}
|
|
506
|
+
return result;
|
|
311
507
|
}
|
|
312
|
-
async function
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
return result;
|
|
508
|
+
async function async$1(a, ...fns) {
|
|
509
|
+
let result = await a;
|
|
510
|
+
for (const fn of fns) result = await fn(result);
|
|
511
|
+
return result;
|
|
318
512
|
}
|
|
319
|
-
pipe.when =
|
|
320
|
-
pipe.unless =
|
|
321
|
-
pipe.either =
|
|
322
|
-
pipe.struct =
|
|
323
|
-
pipe.safe =
|
|
324
|
-
pipe.async =
|
|
513
|
+
pipe.when = when;
|
|
514
|
+
pipe.unless = unless;
|
|
515
|
+
pipe.either = either;
|
|
516
|
+
pipe.struct = struct;
|
|
517
|
+
pipe.safe = safe;
|
|
518
|
+
pipe.async = async$1;
|
|
325
519
|
pipe.try = (f, onError) => (a) => {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
// src/Composition/tap.ts
|
|
334
|
-
import { inspect as nodeInspect } from "util";
|
|
335
|
-
|
|
336
|
-
// src/Types/Brand.ts
|
|
337
|
-
var Brand = {
|
|
338
|
-
/**
|
|
339
|
-
* Returns a constructor that wraps a value of type T in brand K.
|
|
340
|
-
* The resulting function performs an unchecked cast — only use when the raw
|
|
341
|
-
* value is known to satisfy the brand's invariants.
|
|
342
|
-
*
|
|
343
|
-
* @example
|
|
344
|
-
* ```ts
|
|
345
|
-
* type PositiveNumber = Brand<"PositiveNumber", number>;
|
|
346
|
-
* const toPositiveNumber = Brand.wrap<"PositiveNumber", number>();
|
|
347
|
-
*
|
|
348
|
-
* const n: PositiveNumber = toPositiveNumber(42);
|
|
349
|
-
* ```
|
|
350
|
-
*/
|
|
351
|
-
wrap: () => (value) => value,
|
|
352
|
-
/**
|
|
353
|
-
* Strips the brand and returns the underlying value.
|
|
354
|
-
* Since Brand<K, T> extends T this is rarely needed, but can improve readability.
|
|
355
|
-
*
|
|
356
|
-
* @example
|
|
357
|
-
* ```ts
|
|
358
|
-
* type UserId = Brand<"UserId", string>;
|
|
359
|
-
* const toUserId = Brand.wrap<"UserId", string>();
|
|
360
|
-
* const userId: UserId = toUserId("user-123");
|
|
361
|
-
* const raw: string = Brand.unwrap(userId); // "user-123"
|
|
362
|
-
* ```
|
|
363
|
-
*/
|
|
364
|
-
unwrap: (branded) => branded
|
|
520
|
+
try {
|
|
521
|
+
return f(a);
|
|
522
|
+
} catch (error) {
|
|
523
|
+
return onError(error, a);
|
|
524
|
+
}
|
|
365
525
|
};
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
*
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* Creates a Duration from hours.
|
|
399
|
-
*
|
|
400
|
-
* @example
|
|
401
|
-
* ```ts
|
|
402
|
-
* Duration.hours(1); // 3600000ms Duration
|
|
403
|
-
* ```
|
|
404
|
-
*/
|
|
405
|
-
hours: (h) => wrap(h * 60 * 60 * 1e3),
|
|
406
|
-
/**
|
|
407
|
-
* Creates a Duration from days.
|
|
408
|
-
*
|
|
409
|
-
* @example
|
|
410
|
-
* ```ts
|
|
411
|
-
* Duration.days(1); // 86400000ms Duration
|
|
412
|
-
* ```
|
|
413
|
-
*/
|
|
414
|
-
days: (d) => wrap(d * 24 * 60 * 60 * 1e3),
|
|
415
|
-
// --- to ---
|
|
416
|
-
to: {
|
|
417
|
-
/**
|
|
418
|
-
* Converts a Duration back to raw milliseconds.
|
|
419
|
-
*
|
|
420
|
-
* @example
|
|
421
|
-
* ```ts
|
|
422
|
-
* Duration.to.milliseconds(Duration.seconds(2)); // 2000
|
|
423
|
-
* ```
|
|
424
|
-
*/
|
|
425
|
-
milliseconds: (d) => Brand.unwrap(d),
|
|
426
|
-
/**
|
|
427
|
-
* Converts a Duration to seconds.
|
|
428
|
-
*
|
|
429
|
-
* @example
|
|
430
|
-
* ```ts
|
|
431
|
-
* Duration.to.seconds(Duration.milliseconds(2500)); // 2.5
|
|
432
|
-
* ```
|
|
433
|
-
*/
|
|
434
|
-
seconds: (d) => Brand.unwrap(d) / 1e3,
|
|
435
|
-
/**
|
|
436
|
-
* Converts a Duration to minutes.
|
|
437
|
-
*
|
|
438
|
-
* @example
|
|
439
|
-
* ```ts
|
|
440
|
-
* Duration.to.minutes(Duration.seconds(120)); // 2
|
|
441
|
-
* ```
|
|
442
|
-
*/
|
|
443
|
-
minutes: (d) => Brand.unwrap(d) / (60 * 1e3),
|
|
444
|
-
/**
|
|
445
|
-
* Converts a Duration to hours.
|
|
446
|
-
*
|
|
447
|
-
* @example
|
|
448
|
-
* ```ts
|
|
449
|
-
* Duration.to.hours(Duration.minutes(90)); // 1.5
|
|
450
|
-
* ```
|
|
451
|
-
*/
|
|
452
|
-
hours: (d) => Brand.unwrap(d) / (60 * 60 * 1e3),
|
|
453
|
-
/**
|
|
454
|
-
* Converts a Duration to days.
|
|
455
|
-
*
|
|
456
|
-
* @example
|
|
457
|
-
* ```ts
|
|
458
|
-
* Duration.to.days(Duration.hours(36)); // 1.5
|
|
459
|
-
* ```
|
|
460
|
-
*/
|
|
461
|
-
days: (d) => Brand.unwrap(d) / (24 * 60 * 60 * 1e3)
|
|
462
|
-
},
|
|
463
|
-
/**
|
|
464
|
-
* Adds two Durations together.
|
|
465
|
-
*
|
|
466
|
-
* @example
|
|
467
|
-
* ```ts
|
|
468
|
-
* pipe(Duration.seconds(1), Duration.add(Duration.milliseconds(500))); // 1500ms
|
|
469
|
-
* ```
|
|
470
|
-
*/
|
|
471
|
-
add: (other) => (self) => wrap(Brand.unwrap(self) + Brand.unwrap(other)),
|
|
472
|
-
/**
|
|
473
|
-
* Subtracts the other Duration from this one.
|
|
474
|
-
*
|
|
475
|
-
* @example
|
|
476
|
-
* ```ts
|
|
477
|
-
* pipe(Duration.seconds(1), Duration.subtract(Duration.milliseconds(500))); // 500ms
|
|
478
|
-
* ```
|
|
479
|
-
*/
|
|
480
|
-
subtract: (other) => (self) => wrap(Brand.unwrap(self) - Brand.unwrap(other))
|
|
481
|
-
};
|
|
482
|
-
|
|
483
|
-
// src/Composition/tap.ts
|
|
526
|
+
//#endregion
|
|
527
|
+
//#region src/Composition/tap.ts
|
|
528
|
+
/**
|
|
529
|
+
* Executes a side effect function and returns the original value unchanged.
|
|
530
|
+
* Useful for logging, debugging, or other side effects within a pipeline.
|
|
531
|
+
*
|
|
532
|
+
* @example
|
|
533
|
+
* ```ts
|
|
534
|
+
* // Debugging a pipeline
|
|
535
|
+
* pipe(
|
|
536
|
+
* Maybe.make.some(5),
|
|
537
|
+
* tap(x => console.log("Before map:", x)),
|
|
538
|
+
* Maybe.map(n => n * 2),
|
|
539
|
+
* tap(x => console.log("After map:", x)),
|
|
540
|
+
* Maybe.getOrElse(() => 0)
|
|
541
|
+
* );
|
|
542
|
+
* // logs: "Before map: { kind: 'Some', value: 5 }"
|
|
543
|
+
* // logs: "After map: { kind: 'Some', value: 10 }"
|
|
544
|
+
* // returns: 10
|
|
545
|
+
*
|
|
546
|
+
* // Collecting intermediate values
|
|
547
|
+
* const values: number[] = [];
|
|
548
|
+
* pipe(
|
|
549
|
+
* [1, 2, 3],
|
|
550
|
+
* arr => arr.map(n => n * 2),
|
|
551
|
+
* tap(arr => values.push(...arr))
|
|
552
|
+
* );
|
|
553
|
+
* ```
|
|
554
|
+
*
|
|
555
|
+
* @see {@link Maybe.tap} for Maybe-specific tap that only runs on Some
|
|
556
|
+
*/
|
|
484
557
|
function tap(f) {
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
558
|
+
return (a) => {
|
|
559
|
+
f(a);
|
|
560
|
+
return a;
|
|
561
|
+
};
|
|
489
562
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
563
|
+
/**
|
|
564
|
+
* Logs the piped value to the console or a custom logger, returning the value unchanged.
|
|
565
|
+
*
|
|
566
|
+
* @example
|
|
567
|
+
* ```ts
|
|
568
|
+
* pipe(
|
|
569
|
+
* 42,
|
|
570
|
+
* tap.log(), // logs: 42
|
|
571
|
+
* tap.log({ label: "Count" }) // logs: [Count]: 42
|
|
572
|
+
* );
|
|
573
|
+
* ```
|
|
574
|
+
*/
|
|
575
|
+
const log = (options) => (a) => {
|
|
576
|
+
const logger = options?.logger ?? console.log;
|
|
577
|
+
const formatted = (options?.formatter ?? ((val) => {
|
|
578
|
+
try {
|
|
579
|
+
return typeof val === "object" && val !== null ? JSON.stringify(val) : String(val);
|
|
580
|
+
} catch {
|
|
581
|
+
return String(val);
|
|
582
|
+
}
|
|
583
|
+
}))(a);
|
|
584
|
+
if (options?.label !== void 0) logger(`[${options.label}]: ${formatted}`);
|
|
585
|
+
else logger(formatted);
|
|
586
|
+
return a;
|
|
506
587
|
};
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
588
|
+
/**
|
|
589
|
+
* Performs a deep structured inspect formatting on the piped value, returning it unchanged.
|
|
590
|
+
* In Node.js environments, this utilizes Node's `node:util` `inspect` utility.
|
|
591
|
+
*
|
|
592
|
+
* @example
|
|
593
|
+
* ```ts
|
|
594
|
+
* pipe(
|
|
595
|
+
* { user: { name: "Alice", details: { age: 30 } } },
|
|
596
|
+
* tap.inspect({ label: "User Object", depth: 2 })
|
|
597
|
+
* );
|
|
598
|
+
* ```
|
|
599
|
+
*/
|
|
600
|
+
const inspect$1 = (options) => (a) => {
|
|
601
|
+
const label = options?.label;
|
|
602
|
+
const depth = options?.depth ?? null;
|
|
603
|
+
const colors = options?.colors ?? true;
|
|
604
|
+
let formatted;
|
|
605
|
+
if (typeof inspect === "function") formatted = inspect(a, {
|
|
606
|
+
depth,
|
|
607
|
+
colors
|
|
608
|
+
});
|
|
609
|
+
else try {
|
|
610
|
+
formatted = JSON.stringify(a, null, 2);
|
|
611
|
+
} catch {
|
|
612
|
+
formatted = String(a);
|
|
613
|
+
}
|
|
614
|
+
if (label !== void 0) console.log(`[${label}]: ${formatted}`);
|
|
615
|
+
else console.log(formatted);
|
|
616
|
+
return a;
|
|
527
617
|
};
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
618
|
+
/**
|
|
619
|
+
* Triggers a fire-and-forget asynchronous side effect in the background,
|
|
620
|
+
* returning the piped value immediately and synchronously.
|
|
621
|
+
* Any errors thrown by the async function are caught and forwarded to `onError`.
|
|
622
|
+
*
|
|
623
|
+
* @example
|
|
624
|
+
* ```ts
|
|
625
|
+
* const user = { id: 1 };
|
|
626
|
+
* const saveToDatabase = async (u: typeof user) => {};
|
|
627
|
+
* const logError = (err: unknown) => console.error(err);
|
|
628
|
+
*
|
|
629
|
+
* pipe(
|
|
630
|
+
* user,
|
|
631
|
+
* tap.async(async (u) => {
|
|
632
|
+
* await saveToDatabase(u);
|
|
633
|
+
* }, { onError: (err) => logError(err) })
|
|
634
|
+
* );
|
|
635
|
+
* ```
|
|
636
|
+
*/
|
|
637
|
+
const async = (fn, options) => (a) => {
|
|
638
|
+
const onError = options?.onError ?? console.error;
|
|
639
|
+
Promise.resolve(fn(a)).catch((err) => {
|
|
640
|
+
onError(err);
|
|
641
|
+
});
|
|
642
|
+
return a;
|
|
534
643
|
};
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
644
|
+
/**
|
|
645
|
+
* Runs a function and measures its execution duration, returning the value unchanged.
|
|
646
|
+
* Supports both synchronous and asynchronous functions. If the timed function returns
|
|
647
|
+
* a Promise, duration measurement resolves asynchronously upon resolution/rejection.
|
|
648
|
+
*
|
|
649
|
+
* @example
|
|
650
|
+
* ```ts
|
|
651
|
+
* const data = [1, 2, 3];
|
|
652
|
+
* const processData = (d: typeof data) => d.map(n => n * 2);
|
|
653
|
+
* const fetchData = async (d: typeof data) => d.length;
|
|
654
|
+
* const metrics = { histogram: (name: string, ms: number) => {} };
|
|
655
|
+
*
|
|
656
|
+
* // Time a synchronous computation
|
|
657
|
+
* pipe(
|
|
658
|
+
* data,
|
|
659
|
+
* tap.time(processData, { label: "sync-process" })
|
|
660
|
+
* );
|
|
661
|
+
*
|
|
662
|
+
* // Time an asynchronous fetch with custom metrics callback
|
|
663
|
+
* pipe(
|
|
664
|
+
* data,
|
|
665
|
+
* tap.time(fetchData, {
|
|
666
|
+
* onFinish: (dur) => metrics.histogram("api.time", Duration.to.milliseconds(dur))
|
|
667
|
+
* })
|
|
668
|
+
* );
|
|
669
|
+
* ```
|
|
670
|
+
*/
|
|
671
|
+
const time = (fn, config) => (a) => {
|
|
672
|
+
const start = performance.now();
|
|
673
|
+
const triggerFinish = (duration) => {
|
|
674
|
+
if (config.label !== void 0) console.log(`[${config.label}]: ${Duration.to.milliseconds(duration)}ms`);
|
|
675
|
+
else config.onFinish(duration);
|
|
676
|
+
};
|
|
677
|
+
try {
|
|
678
|
+
const res = fn(a);
|
|
679
|
+
if (res !== null && (typeof res === "object" || typeof res === "function") && typeof res.then === "function") res.then(() => {
|
|
680
|
+
const duration = Duration.milliseconds(performance.now() - start);
|
|
681
|
+
triggerFinish(duration);
|
|
682
|
+
}, () => {
|
|
683
|
+
const duration = Duration.milliseconds(performance.now() - start);
|
|
684
|
+
triggerFinish(duration);
|
|
685
|
+
});
|
|
686
|
+
else triggerFinish(Duration.milliseconds(performance.now() - start));
|
|
687
|
+
} catch (err) {
|
|
688
|
+
triggerFinish(Duration.milliseconds(performance.now() - start));
|
|
689
|
+
throw err;
|
|
690
|
+
}
|
|
691
|
+
return a;
|
|
564
692
|
};
|
|
565
693
|
tap.log = log;
|
|
566
|
-
tap.inspect = inspect;
|
|
567
|
-
tap.async =
|
|
694
|
+
tap.inspect = inspect$1;
|
|
695
|
+
tap.async = async;
|
|
568
696
|
tap.time = time;
|
|
569
|
-
|
|
570
|
-
|
|
697
|
+
//#endregion
|
|
698
|
+
//#region src/Composition/uncurry.ts
|
|
571
699
|
function uncurry(f) {
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
700
|
+
return (...args) => {
|
|
701
|
+
const inner = f(...args.slice(0, f.length));
|
|
702
|
+
return inner.length === 0 ? inner() : inner(...args.slice(f.length));
|
|
703
|
+
};
|
|
576
704
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
once,
|
|
602
|
-
or,
|
|
603
|
-
pipe,
|
|
604
|
-
tap,
|
|
605
|
-
tuple,
|
|
606
|
-
uncurry,
|
|
607
|
-
uncurry3,
|
|
608
|
-
uncurry4,
|
|
609
|
-
untuple
|
|
610
|
-
};
|
|
705
|
+
/**
|
|
706
|
+
* Converts a curried 3-argument function into a multi-argument function.
|
|
707
|
+
*
|
|
708
|
+
* @example
|
|
709
|
+
* ```ts
|
|
710
|
+
* const curriedAdd3 = (a: number) => (b: number) => (c: number) => a + b + c;
|
|
711
|
+
* const add3 = uncurry3(curriedAdd3);
|
|
712
|
+
* add3(1, 2, 3); // 6
|
|
713
|
+
* ```
|
|
714
|
+
*/
|
|
715
|
+
const uncurry3 = (f) => (a, b, c) => f(a)(b)(c);
|
|
716
|
+
/**
|
|
717
|
+
* Converts a curried 4-argument function into a multi-argument function.
|
|
718
|
+
*
|
|
719
|
+
* @example
|
|
720
|
+
* ```ts
|
|
721
|
+
* const curriedAdd4 = (a: number) => (b: number) => (c: number) => (d: number) => a + b + c + d;
|
|
722
|
+
* const add4 = uncurry4(curriedAdd4);
|
|
723
|
+
* add4(1, 2, 3, 4); // 10
|
|
724
|
+
* ```
|
|
725
|
+
*/
|
|
726
|
+
const uncurry4 = (f) => (a, b, c, d) => f(a)(b)(c)(d);
|
|
727
|
+
//#endregion
|
|
728
|
+
export { and, compose, constFalse, constNull, constTrue, constUndefined, constVoid, constant, converge, curry, curry3, curry4, defaultTo, flip, flow, identity, juxt, memoize, memoizeWeak, not, on, once, or, pipe, tap, tuple, uncurry, uncurry3, uncurry4, untuple };
|