@nlozgachev/pipelined 0.57.0 → 0.59.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 CHANGED
@@ -555,12 +555,12 @@ if (Result.is.ok(email)) {
555
555
  - **`@nlozgachev/pipelined/core`**: Core context containers, async runtimes, optics, and logic
556
556
  abstractions (<16 KB gzipped).
557
557
  - **`@nlozgachev/pipelined/data`**: Curried, data-last utilities for collections, numbers, strings,
558
- and JSON (<13 KB gzipped).
558
+ and JSON (<10 KB gzipped).
559
559
  - **`@nlozgachev/pipelined/composition`**: Pure higher-order function combinators (`pipe`, `flow`,
560
560
  `compose`, `curry`, `uncurry`, `converge`, `juxt`, `memoize`, `tap`, `on`, `not`, `flip`, `fn`)
561
- (<4 KB gzipped).
562
- - **`@nlozgachev/pipelined/types`**: Type-level utilities (`Brand`, `Duration`, `RetryPolicy`) (<2
563
- KB gzipped).
561
+ (<3 KB gzipped).
562
+ - **`@nlozgachev/pipelined/types`**: Type-level utilities (`Brand`, `Duration`, `RetryPolicy`) (<700
563
+ B gzipped).
564
564
 
565
565
  Every utility in the library is benchmarked against its native equivalent. While currying introduces
566
566
  a small function call overhead for composability, the library uses custom algorithms for
@@ -1,7 +1,3 @@
1
- import {
2
- Duration
3
- } from "./chunk-OIIOGDHK.js";
4
-
5
1
  // src/Composition/compose.ts
6
2
  function compose(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9) {
7
3
  const len = arguments.length;
@@ -324,6 +320,36 @@ pipe.try = (f, onError) => (a) => {
324
320
 
325
321
  // src/Composition/tap.ts
326
322
  import { inspect as nodeInspect } from "util";
323
+
324
+ // src/Types/Brand.ts
325
+ var Brand;
326
+ ((Brand2) => {
327
+ Brand2.wrap = () => (value) => value;
328
+ Brand2.unwrap = (branded) => branded;
329
+ })(Brand || (Brand = {}));
330
+
331
+ // src/Types/Duration.ts
332
+ var Duration;
333
+ ((Duration2) => {
334
+ const wrap = Brand.wrap();
335
+ Duration2.milliseconds = (ms) => wrap(ms);
336
+ Duration2.seconds = (s) => wrap(s * 1e3);
337
+ Duration2.minutes = (m) => wrap(m * 60 * 1e3);
338
+ Duration2.hours = (h) => wrap(h * 60 * 60 * 1e3);
339
+ Duration2.days = (d) => wrap(d * 24 * 60 * 60 * 1e3);
340
+ let to;
341
+ ((to2) => {
342
+ to2.milliseconds = (d) => Brand.unwrap(d);
343
+ to2.seconds = (d) => Brand.unwrap(d) / 1e3;
344
+ to2.minutes = (d) => Brand.unwrap(d) / (60 * 1e3);
345
+ to2.hours = (d) => Brand.unwrap(d) / (60 * 60 * 1e3);
346
+ to2.days = (d) => Brand.unwrap(d) / (24 * 60 * 60 * 1e3);
347
+ })(to = Duration2.to || (Duration2.to = {}));
348
+ Duration2.add = (other) => (self) => wrap(Brand.unwrap(self) + Brand.unwrap(other));
349
+ Duration2.subtract = (other) => (self) => wrap(Brand.unwrap(self) - Brand.unwrap(other));
350
+ })(Duration || (Duration = {}));
351
+
352
+ // src/Composition/tap.ts
327
353
  function tap(f) {
328
354
  return (a) => {
329
355
  f(a);
@@ -417,36 +443,35 @@ function uncurry(f) {
417
443
  }
418
444
  var uncurry3 = (f) => (a, b, c) => f(a)(b)(c);
419
445
  var uncurry4 = (f) => (a, b, c, d) => f(a)(b)(c)(d);
420
-
421
446
  export {
447
+ and,
422
448
  compose,
449
+ constFalse,
450
+ constNull,
451
+ constTrue,
452
+ constUndefined,
453
+ constVoid,
454
+ constant,
423
455
  converge,
424
456
  curry,
425
457
  curry3,
426
458
  curry4,
459
+ defaultTo,
427
460
  flip,
428
461
  flow,
429
462
  identity,
430
- constant,
431
- constTrue,
432
- constFalse,
433
- constNull,
434
- constUndefined,
435
- constVoid,
436
- and,
437
- or,
438
- once,
439
- defaultTo,
440
- tuple,
441
- untuple,
442
463
  juxt,
443
464
  memoize,
444
465
  memoizeWeak,
445
466
  not,
446
467
  on,
468
+ once,
469
+ or,
447
470
  pipe,
448
471
  tap,
472
+ tuple,
449
473
  uncurry,
450
474
  uncurry3,
451
- uncurry4
475
+ uncurry4,
476
+ untuple
452
477
  };
package/dist/core.cjs CHANGED
@@ -30,6 +30,7 @@ __export(Core_exports, {
30
30
  Op: () => Op,
31
31
  Optional: () => Optional,
32
32
  Ordering: () => Ordering,
33
+ Pair: () => Pair,
33
34
  Predicate: () => Predicate,
34
35
  Reader: () => Reader,
35
36
  Refinement: () => Refinement,
@@ -40,7 +41,6 @@ __export(Core_exports, {
40
41
  Stream: () => Stream,
41
42
  Task: () => Task,
42
43
  These: () => These,
43
- Tuple: () => Tuple,
44
44
  Validation: () => Validation
45
45
  });
46
46
  module.exports = __toCommonJS(Core_exports);
@@ -1473,6 +1473,34 @@ var Ordering;
1473
1473
  };
1474
1474
  })(Ordering || (Ordering = {}));
1475
1475
 
1476
+ // src/Core/Pair.ts
1477
+ var Pair;
1478
+ ((Pair2) => {
1479
+ let from;
1480
+ ((from2) => {
1481
+ from2.pair = (first2, second2) => [first2, second2];
1482
+ from2.array = (arr) => arr;
1483
+ })(from = Pair2.from || (Pair2.from = {}));
1484
+ Pair2.first = (p) => p[0];
1485
+ Pair2.second = (p) => p[1];
1486
+ Pair2.mapFirst = (f) => (p) => [f(p[0]), p[1]];
1487
+ Pair2.mapSecond = (f) => (p) => [p[0], f(p[1])];
1488
+ Pair2.mapBoth = (onFirst, onSecond) => (p) => [
1489
+ onFirst(p[0]),
1490
+ onSecond(p[1])
1491
+ ];
1492
+ Pair2.fold = (f) => (p) => f(p[0], p[1]);
1493
+ Pair2.swap = (p) => [p[1], p[0]];
1494
+ let to;
1495
+ ((to2) => {
1496
+ to2.Array = (p) => [...p];
1497
+ })(to = Pair2.to || (Pair2.to = {}));
1498
+ Pair2.tap = (f) => (p) => {
1499
+ f(p[0], p[1]);
1500
+ return p;
1501
+ };
1502
+ })(Pair || (Pair = {}));
1503
+
1476
1504
  // src/Core/Predicate.ts
1477
1505
  var Predicate;
1478
1506
  ((Predicate2) => {
@@ -2531,34 +2559,6 @@ var These;
2531
2559
  };
2532
2560
  })(These || (These = {}));
2533
2561
 
2534
- // src/Core/Tuple.ts
2535
- var Tuple;
2536
- ((Tuple2) => {
2537
- let from;
2538
- ((from2) => {
2539
- from2.pair = (first2, second2) => [first2, second2];
2540
- from2.array = (arr) => arr;
2541
- })(from = Tuple2.from || (Tuple2.from = {}));
2542
- Tuple2.first = (tuple) => tuple[0];
2543
- Tuple2.second = (tuple) => tuple[1];
2544
- Tuple2.mapFirst = (f) => (tuple) => [f(tuple[0]), tuple[1]];
2545
- Tuple2.mapSecond = (f) => (tuple) => [tuple[0], f(tuple[1])];
2546
- Tuple2.mapBoth = (onFirst, onSecond) => (tuple) => [
2547
- onFirst(tuple[0]),
2548
- onSecond(tuple[1])
2549
- ];
2550
- Tuple2.fold = (f) => (tuple) => f(tuple[0], tuple[1]);
2551
- Tuple2.swap = (tuple) => [tuple[1], tuple[0]];
2552
- let to;
2553
- ((to2) => {
2554
- to2.Array = (tuple) => [...tuple];
2555
- })(to = Tuple2.to || (Tuple2.to = {}));
2556
- Tuple2.tap = (f) => (tuple) => {
2557
- f(tuple[0], tuple[1]);
2558
- return tuple;
2559
- };
2560
- })(Tuple || (Tuple = {}));
2561
-
2562
2562
  // src/Core/Validation.ts
2563
2563
  var Validation;
2564
2564
  ((Validation2) => {
@@ -2676,6 +2676,7 @@ var Validation;
2676
2676
  Op,
2677
2677
  Optional,
2678
2678
  Ordering,
2679
+ Pair,
2679
2680
  Predicate,
2680
2681
  Reader,
2681
2682
  Refinement,
@@ -2686,6 +2687,5 @@ var Validation;
2686
2687
  Stream,
2687
2688
  Task,
2688
2689
  These,
2689
- Tuple,
2690
2690
  Validation
2691
2691
  });
package/dist/core.d.cts CHANGED
@@ -1327,6 +1327,148 @@ declare namespace Optional {
1327
1327
  const andThenLens: <A, B>(inner: Lens<A, B>) => <S>(outer: Optional<S, A>) => Optional<S, B>;
1328
1328
  }
1329
1329
 
1330
+ /**
1331
+ * Pair<A, B> represents a pair of two values that are always both present.
1332
+ * It is a typed alias for `readonly [A, B]`.
1333
+ *
1334
+ * Use Pair when two values always travel together through a pipeline and you
1335
+ * want to transform either or both sides without destructuring.
1336
+ *
1337
+ * @example
1338
+ * ```ts
1339
+ * import { Pair } from "@nlozgachev/pipelined/core";
1340
+ * import { pipe } from "@nlozgachev/pipelined/composition";
1341
+ *
1342
+ * const entry = Pair.from.pair("alice", 42);
1343
+ *
1344
+ * pipe(
1345
+ * entry,
1346
+ * Pair.mapFirst((name) => name.toUpperCase()),
1347
+ * Pair.mapSecond((score) => score * 2),
1348
+ * Pair.fold((name, score) => `${name}: ${score}`),
1349
+ * ); // "ALICE: 84"
1350
+ * ```
1351
+ */
1352
+ type Pair<A, B> = readonly [A, B];
1353
+ declare namespace Pair {
1354
+ namespace from {
1355
+ /**
1356
+ * Creates a Pair from two values.
1357
+ *
1358
+ * @example
1359
+ * ```ts
1360
+ * Pair.from.pair("Paris", 2_161_000); // ["Paris", 2161000]
1361
+ * ```
1362
+ */
1363
+ const pair: <A, B>(first: A, second: B) => Pair<A, B>;
1364
+ /**
1365
+ * Creates a Pair from a two-element array.
1366
+ *
1367
+ * @example
1368
+ * ```ts
1369
+ * Pair.from.array(["Paris", 2_161_000] as const); // ["Paris", 2161000]
1370
+ * ```
1371
+ */
1372
+ const array: <A, B>(arr: readonly [A, B]) => Pair<A, B>;
1373
+ }
1374
+ /**
1375
+ * Returns the first value from the pair.
1376
+ *
1377
+ * @example
1378
+ * ```ts
1379
+ * Pair.first(Pair.from.pair("Paris", 2_161_000)); // "Paris"
1380
+ * ```
1381
+ */
1382
+ const first: <A, B>(p: Pair<A, B>) => A;
1383
+ /**
1384
+ * Returns the second value from the pair.
1385
+ *
1386
+ * @example
1387
+ * ```ts
1388
+ * Pair.second(Pair.from.pair("Paris", 2_161_000)); // 2161000
1389
+ * ```
1390
+ */
1391
+ const second: <A, B>(p: Pair<A, B>) => B;
1392
+ /**
1393
+ * Transforms the first value, leaving the second unchanged.
1394
+ *
1395
+ * @example
1396
+ * ```ts
1397
+ * pipe(Pair.from.pair("alice", 42), Pair.mapFirst((s) => s.toUpperCase())); // ["ALICE", 42]
1398
+ * ```
1399
+ */
1400
+ const mapFirst: <A, C>(f: (a: A) => C) => <B>(p: Pair<A, B>) => Pair<C, B>;
1401
+ /**
1402
+ * Transforms the second value, leaving the first unchanged.
1403
+ *
1404
+ * @example
1405
+ * ```ts
1406
+ * pipe(Pair.from.pair("alice", 42), Pair.mapSecond((n) => n * 2)); // ["alice", 84]
1407
+ * ```
1408
+ */
1409
+ const mapSecond: <B, D>(f: (b: B) => D) => <A>(p: Pair<A, B>) => Pair<A, D>;
1410
+ /**
1411
+ * Transforms both values independently in a single step.
1412
+ *
1413
+ * @example
1414
+ * ```ts
1415
+ * pipe(
1416
+ * Pair.from.pair("alice", 42),
1417
+ * Pair.mapBoth(
1418
+ * (name) => name.toUpperCase(),
1419
+ * (score) => score * 2,
1420
+ * ),
1421
+ * ); // ["ALICE", 84]
1422
+ * ```
1423
+ */
1424
+ const mapBoth: <A, C, B, D>(onFirst: (a: A) => C, onSecond: (b: B) => D) => (p: Pair<A, B>) => Pair<C, D>;
1425
+ /**
1426
+ * Applies a binary function to both values, collapsing the pair into a single value.
1427
+ * Useful as the final step when consuming a pair in a pipeline.
1428
+ *
1429
+ * @example
1430
+ * ```ts
1431
+ * pipe(Pair.from.pair("Alice", 100), Pair.fold((name, score) => `${name}: ${score}`));
1432
+ * // "Alice: 100"
1433
+ * ```
1434
+ */
1435
+ const fold: <A, B, C>(f: (a: A, b: B) => C) => (p: Pair<A, B>) => C;
1436
+ /**
1437
+ * Swaps the two values: `[A, B]` becomes `[B, A]`.
1438
+ *
1439
+ * @example
1440
+ * ```ts
1441
+ * Pair.swap(Pair.from.pair("key", 1)); // [1, "key"]
1442
+ * ```
1443
+ */
1444
+ const swap: <A, B>(p: Pair<A, B>) => Pair<B, A>;
1445
+ namespace to {
1446
+ /**
1447
+ * Converts the pair to a heterogeneous readonly array `readonly (A | B)[]`.
1448
+ *
1449
+ * @example
1450
+ * ```ts
1451
+ * Pair.to.Array(Pair.from.pair("hello", 42)); // ["hello", 42]
1452
+ * ```
1453
+ */
1454
+ const Array: <A, B>(p: Pair<A, B>) => readonly (A | B)[];
1455
+ }
1456
+ /**
1457
+ * Runs a side effect with both values without changing the pair.
1458
+ * Useful for logging or debugging in the middle of a pipeline.
1459
+ *
1460
+ * @example
1461
+ * ```ts
1462
+ * pipe(
1463
+ * Pair.from.pair("Paris", 2_161_000),
1464
+ * Pair.tap((city, pop) => console.log(`${city}: ${pop}`)),
1465
+ * Pair.mapSecond((n) => n / 1_000_000),
1466
+ * ); // logs "Paris: 2161000", returns ["Paris", 2.161]
1467
+ * ```
1468
+ */
1469
+ const tap: <A, B>(f: (a: A, b: B) => void) => (p: Pair<A, B>) => Pair<A, B>;
1470
+ }
1471
+
1330
1472
  /**
1331
1473
  * A boolean-valued function over a type `A`.
1332
1474
  *
@@ -2877,146 +3019,4 @@ declare namespace These {
2877
3019
  const swap: <A, B>(data: These<A, B>) => These<B, A>;
2878
3020
  }
2879
3021
 
2880
- /**
2881
- * Tuple<A, B> represents a pair of two values that are always both present.
2882
- * It is a typed alias for `readonly [A, B]`.
2883
- *
2884
- * Use Tuple when two values always travel together through a pipeline and you
2885
- * want to transform either or both sides without destructuring.
2886
- *
2887
- * @example
2888
- * ```ts
2889
- * import { Tuple } from "@nlozgachev/pipelined/core";
2890
- * import { pipe } from "@nlozgachev/pipelined/composition";
2891
- *
2892
- * const entry = Tuple.from.pair("alice", 42);
2893
- *
2894
- * pipe(
2895
- * entry,
2896
- * Tuple.mapFirst((name) => name.toUpperCase()),
2897
- * Tuple.mapSecond((score) => score * 2),
2898
- * Tuple.fold((name, score) => `${name}: ${score}`),
2899
- * ); // "ALICE: 84"
2900
- * ```
2901
- */
2902
- type Tuple<A, B> = readonly [A, B];
2903
- declare namespace Tuple {
2904
- namespace from {
2905
- /**
2906
- * Creates a pair from two values.
2907
- *
2908
- * @example
2909
- * ```ts
2910
- * Tuple.from.pair("Paris", 2_161_000); // ["Paris", 2161000]
2911
- * ```
2912
- */
2913
- const pair: <A, B>(first: A, second: B) => Tuple<A, B>;
2914
- /**
2915
- * Creates a Tuple from a two-element array.
2916
- *
2917
- * @example
2918
- * ```ts
2919
- * Tuple.from.array(["Paris", 2_161_000] as const); // ["Paris", 2161000]
2920
- * ```
2921
- */
2922
- const array: <A, B>(arr: readonly [A, B]) => Tuple<A, B>;
2923
- }
2924
- /**
2925
- * Returns the first value from the pair.
2926
- *
2927
- * @example
2928
- * ```ts
2929
- * Tuple.first(Tuple.from.pair("Paris", 2_161_000)); // "Paris"
2930
- * ```
2931
- */
2932
- const first: <A, B>(tuple: Tuple<A, B>) => A;
2933
- /**
2934
- * Returns the second value from the pair.
2935
- *
2936
- * @example
2937
- * ```ts
2938
- * Tuple.second(Tuple.from.pair("Paris", 2_161_000)); // 2161000
2939
- * ```
2940
- */
2941
- const second: <A, B>(tuple: Tuple<A, B>) => B;
2942
- /**
2943
- * Transforms the first value, leaving the second unchanged.
2944
- *
2945
- * @example
2946
- * ```ts
2947
- * pipe(Tuple.from.pair("alice", 42), Tuple.mapFirst((s) => s.toUpperCase())); // ["ALICE", 42]
2948
- * ```
2949
- */
2950
- const mapFirst: <A, C>(f: (a: A) => C) => <B>(tuple: Tuple<A, B>) => Tuple<C, B>;
2951
- /**
2952
- * Transforms the second value, leaving the first unchanged.
2953
- *
2954
- * @example
2955
- * ```ts
2956
- * pipe(Tuple.from.pair("alice", 42), Tuple.mapSecond((n) => n * 2)); // ["alice", 84]
2957
- * ```
2958
- */
2959
- const mapSecond: <B, D>(f: (b: B) => D) => <A>(tuple: Tuple<A, B>) => Tuple<A, D>;
2960
- /**
2961
- * Transforms both values independently in a single step.
2962
- *
2963
- * @example
2964
- * ```ts
2965
- * pipe(
2966
- * Tuple.from.pair("alice", 42),
2967
- * Tuple.mapBoth(
2968
- * (name) => name.toUpperCase(),
2969
- * (score) => score * 2,
2970
- * ),
2971
- * ); // ["ALICE", 84]
2972
- * ```
2973
- */
2974
- const mapBoth: <A, C, B, D>(onFirst: (a: A) => C, onSecond: (b: B) => D) => (tuple: Tuple<A, B>) => Tuple<C, D>;
2975
- /**
2976
- * Applies a binary function to both values, collapsing the pair into a single value.
2977
- * Useful as the final step when consuming a pair in a pipeline.
2978
- *
2979
- * @example
2980
- * ```ts
2981
- * pipe(Tuple.from.pair("Alice", 100), Tuple.fold((name, score) => `${name}: ${score}`));
2982
- * // "Alice: 100"
2983
- * ```
2984
- */
2985
- const fold: <A, B, C>(f: (a: A, b: B) => C) => (tuple: Tuple<A, B>) => C;
2986
- /**
2987
- * Swaps the two values: `[A, B]` becomes `[B, A]`.
2988
- *
2989
- * @example
2990
- * ```ts
2991
- * Tuple.swap(Tuple.from.pair("key", 1)); // [1, "key"]
2992
- * ```
2993
- */
2994
- const swap: <A, B>(tuple: Tuple<A, B>) => Tuple<B, A>;
2995
- namespace to {
2996
- /**
2997
- * Converts the pair to a heterogeneous readonly array `readonly (A | B)[]`.
2998
- *
2999
- * @example
3000
- * ```ts
3001
- * Tuple.to.Array(Tuple.from.pair("hello", 42)); // ["hello", 42]
3002
- * ```
3003
- */
3004
- const Array: <A, B>(tuple: Tuple<A, B>) => readonly (A | B)[];
3005
- }
3006
- /**
3007
- * Runs a side effect with both values without changing the pair.
3008
- * Useful for logging or debugging in the middle of a pipeline.
3009
- *
3010
- * @example
3011
- * ```ts
3012
- * pipe(
3013
- * Tuple.from.pair("Paris", 2_161_000),
3014
- * Tuple.tap((city, pop) => console.log(`${city}: ${pop}`)),
3015
- * Tuple.mapSecond((n) => n / 1_000_000),
3016
- * ); // logs "Paris: 2161000", returns ["Paris", 2.161]
3017
- * ```
3018
- */
3019
- const tap: <A, B>(f: (a: A, b: B) => void) => (tuple: Tuple<A, B>) => Tuple<A, B>;
3020
- }
3021
-
3022
- export { Combinable, Deferred, type Failure, Lazy, Lens, type Loading, Logged, Maybe, type NotAsked, Op, Optional, Predicate, Reader, Refinement, RemoteData, Resource, Result, State, Stream, type Success, Task, These, type TheseBoth, type TheseFirst, type TheseSecond, Tuple };
3022
+ export { Combinable, Deferred, type Failure, Lazy, Lens, type Loading, Logged, Maybe, type NotAsked, Op, Optional, Pair, Predicate, Reader, Refinement, RemoteData, Resource, Result, State, Stream, type Success, Task, These, type TheseBoth, type TheseFirst, type TheseSecond };