@nlozgachev/pipelined 0.64.0 → 0.65.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.
@@ -1,610 +1,728 @@
1
- // src/Composition/compose.ts
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
- const len = arguments.length;
4
- switch (len) {
5
- case 1: {
6
- return f0;
7
- }
8
- case 2: {
9
- return function() {
10
- return f0(f1.apply(this, arguments));
11
- };
12
- }
13
- case 3: {
14
- return function() {
15
- return f0(f1(f2.apply(this, arguments)));
16
- };
17
- }
18
- case 4: {
19
- return function() {
20
- return f0(f1(f2(f3.apply(this, arguments))));
21
- };
22
- }
23
- case 5: {
24
- return function() {
25
- return f0(f1(f2(f3(f4.apply(this, arguments)))));
26
- };
27
- }
28
- case 6: {
29
- return function() {
30
- return f0(f1(f2(f3(f4(f5.apply(this, arguments))))));
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
- // src/Composition/converge.ts
36
+ //#endregion
37
+ //#region src/Composition/converge.ts
57
38
  function converge(f, transformers) {
58
- return (a) => f(...transformers.map((t) => t(a)));
39
+ return (a) => f(...transformers.map((t) => t(a)));
59
40
  }
60
-
61
- // src/Composition/curry.ts
62
- var curry = (f) => (a) => (b) => f(a, b);
63
- var curry3 = (f) => (a) => (b) => (c) => f(a, b, c);
64
- var curry4 = (f) => (a) => (b) => (c) => (d) => f(a, b, c, d);
65
-
66
- // src/Composition/flip.ts
67
- var flip = (f) => (b) => (a) => f(a)(b);
68
-
69
- // src/Composition/flow.ts
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
- const len = arguments.length;
72
- switch (len) {
73
- case 0: {
74
- return function(...args) {
75
- return args[0];
76
- };
77
- }
78
- case 1: {
79
- return ab;
80
- }
81
- case 2: {
82
- return function() {
83
- return bc(ab.apply(this, arguments));
84
- };
85
- }
86
- case 3: {
87
- return function() {
88
- return cd(bc(ab.apply(this, arguments)));
89
- };
90
- }
91
- case 4: {
92
- return function() {
93
- return de(cd(bc(ab.apply(this, arguments))));
94
- };
95
- }
96
- case 5: {
97
- return function() {
98
- return ef(de(cd(bc(ab.apply(this, arguments)))));
99
- };
100
- }
101
- case 6: {
102
- return function() {
103
- return fg(ef(de(cd(bc(ab.apply(this, arguments))))));
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
- var when = (predicate, onTrue) => (a) => predicate(a) ? onTrue(a) : a;
129
- var unless = (predicate, onFalse) => (a) => predicate(a) ? a : onFalse(a);
130
- var either = (predicate, onTrue, onFalse) => (a) => predicate(a) ? onTrue(a) : onFalse(a);
131
- var struct = (fields) => (a) => {
132
- const result = {};
133
- for (const key of Object.keys(fields)) {
134
- result[key] = fields[key](a);
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
- return (a) => {
140
- let result = a;
141
- if (result === null || result === void 0) {
142
- return result;
143
- }
144
- for (const fn of fns) {
145
- result = fn(result);
146
- if (result === null || result === void 0) {
147
- return result;
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
- return async (a) => {
155
- let result = await a;
156
- for (const fn of fns) {
157
- result = await fn(result);
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
- try {
170
- return f(a);
171
- } catch (error) {
172
- return onError(error, a);
173
- }
177
+ try {
178
+ return f(a);
179
+ } catch (error) {
180
+ return onError(error, a);
181
+ }
174
182
  };
175
-
176
- // src/Composition/fn.ts
177
- var identity = (a) => a;
178
- var constant = (a) => () => a;
179
- var constTrue = () => true;
180
- var constFalse = () => false;
181
- var constNull = () => null;
182
- var constUndefined = () => void 0;
183
- var constVoid = () => {
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
- var and = (p1, p2) => (...args) => p1(...args) && p2(...args);
186
- var or = (p1, p2) => (...args) => p1(...args) || p2(...args);
187
- var once = (f) => {
188
- let called = false;
189
- let result;
190
- return () => {
191
- if (!called) {
192
- result = f();
193
- called = true;
194
- }
195
- return result;
196
- };
197
- };
198
- var defaultTo = (fallback) => (a) => a === null || a === void 0 ? fallback : a;
199
- var tuple = (f) => (args) => f(...args);
200
- var untuple = (f) => (...args) => f(args);
201
-
202
- // src/Composition/juxt.ts
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
- return (a) => fns.map((f) => f(a));
344
+ return (a) => fns.map((f) => f(a));
205
345
  }
206
-
207
- // src/Composition/memoize.ts
208
- var memoize = (f, options) => {
209
- const cache = /* @__PURE__ */ new Map();
210
- const keyFn = options?.key ?? ((a) => a);
211
- const maxSize = options?.maxSize;
212
- return (a) => {
213
- const key = keyFn(a);
214
- if (cache.has(key)) {
215
- const cached = cache.get(key);
216
- if (maxSize !== void 0) {
217
- cache.delete(key);
218
- cache.set(key, cached);
219
- }
220
- return cached;
221
- }
222
- const result = f(a);
223
- cache.set(key, result);
224
- if (maxSize !== void 0 && cache.size > maxSize) {
225
- for (const k of cache.keys()) {
226
- cache.delete(k);
227
- break;
228
- }
229
- }
230
- return result;
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
- var memoizeWeak = (f) => {
234
- const cache = /* @__PURE__ */ new WeakMap();
235
- return (a) => {
236
- if (cache.has(a)) {
237
- return cache.get(a);
238
- }
239
- const result = f(a);
240
- cache.set(a, result);
241
- return result;
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
- // src/Composition/not.ts
246
- var not = (predicate) => (...args) => !predicate(...args);
247
-
248
- // src/Composition/on.ts
249
- var on = (f, g) => (a, b) => f(g(a), g(b));
250
-
251
- // src/Composition/pipe.ts
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
- switch (arguments.length) {
254
- case 1: {
255
- return a;
256
- }
257
- case 2: {
258
- return ab(a);
259
- }
260
- case 3: {
261
- return bc(ab(a));
262
- }
263
- case 4: {
264
- return cd(bc(ab(a)));
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
- var when2 = (predicate, onTrue) => (a) => predicate(a) ? onTrue(a) : a;
290
- var unless2 = (predicate, onFalse) => (a) => predicate(a) ? a : onFalse(a);
291
- var either2 = (predicate, onTrue, onFalse) => (a) => predicate(a) ? onTrue(a) : onFalse(a);
292
- var struct2 = (fields) => (a) => {
293
- const result = {};
294
- for (const key of Object.keys(fields)) {
295
- result[key] = fields[key](a);
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 safe2(a, ...fns) {
300
- let result = a;
301
- if (result === null || result === void 0) {
302
- return result;
303
- }
304
- for (const fn of fns) {
305
- result = fn(result);
306
- if (result === null || result === void 0) {
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 async2(a, ...fns) {
313
- let result = await a;
314
- for (const fn of fns) {
315
- result = await fn(result);
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 = when2;
320
- pipe.unless = unless2;
321
- pipe.either = either2;
322
- pipe.struct = struct2;
323
- pipe.safe = safe2;
324
- pipe.async = async2;
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
- try {
327
- return f(a);
328
- } catch (error) {
329
- return onError(error, a);
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
- // src/Types/Duration.ts
368
- var wrap = Brand.wrap();
369
- var Duration = {
370
- /**
371
- * Creates a Duration from milliseconds.
372
- *
373
- * @example
374
- * ```ts
375
- * Duration.milliseconds(500); // 500ms Duration
376
- * ```
377
- */
378
- milliseconds: (ms) => wrap(ms),
379
- /**
380
- * Creates a Duration from seconds.
381
- *
382
- * @example
383
- * ```ts
384
- * Duration.seconds(2); // 2000ms Duration
385
- * ```
386
- */
387
- seconds: (s) => wrap(s * 1e3),
388
- /**
389
- * Creates a Duration from minutes.
390
- *
391
- * @example
392
- * ```ts
393
- * Duration.minutes(5); // 300000ms Duration
394
- * ```
395
- */
396
- minutes: (m) => wrap(m * 60 * 1e3),
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
- return (a) => {
486
- f(a);
487
- return a;
488
- };
558
+ return (a) => {
559
+ f(a);
560
+ return a;
561
+ };
489
562
  }
490
- var log = (options) => (a) => {
491
- const logger = options?.logger ?? console.log;
492
- const formatter = options?.formatter ?? ((val) => {
493
- try {
494
- return typeof val === "object" && val !== null ? JSON.stringify(val) : String(val);
495
- } catch {
496
- return String(val);
497
- }
498
- });
499
- const formatted = formatter(a);
500
- if (options?.label !== void 0) {
501
- logger(`[${options.label}]: ${formatted}`);
502
- } else {
503
- logger(formatted);
504
- }
505
- return a;
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
- var inspect = (options) => (a) => {
508
- const label = options?.label;
509
- const depth = options?.depth ?? null;
510
- const colors = options?.colors ?? true;
511
- let formatted;
512
- if (typeof nodeInspect === "function") {
513
- formatted = nodeInspect(a, { depth, colors });
514
- } else {
515
- try {
516
- formatted = JSON.stringify(a, null, 2);
517
- } catch {
518
- formatted = String(a);
519
- }
520
- }
521
- if (label !== void 0) {
522
- console.log(`[${label}]: ${formatted}`);
523
- } else {
524
- console.log(formatted);
525
- }
526
- return a;
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
- var async3 = (fn, options) => (a) => {
529
- const onError = options?.onError ?? console.error;
530
- Promise.resolve(fn(a)).catch((err) => {
531
- onError(err);
532
- });
533
- return a;
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
- var time = (fn, config) => (a) => {
536
- const start = performance.now();
537
- const triggerFinish = (duration) => {
538
- if (config.label !== void 0) {
539
- console.log(`[${config.label}]: ${Duration.to.milliseconds(duration)}ms`);
540
- } else {
541
- config.onFinish(duration);
542
- }
543
- };
544
- try {
545
- const res = fn(a);
546
- if (res !== null && (typeof res === "object" || typeof res === "function") && typeof res.then === "function") {
547
- res.then(() => {
548
- const duration = Duration.milliseconds(performance.now() - start);
549
- triggerFinish(duration);
550
- }, () => {
551
- const duration = Duration.milliseconds(performance.now() - start);
552
- triggerFinish(duration);
553
- });
554
- } else {
555
- const duration = Duration.milliseconds(performance.now() - start);
556
- triggerFinish(duration);
557
- }
558
- } catch (err) {
559
- const duration = Duration.milliseconds(performance.now() - start);
560
- triggerFinish(duration);
561
- throw err;
562
- }
563
- return a;
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 = async3;
694
+ tap.inspect = inspect$1;
695
+ tap.async = async;
568
696
  tap.time = time;
569
-
570
- // src/Composition/uncurry.ts
697
+ //#endregion
698
+ //#region src/Composition/uncurry.ts
571
699
  function uncurry(f) {
572
- return (...args) => {
573
- const inner = f(...args.slice(0, f.length));
574
- return inner.length === 0 ? inner() : inner(...args.slice(f.length));
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
- var uncurry3 = (f) => (a, b, c) => f(a)(b)(c);
578
- var uncurry4 = (f) => (a, b, c, d) => f(a)(b)(c)(d);
579
- export {
580
- and,
581
- compose,
582
- constFalse,
583
- constNull,
584
- constTrue,
585
- constUndefined,
586
- constVoid,
587
- constant,
588
- converge,
589
- curry,
590
- curry3,
591
- curry4,
592
- defaultTo,
593
- flip,
594
- flow,
595
- identity,
596
- juxt,
597
- memoize,
598
- memoizeWeak,
599
- not,
600
- on,
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 };