@nlozgachev/pipelined 0.46.0 → 0.48.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,6 +1,7 @@
1
- import { a as NonEmptyArr, N as NonEmpty } from './InternalTypes-CLE7qlOc.mjs';
2
- import { M as Maybe, R as Result, E as Equality, b as Ordering, T as Task } from './Validation-v38R0qH-.mjs';
3
- import { Brand } from './types.mjs';
1
+ import { a as NonEmptyArr, N as NonEmpty } from './InternalTypes-CDiDBAY4.mjs';
2
+ import { M as Maybe, R as Result, E as Equality, b as Ordering, T as Task } from './Validation-D-aARYlP.mjs';
3
+ import { B as Brand } from './Duration-B8joKzro.mjs';
4
+ import './types.mjs';
4
5
 
5
6
  declare namespace ArrTaskResult {
6
7
  /**
@@ -14,12 +15,12 @@ declare namespace ArrTaskResult {
14
15
  *
15
16
  * pipe(
16
17
  * [1, 2, 3],
17
- * Arr.Task.Result.traverse(validate)
18
+ * Arr.traverse.Task.Result(validate)
18
19
  * )(); // Deferred<Ok([1, 2, 3])>
19
20
  *
20
21
  * pipe(
21
22
  * [1, -1, 3],
22
- * Arr.Task.Result.traverse(validate)
23
+ * Arr.traverse.Task.Result(validate)
23
24
  * )(); // Deferred<Err("non-positive")>
24
25
  * ```
25
26
  */
@@ -27,6 +28,14 @@ declare namespace ArrTaskResult {
27
28
  /**
28
29
  * Collects an array of Task.Results into a Task.Result of array.
29
30
  * Returns the first Err if any element is Err, runs sequentially.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * pipe(
35
+ * [Task.Result.ok(1), Task.Result.ok(2)],
36
+ * Arr.sequence.Task.Result
37
+ * )(); // Deferred<Ok([1, 2])>
38
+ * ```
30
39
  */
31
40
  const sequence: <E, A>(data: readonly Task<Result<E, A>>[]) => Task<Result<E, readonly A[]>>;
32
41
  }
@@ -84,7 +93,7 @@ declare namespace ArrNonEmpty {
84
93
  *
85
94
  * @example
86
95
  * ```ts
87
- * pipe([1, 2, 3, 4] as NonEmptyArr<number>, Arr.NonEmpty.reduce((a, b) => a + b)); // 10
96
+ * pipe([1, 2, 3, 4] as Arr.NonEmpty<number>, Arr.NonEmpty.reduce((a: number, b: number) => a + b)); // 10
88
97
  * ```
89
98
  */
90
99
  const reduce: <A>(f: (acc: A, a: A) => A) => (data: NonEmptyArr<A>) => A;
@@ -383,6 +392,8 @@ declare namespace Arr {
383
392
  * ```ts
384
393
  * pipe([3, 1, 2], Arr.sortWith(Ordering.number)); // [1, 2, 3]
385
394
  *
395
+ * type Product = { price: number };
396
+ * const products: Product[] = [{ price: 20 }, { price: 10 }];
386
397
  * const byPrice = pipe(Ordering.number, Ordering.by((p: Product) => p.price));
387
398
  * pipe(products, Arr.sortWith(byPrice));
388
399
  * ```
@@ -402,7 +413,7 @@ declare namespace Arr {
402
413
  *
403
414
  * @example
404
415
  * ```ts
405
- * pipe([1, 2], Arr.zipWith((a, b) => a + b, ["a", "b"])); // ["1a", "2b"]
416
+ * pipe([1, 2], Arr.zipWith((a: number, b: string) => `${a}${b}`)(["a", "b"])); // ["1a", "2b"]
406
417
  * ```
407
418
  */
408
419
  export const zipWith: <A, B, C>(f: (a: A, b: B) => C) => (other: readonly B[]) => (data: readonly A[]) => readonly C[];
@@ -481,10 +492,22 @@ declare namespace Arr {
481
492
  export namespace is {
482
493
  /**
483
494
  * Returns true if the array is empty.
495
+ *
496
+ * @example
497
+ * ```ts
498
+ * Arr.is.empty([]); // true
499
+ * Arr.is.empty([1]); // false
500
+ * ```
484
501
  */
485
502
  const empty: <A>(data: readonly A[]) => data is readonly [];
486
503
  /**
487
504
  * Returns true if the array is non-empty (type guard).
505
+ *
506
+ * @example
507
+ * ```ts
508
+ * Arr.is.nonEmpty([1, 2]); // true
509
+ * Arr.is.nonEmpty([]); // false
510
+ * ```
488
511
  */
489
512
  const nonEmpty: <A>(data: readonly A[]) => data is NonEmpty<A>;
490
513
  }
@@ -508,6 +531,11 @@ declare namespace Arr {
508
531
  export const append: <A>(value: A) => (data: readonly A[]) => NonEmpty<A>;
509
532
  /**
510
533
  * Returns the length of an array.
534
+ *
535
+ * @example
536
+ * ```ts
537
+ * Arr.size([1, 2, 3]); // 3
538
+ * ```
511
539
  */
512
540
  export const size: <A>(data: readonly A[]) => number;
513
541
  /**
@@ -619,10 +647,257 @@ declare namespace Arr {
619
647
  * ```
620
648
  */
621
649
  export const splitAt: (index: number) => <A>(data: readonly A[]) => readonly [readonly A[], readonly A[]];
650
+ /**
651
+ * Partitions an array by applying a function returning `Maybe<B>`.
652
+ * Elements returning `None` are gathered into `failures` (original `A` values);
653
+ * elements returning `Some(b)` are gathered into `successes` (`B` values).
654
+ *
655
+ * @example
656
+ * ```ts
657
+ * const parseNumber = (s: string) => isNaN(Number(s)) ? Maybe.make.none() : Maybe.make.some(Number(s));
658
+ * pipe(["1", "abc", "3"], Arr.partitionMaybe(parseNumber)); // [["abc"], [1, 3]]
659
+ * ```
660
+ */
661
+ export const partitionMaybe: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => readonly [failures: readonly A[], successes: readonly B[]];
662
+ /**
663
+ * Safely looks up an element by index. Supports negative indices counting back from the end.
664
+ * Returns `None` if the index is out of bounds.
665
+ *
666
+ * @example
667
+ * ```ts
668
+ * pipe([10, 20, 30], Arr.at(1)); // Some(20)
669
+ * pipe([10, 20, 30], Arr.at(-1)); // Some(30)
670
+ * pipe([10, 20, 30], Arr.at(5)); // None
671
+ * ```
672
+ */
673
+ export const at: (index: number) => <A>(data: readonly A[]) => Maybe<A>;
674
+ /**
675
+ * Finds the first element in an array for which `f` returns `Some(b)`.
676
+ *
677
+ * @example
678
+ * ```ts
679
+ * pipe(
680
+ * ["1", "a", "2"],
681
+ * Arr.findMap((s) => isNaN(Number(s)) ? Maybe.make.none() : Maybe.make.some(Number(s)))
682
+ * ); // Some(1)
683
+ * ```
684
+ */
685
+ export const findMap: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => Maybe<B>;
686
+ /**
687
+ * Indexes elements of an array into a `ReadonlyMap<K, A>` using a key extraction function.
688
+ *
689
+ * @example
690
+ * ```ts
691
+ * pipe(
692
+ * [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }],
693
+ * Arr.indexBy((u) => u.id)
694
+ * ); // ReadonlyMap { 1 => { id: 1, name: "Alice" }, 2 => { id: 2, name: "Bob" } }
695
+ * ```
696
+ */
697
+ export const indexBy: <A, K>(keyFn: (a: A) => K) => (data: readonly A[]) => ReadonlyMap<K, A>;
698
+ /**
699
+ * Counts occurrences of each element in an array, returning a `ReadonlyMap<A, number>`.
700
+ *
701
+ * @example
702
+ * ```ts
703
+ * Arr.frequencies(["a", "b", "a", "c", "b", "a"]);
704
+ * // ReadonlyMap { "a" => 3, "b" => 2, "c" => 1 }
705
+ * ```
706
+ */
707
+ export const frequencies: <A>(data: readonly A[]) => ReadonlyMap<A, number>;
708
+ /**
709
+ * Groups consecutive elements that share the same key returned by `keyFn`.
710
+ *
711
+ * @example
712
+ * ```ts
713
+ * pipe(
714
+ * [1, 1, 2, 3, 3, 1],
715
+ * Arr.chunkBy((n) => n)
716
+ * ); // [[1, 1], [2], [3, 3], [1]]
717
+ * ```
718
+ */
719
+ export const chunkBy: <A, K>(keyFn: (a: A) => K) => (data: readonly A[]) => readonly (readonly A[])[];
720
+ /**
721
+ * Removes consecutive duplicate elements.
722
+ * An optional `Equality<A>` can be provided (defaults to `Object.is`).
723
+ *
724
+ * @example
725
+ * ```ts
726
+ * Arr.dedupeAdjacent()([1, 1, 2, 2, 1, 3]); // [1, 2, 1, 3]
727
+ * ```
728
+ */
729
+ export const dedupeAdjacent: <A>(eq?: Equality<A>) => (data: readonly A[]) => readonly A[];
730
+ /**
731
+ * Produces a sliding window of `size` elements over an array, advancing by `step` (default `1`).
732
+ * Returns an empty array if `size <= 0` or `size > data.length`.
733
+ *
734
+ * @example
735
+ * ```ts
736
+ * pipe([1, 2, 3, 4], Arr.windowed(2)); // [[1, 2], [2, 3], [3, 4]]
737
+ * pipe([1, 2, 3, 4], Arr.windowed(2, { step: 2 })); // [[1, 2], [3, 4]]
738
+ * ```
739
+ */
740
+ export const windowed: (size: number, options?: {
741
+ step?: number;
742
+ }) => <A>(data: readonly A[]) => readonly (readonly A[])[];
743
+ /**
744
+ * Generates an array from an initial seed state until `f` returns `None`.
745
+ *
746
+ * @example
747
+ * ```ts
748
+ * Arr.unfold(1, (n) => n > 3 ? Maybe.make.none() : Maybe.make.some([n, n + 1]));
749
+ * // [1, 2, 3]
750
+ * ```
751
+ */
752
+ export const unfold: <A, S>(initial: S, f: (state: S) => Maybe<readonly [A, S]>) => readonly A[];
622
753
  export const NonEmpty: typeof ArrNonEmpty;
623
754
  export { };
624
755
  }
625
756
 
757
+ /**
758
+ * Safe conversion and arithmetic utilities for arbitrary-precision integers (`bigint`).
759
+ * All functions are pure and data-last to compose cleanly with `pipe`.
760
+ *
761
+ * @example
762
+ * ```ts
763
+ * import { BigNum } from "@nlozgachev/pipelined/data";
764
+ * import { pipe } from "@nlozgachev/pipelined/composition";
765
+ *
766
+ * const result = pipe(
767
+ * BigNum.from.string("100"),
768
+ * Maybe.map(BigNum.add(50n))
769
+ * ); // Some(150n)
770
+ * ```
771
+ */
772
+ declare namespace BigNum {
773
+ namespace from {
774
+ /**
775
+ * Safely parses a string into a `bigint`. Returns `None` if parsing fails.
776
+ *
777
+ * @example
778
+ * ```ts
779
+ * BigNum.from.string("123"); // Some(123n)
780
+ * BigNum.from.string("abc"); // None
781
+ * ```
782
+ */
783
+ const string: (s: string) => Maybe<bigint>;
784
+ /**
785
+ * Safely converts a number into a `bigint`. Returns `None` for floats, `NaN`, or non-safe integers.
786
+ *
787
+ * @example
788
+ * ```ts
789
+ * BigNum.from.number(42); // Some(42n)
790
+ * BigNum.from.number(3.14); // None
791
+ * ```
792
+ */
793
+ const number: (n: number) => Maybe<bigint>;
794
+ }
795
+ namespace to {
796
+ /**
797
+ * Safely converts a `bigint` to a `number`. Returns `None` if the value is outside JavaScript's safe integer range.
798
+ *
799
+ * @example
800
+ * ```ts
801
+ * BigNum.to.number(42n); // Some(42)
802
+ * BigNum.to.number(9007199254740993n); // None
803
+ * ```
804
+ */
805
+ const number: (b: bigint) => Maybe<number>;
806
+ }
807
+ /**
808
+ * Adds `b` to `a`. Data-last curried signature: `add(b)(a)` = `a + b`.
809
+ *
810
+ * @example
811
+ * ```ts
812
+ * pipe(10n, BigNum.add(5n)); // 15n
813
+ * ```
814
+ */
815
+ const add: (b: bigint) => (a: bigint) => bigint;
816
+ /**
817
+ * Subtracts `b` from `a`. Data-last curried signature: `sub(b)(a)` = `a - b`.
818
+ *
819
+ * @example
820
+ * ```ts
821
+ * pipe(10n, BigNum.sub(3n)); // 7n
822
+ * ```
823
+ */
824
+ const sub: (b: bigint) => (a: bigint) => bigint;
825
+ /**
826
+ * Multiplies `a` by `b`. Data-last curried signature: `mul(b)(a)` = `a * b`.
827
+ *
828
+ * @example
829
+ * ```ts
830
+ * pipe(6n, BigNum.mul(7n)); // 42n
831
+ * ```
832
+ */
833
+ const mul: (b: bigint) => (a: bigint) => bigint;
834
+ /**
835
+ * Divides `a` by `b`. Returns `None` if `b` is `0n`.
836
+ *
837
+ * @example
838
+ * ```ts
839
+ * pipe(20n, BigNum.div(4n)); // Some(5n)
840
+ * pipe(5n, BigNum.div(0n)); // None
841
+ * ```
842
+ */
843
+ const div: (b: bigint) => (a: bigint) => Maybe<bigint>;
844
+ /**
845
+ * Computes remainder of `a / b`. Returns `None` if `b` is `0n`.
846
+ *
847
+ * @example
848
+ * ```ts
849
+ * pipe(10n, BigNum.mod(3n)); // Some(1n)
850
+ * pipe(5n, BigNum.mod(0n)); // None
851
+ * ```
852
+ */
853
+ const mod: (b: bigint) => (a: bigint) => Maybe<bigint>;
854
+ /**
855
+ * Clamps `a` between `min` and `max` (inclusive).
856
+ *
857
+ * @example
858
+ * ```ts
859
+ * pipe(150n, BigNum.clamp(0n, 100n)); // 100n
860
+ * ```
861
+ */
862
+ const clamp: (min: bigint, max: bigint) => (a: bigint) => bigint;
863
+ /**
864
+ * Returns `true` if `a` is in the range `[start, end)` (inclusive start, exclusive end).
865
+ *
866
+ * @example
867
+ * ```ts
868
+ * pipe(5n, BigNum.inRange(1n, 10n)); // true
869
+ * ```
870
+ */
871
+ const inRange: (start: bigint, end: bigint) => (a: bigint) => boolean;
872
+ /**
873
+ * Returns absolute value of a `bigint`.
874
+ *
875
+ * @example
876
+ * ```ts
877
+ * BigNum.abs(-42n); // 42n
878
+ * ```
879
+ */
880
+ const abs: (a: bigint) => bigint;
881
+ /**
882
+ * Returns the minimum of `a` and `b`.
883
+ *
884
+ * @example
885
+ * ```ts
886
+ * pipe(10n, BigNum.min(5n)); // 5n
887
+ * ```
888
+ */
889
+ const min: (b: bigint) => (a: bigint) => bigint;
890
+ /**
891
+ * Returns the maximum of `a` and `b`.
892
+ *
893
+ * @example
894
+ * ```ts
895
+ * pipe(10n, BigNum.max(5n)); // 10n
896
+ * ```
897
+ */
898
+ const max: (b: bigint) => (a: bigint) => bigint;
899
+ }
900
+
626
901
  /**
627
902
  * A branded type representing a key-value dictionary with at least one entry.
628
903
  */
@@ -743,6 +1018,12 @@ declare namespace Dict {
743
1018
  const empty: <K, V>(m: ReadonlyMap<K, V>) => boolean;
744
1019
  /**
745
1020
  * Type guard to check if a dictionary is non-empty.
1021
+ *
1022
+ * @example
1023
+ * ```ts
1024
+ * Dict.is.nonEmpty(Dict.from.entries([["a", 1]])); // true
1025
+ * Dict.is.nonEmpty(Dict.empty()); // false
1026
+ * ```
746
1027
  */
747
1028
  const nonEmpty: <K, V>(m: ReadonlyMap<K, V>) => m is NonEmpty<K, V>;
748
1029
  }
@@ -804,8 +1085,8 @@ declare namespace Dict {
804
1085
  *
805
1086
  * @example
806
1087
  * ```ts
807
- * pipe(Dict.from.Entries([["a", 1]]), Dict.has("a")); // true
808
- * pipe(Dict.from.Entries([["a", 1]]), Dict.has("b")); // false
1088
+ * pipe(Dict.from.entries([["a", 1]]), Dict.has("a")); // true
1089
+ * pipe(Dict.from.entries([["a", 1]]), Dict.has("b")); // false
809
1090
  * ```
810
1091
  */
811
1092
  const has: <K>(key: K) => <V>(m: ReadonlyMap<K, V>) => boolean;
@@ -814,8 +1095,8 @@ declare namespace Dict {
814
1095
  *
815
1096
  * @example
816
1097
  * ```ts
817
- * pipe(Dict.from.Entries([["a", 1]]), Dict.lookup("a")); // Some(1)
818
- * pipe(Dict.from.Entries([["a", 1]]), Dict.lookup("b")); // None
1098
+ * pipe(Dict.from.entries([["a", 1]]), Dict.lookup("a")); // Some(1)
1099
+ * pipe(Dict.from.entries([["a", 1]]), Dict.lookup("b")); // None
819
1100
  * ```
820
1101
  */
821
1102
  const lookup: <K>(key: K) => <V>(m: ReadonlyMap<K, V>) => Maybe<V>;
@@ -824,7 +1105,7 @@ declare namespace Dict {
824
1105
  *
825
1106
  * @example
826
1107
  * ```ts
827
- * Dict.size(Dict.from.Entries([["a", 1], ["b", 2]])); // 2
1108
+ * Dict.size(Dict.from.entries([["a", 1], ["b", 2]])); // 2
828
1109
  * ```
829
1110
  */
830
1111
  const size: <K, V>(m: ReadonlyMap<K, V>) => number;
@@ -833,7 +1114,7 @@ declare namespace Dict {
833
1114
  *
834
1115
  * @example
835
1116
  * ```ts
836
- * Dict.keys(Dict.from.Entries([["a", 1], ["b", 2]])); // ["a", "b"]
1117
+ * Dict.keys(Dict.from.entries([["a", 1], ["b", 2]])); // ["a", "b"]
837
1118
  * ```
838
1119
  */
839
1120
  const keys: <K, V>(m: ReadonlyMap<K, V>) => readonly K[];
@@ -842,7 +1123,7 @@ declare namespace Dict {
842
1123
  *
843
1124
  * @example
844
1125
  * ```ts
845
- * Dict.values(Dict.from.Entries([["a", 1], ["b", 2]])); // [1, 2]
1126
+ * Dict.values(Dict.from.entries([["a", 1], ["b", 2]])); // [1, 2]
846
1127
  * ```
847
1128
  */
848
1129
  const values: <K, V>(m: ReadonlyMap<K, V>) => readonly V[];
@@ -851,7 +1132,7 @@ declare namespace Dict {
851
1132
  *
852
1133
  * @example
853
1134
  * ```ts
854
- * Dict.entries(Dict.from.Entries([["a", 1], ["b", 2]])); // [["a", 1], ["b", 2]]
1135
+ * Dict.entries(Dict.from.entries([["a", 1], ["b", 2]])); // [["a", 1], ["b", 2]]
855
1136
  * ```
856
1137
  */
857
1138
  const entries: <K, V>(m: ReadonlyMap<K, V>) => readonly (readonly [K, V])[];
@@ -861,7 +1142,7 @@ declare namespace Dict {
861
1142
  *
862
1143
  * @example
863
1144
  * ```ts
864
- * pipe(Dict.from.Entries([["a", 1]]), Dict.insert("b", 2));
1145
+ * pipe(Dict.from.entries([["a", 1]]), Dict.insert("b", 2));
865
1146
  * // ReadonlyMap { "a" => 1, "b" => 2 }
866
1147
  * ```
867
1148
  */
@@ -872,7 +1153,7 @@ declare namespace Dict {
872
1153
  *
873
1154
  * @example
874
1155
  * ```ts
875
- * pipe(Dict.from.Entries([["a", 1], ["b", 2]]), Dict.remove("a"));
1156
+ * pipe(Dict.from.entries([["a", 1], ["b", 2]]), Dict.remove("a"));
876
1157
  * // ReadonlyMap { "b" => 2 }
877
1158
  * ```
878
1159
  */
@@ -885,11 +1166,9 @@ declare namespace Dict {
885
1166
  *
886
1167
  * @example
887
1168
  * ```ts
888
- * import { Maybe } from "@nlozgachev/pipelined/core";
889
- *
890
- * const increment = (opt: Maybe<number>) => Maybe.getOrElse(() => 0)(opt) + 1;
891
- * pipe(Dict.from.Entries([["views", 5]]), Dict.upsert("views", increment)); // { views: 6 }
892
- * pipe(Dict.from.Entries([["views", 5]]), Dict.upsert("likes", increment)); // { views: 5, likes: 1 }
1169
+ * const increment = (opt: Maybe<number>) => pipe(opt, Maybe.getOrElse(() => 0)) + 1;
1170
+ * pipe(Dict.from.entries([["views", 5]]), Dict.upsert("views", increment)); // { views: 6 }
1171
+ * pipe(Dict.from.entries([["views", 5]]), Dict.upsert("likes", increment)); // { views: 5, likes: 1 }
893
1172
  * ```
894
1173
  */
895
1174
  const upsert: <K, V>(key: K, f: (existing: Maybe<V>) => V) => (m: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
@@ -898,7 +1177,7 @@ declare namespace Dict {
898
1177
  *
899
1178
  * @example
900
1179
  * ```ts
901
- * pipe(Dict.from.Entries([["a", 1], ["b", 2]]), Dict.map(n => n * 2));
1180
+ * pipe(Dict.from.entries([["a", 1], ["b", 2]]), Dict.map(n => n * 2));
902
1181
  * // ReadonlyMap { "a" => 2, "b" => 4 }
903
1182
  * ```
904
1183
  */
@@ -908,7 +1187,7 @@ declare namespace Dict {
908
1187
  *
909
1188
  * @example
910
1189
  * ```ts
911
- * pipe(Dict.from.Entries([["a", 1], ["b", 2]]), Dict.mapWithKey((k, v) => `${k}:${v}`));
1190
+ * pipe(Dict.from.entries([["a", 1], ["b", 2]]), Dict.mapWithKey((k, v) => `${k}:${v}`));
912
1191
  * // ReadonlyMap { "a" => "a:1", "b" => "b:2" }
913
1192
  * ```
914
1193
  */
@@ -918,7 +1197,7 @@ declare namespace Dict {
918
1197
  *
919
1198
  * @example
920
1199
  * ```ts
921
- * pipe(Dict.from.Entries([["a", 1], ["b", 3], ["c", 0]]), Dict.filter(n => n > 0));
1200
+ * pipe(Dict.from.entries([["a", 1], ["b", 3], ["c", 0]]), Dict.filter(n => n > 0));
922
1201
  * // ReadonlyMap { "a" => 1, "b" => 3 }
923
1202
  * ```
924
1203
  */
@@ -929,7 +1208,7 @@ declare namespace Dict {
929
1208
  *
930
1209
  * @example
931
1210
  * ```ts
932
- * pipe(Dict.from.Entries([["a", 1], ["b", 2]]), Dict.filterWithKey((k, v) => k !== "a" && v > 0));
1211
+ * pipe(Dict.from.entries([["a", 1], ["b", 2]]), Dict.filterWithKey((k, v) => k !== "a" && v > 0));
933
1212
  * // ReadonlyMap { "b" => 2 }
934
1213
  * ```
935
1214
  */
@@ -940,9 +1219,7 @@ declare namespace Dict {
940
1219
  *
941
1220
  * @example
942
1221
  * ```ts
943
- * import { Maybe } from "@nlozgachev/pipelined/core";
944
- *
945
- * Dict.compact(Dict.from.Entries([
1222
+ * Dict.compact(Dict.from.entries<string, Maybe<number>>([
946
1223
  * ["a", Maybe.make.some(1)],
947
1224
  * ["b", Maybe.make.none()],
948
1225
  * ["c", Maybe.make.some(3)],
@@ -973,8 +1250,8 @@ declare namespace Dict {
973
1250
  * @example
974
1251
  * ```ts
975
1252
  * pipe(
976
- * Dict.from.Entries([["a", 1], ["b", 2]]),
977
- * Dict.union(Dict.from.Entries([["b", 3], ["c", 4]])),
1253
+ * Dict.from.entries([["a", 1], ["b", 2]]),
1254
+ * Dict.union(Dict.from.entries([["b", 3], ["c", 4]])),
978
1255
  * );
979
1256
  * // ReadonlyMap { "a" => 1, "b" => 3, "c" => 4 }
980
1257
  * ```
@@ -987,8 +1264,8 @@ declare namespace Dict {
987
1264
  * @example
988
1265
  * ```ts
989
1266
  * pipe(
990
- * Dict.from.Entries([["a", 1], ["b", 2], ["c", 3]]),
991
- * Dict.intersection(Dict.from.Entries([["b", 99], ["c", 0]])),
1267
+ * Dict.from.entries([["a", 1], ["b", 2], ["c", 3]]),
1268
+ * Dict.intersection(Dict.from.entries([["b", 99], ["c", 0]])),
992
1269
  * );
993
1270
  * // ReadonlyMap { "b" => 2, "c" => 3 }
994
1271
  * ```
@@ -1000,8 +1277,8 @@ declare namespace Dict {
1000
1277
  * @example
1001
1278
  * ```ts
1002
1279
  * pipe(
1003
- * Dict.from.Entries([["a", 1], ["b", 2], ["c", 3]]),
1004
- * Dict.difference(Dict.from.Entries([["b", 0]])),
1280
+ * Dict.from.entries([["a", 1], ["b", 2], ["c", 3]]),
1281
+ * Dict.difference(Dict.from.entries([["b", 0]])),
1005
1282
  * );
1006
1283
  * // ReadonlyMap { "a" => 1, "c" => 3 }
1007
1284
  * ```
@@ -1013,8 +1290,8 @@ declare namespace Dict {
1013
1290
  *
1014
1291
  * @example
1015
1292
  * ```ts
1016
- * Dict.reduce(0, (acc, value) => acc + value)(
1017
- * Dict.from.Entries([["a", 1], ["b", 2], ["c", 3]])
1293
+ * Dict.reduce(0, (acc, value: number) => acc + value)(
1294
+ * Dict.from.entries([["a", 1], ["b", 2], ["c", 3]])
1018
1295
  * ); // 6
1019
1296
  * ```
1020
1297
  */
@@ -1026,25 +1303,105 @@ declare namespace Dict {
1026
1303
  * @example
1027
1304
  * ```ts
1028
1305
  * Dict.reduceWithKey("", (acc, value, key) => acc + key + ":" + value + " ")(
1029
- * Dict.from.Entries([["a", 1], ["b", 2]])
1306
+ * Dict.from.entries([["a", 1], ["b", 2]])
1030
1307
  * ); // "a:1 b:2 "
1031
1308
  * ```
1032
1309
  */
1033
1310
  const reduceWithKey: <K, A, B>(init: B, f: (acc: B, value: A, key: K) => B) => (m: ReadonlyMap<K, A>) => B;
1311
+ /**
1312
+ * Merges two maps using a custom combination function on key collisions.
1313
+ * Supports both uncurried `Dict.mergeWith(combine)(first, second)` and curried `pipe(first, Dict.mergeWith(combine)(second))`.
1314
+ *
1315
+ * @example
1316
+ * ```ts
1317
+ * const combineStats = Dict.mergeWith((a: number, b: number) => a + b);
1318
+ * const map1 = Dict.from.entries([["a", 1], ["b", 2]]);
1319
+ * const map2 = Dict.from.entries([["b", 3], ["c", 4]]);
1320
+ * combineStats(map1, map2);
1321
+ * pipe(map1, combineStats(map2));
1322
+ * ```
1323
+ */
1324
+ function mergeWith<K, V>(combine: (a: V, b: V) => V): {
1325
+ (second: ReadonlyMap<K, V>): (first: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
1326
+ (first: ReadonlyMap<K, V>, second: ReadonlyMap<K, V>): ReadonlyMap<K, V>;
1327
+ };
1034
1328
  namespace to {
1035
1329
  /**
1036
1330
  * Converts a `ReadonlyMap<string, V>` to a plain object. Only meaningful when keys are strings.
1037
1331
  *
1038
1332
  * @example
1039
1333
  * ```ts
1040
- * Dict.to.Record(Dict.from.Entries([["a", 1], ["b", 2]])); // { a: 1, b: 2 }
1334
+ * Dict.to.Record(Dict.from.entries([["a", 1], ["b", 2]])); // { a: 1, b: 2 }
1041
1335
  * ```
1042
1336
  */
1043
1337
  const Record: <V>(m: ReadonlyMap<string, V>) => Readonly<Record<string, V>>;
1044
1338
  }
1339
+ /**
1340
+ * Transforms key and value pairs simultaneously into a new ReadonlyMap.
1341
+ *
1342
+ * @example
1343
+ * ```ts
1344
+ * pipe(
1345
+ * Dict.from.entries([["a", 1], ["b", 2]]),
1346
+ * Dict.mapEntries((k, v) => [k.toUpperCase(), v * 10])
1347
+ * ); // Map { "A" => 10, "B" => 20 }
1348
+ * ```
1349
+ */
1350
+ const mapEntries: <K1, V1, K2, V2>(f: (key: K1, value: V1) => readonly [K2, V2]) => (data: ReadonlyMap<K1, V1>) => ReadonlyMap<K2, V2>;
1351
+ /**
1352
+ * Transforms keys of a ReadonlyMap while preserving values.
1353
+ *
1354
+ * @example
1355
+ * ```ts
1356
+ * pipe(
1357
+ * Dict.from.entries([["a", 1], ["b", 2]]),
1358
+ * Dict.mapKeys((k) => k.toUpperCase())
1359
+ * ); // Map { "A" => 1, "B" => 2 }
1360
+ * ```
1361
+ */
1362
+ const mapKeys: <K1, K2, V>(f: (key: K1) => K2) => (data: ReadonlyMap<K1, V>) => ReadonlyMap<K2, V>;
1045
1363
  const NonEmpty: typeof DictNonEmpty;
1046
1364
  }
1047
1365
 
1366
+ /**
1367
+ * Pure, non-throwing JSON utilities.
1368
+ * Wraps runtime JSON parsing and stringifying in typed `Result` containers.
1369
+ *
1370
+ * @example
1371
+ * ```ts
1372
+ * import { Json } from "@nlozgachev/pipelined/data";
1373
+ * import { pipe } from "@nlozgachev/pipelined/composition";
1374
+ *
1375
+ * const result = pipe(
1376
+ * Json.parse('{"name":"Alice"}'),
1377
+ * Result.map((data: any) => data.name)
1378
+ * ); // Ok("Alice")
1379
+ * ```
1380
+ */
1381
+ declare namespace Json {
1382
+ /**
1383
+ * Safely parses a JSON string into `unknown`.
1384
+ * Converts thrown exceptions into a `Result<SyntaxError, unknown>`.
1385
+ *
1386
+ * @example
1387
+ * ```ts
1388
+ * Json.parse('{"a": 1}'); // Ok({ a: 1 })
1389
+ * Json.parse('{invalid}'); // Err(SyntaxError)
1390
+ * ```
1391
+ */
1392
+ const parse: (text: string) => Result<SyntaxError, unknown>;
1393
+ /**
1394
+ * Safely stringifies a value into a JSON string.
1395
+ * Converts thrown exceptions (e.g. circular references) into a `Result<TypeError, string>`.
1396
+ *
1397
+ * @example
1398
+ * ```ts
1399
+ * Json.stringify({ a: 1 }); // Ok('{"a":1}')
1400
+ * ```
1401
+ */
1402
+ const stringify: (value: unknown, replacer?: (this: any, key: string, value: any) => any, space?: string | number) => Result<TypeError, string>;
1403
+ }
1404
+
1048
1405
  /**
1049
1406
  * Number utilities for common operations. All transformation functions are data-last
1050
1407
  * and curried so they compose naturally with `pipe` and `Arr.map`.
@@ -1062,6 +1419,102 @@ declare namespace Dict {
1062
1419
  * ```
1063
1420
  */
1064
1421
  declare namespace Num {
1422
+ namespace is {
1423
+ /**
1424
+ * Returns `true` when the number is equal to zero.
1425
+ *
1426
+ * @example
1427
+ * ```ts
1428
+ * Num.is.zero(0); // true
1429
+ * Num.is.zero(5); // false
1430
+ * ```
1431
+ */
1432
+ const zero: (n: number) => boolean;
1433
+ /**
1434
+ * Returns `true` when the number is a whole integer.
1435
+ *
1436
+ * @example
1437
+ * ```ts
1438
+ * Num.is.integer(5); // true
1439
+ * Num.is.integer(3.14); // false
1440
+ * ```
1441
+ */
1442
+ const integer: (n: number) => boolean;
1443
+ /**
1444
+ * Returns `true` when the number is a finite float (fractional number).
1445
+ *
1446
+ * @example
1447
+ * ```ts
1448
+ * Num.is.float(3.14); // true
1449
+ * Num.is.float(5); // false
1450
+ * ```
1451
+ */
1452
+ const float: (n: number) => boolean;
1453
+ /**
1454
+ * Returns `true` when the number is finite (not `Infinity`, `-Infinity`, or `NaN`).
1455
+ *
1456
+ * @example
1457
+ * ```ts
1458
+ * Num.is.finite(42); // true
1459
+ * Num.is.finite(Infinity); // false
1460
+ * ```
1461
+ */
1462
+ const finite: (n: number) => boolean;
1463
+ /**
1464
+ * Returns `true` when the value is `NaN`.
1465
+ *
1466
+ * @example
1467
+ * ```ts
1468
+ * Num.is.nan(NaN); // true
1469
+ * Num.is.nan(42); // false
1470
+ * ```
1471
+ */
1472
+ const nan: (n: number) => boolean;
1473
+ /**
1474
+ * Returns `true` when the number is an even integer.
1475
+ *
1476
+ * @example
1477
+ * ```ts
1478
+ * Num.is.even(4); // true
1479
+ * Num.is.even(3); // false
1480
+ * Num.is.even(2.5); // false
1481
+ * ```
1482
+ */
1483
+ const even: (n: number) => boolean;
1484
+ /**
1485
+ * Returns `true` when the number is an odd integer.
1486
+ *
1487
+ * @example
1488
+ * ```ts
1489
+ * Num.is.odd(3); // true
1490
+ * Num.is.odd(4); // false
1491
+ * Num.is.odd(2.5); // false
1492
+ * ```
1493
+ */
1494
+ const odd: (n: number) => boolean;
1495
+ /**
1496
+ * Returns `true` when the number is strictly greater than zero.
1497
+ *
1498
+ * @example
1499
+ * ```ts
1500
+ * Num.is.positive(5); // true
1501
+ * Num.is.positive(0); // false
1502
+ * Num.is.positive(-5); // false
1503
+ * ```
1504
+ */
1505
+ const positive: (n: number) => boolean;
1506
+ /**
1507
+ * Returns `true` when the number is strictly less than zero.
1508
+ *
1509
+ * @example
1510
+ * ```ts
1511
+ * Num.is.negative(-5); // true
1512
+ * Num.is.negative(0); // false
1513
+ * Num.is.negative(5); // false
1514
+ * ```
1515
+ */
1516
+ const negative: (n: number) => boolean;
1517
+ }
1065
1518
  /**
1066
1519
  * Generates an array of numbers from `from` to `to` (both inclusive),
1067
1520
  * stepping by `step` (default `1`). If `step` is negative or zero, or `from > to`,
@@ -1266,6 +1719,18 @@ declare namespace Num {
1266
1719
  * ```
1267
1720
  */
1268
1721
  const max: (ns: readonly number[]) => Maybe<number>;
1722
+ /**
1723
+ * Formats a number using `Intl.NumberFormat`. Returns `None` when `n` is `NaN` or non-finite.
1724
+ * Data-last curried signature.
1725
+ *
1726
+ * @example
1727
+ * ```ts
1728
+ * const formatCurrency = Num.format({ style: "currency", currency: "USD" }, "en-US");
1729
+ * pipe(1234.5, formatCurrency); // Some("$1,234.50")
1730
+ * pipe(NaN, formatCurrency); // None
1731
+ * ```
1732
+ */
1733
+ const format: (options?: Intl.NumberFormatOptions, locales?: string | string[]) => (n: number) => Maybe<string>;
1269
1734
  }
1270
1735
 
1271
1736
  /**
@@ -1370,10 +1835,22 @@ declare namespace Rec {
1370
1835
  namespace is {
1371
1836
  /**
1372
1837
  * Returns true if the record has no keys.
1838
+ *
1839
+ * @example
1840
+ * ```ts
1841
+ * Rec.is.empty({}); // true
1842
+ * Rec.is.empty({ a: 1 }); // false
1843
+ * ```
1373
1844
  */
1374
1845
  const empty: <A>(data: Readonly<Record<string, A>>) => boolean;
1375
1846
  /**
1376
1847
  * Type guard to check if a record is non-empty.
1848
+ *
1849
+ * @example
1850
+ * ```ts
1851
+ * Rec.is.nonEmpty({ a: 1 }); // true
1852
+ * Rec.is.nonEmpty({}); // false
1853
+ * ```
1377
1854
  */
1378
1855
  const nonEmpty: <A, K extends string>(data: Readonly<Record<K, A>>) => data is NonEmptyRecord<A, K>;
1379
1856
  }
@@ -1386,6 +1863,17 @@ declare namespace Rec {
1386
1863
  * ```
1387
1864
  */
1388
1865
  const map: <A, B>(f: (a: A) => B) => <K extends string>(data: Readonly<Record<K, A>>) => Readonly<Record<K, B>>;
1866
+ /**
1867
+ * Maps each value in a record with a function returning a `Maybe`, keeping only `Some` values.
1868
+ *
1869
+ * @example
1870
+ * ```ts
1871
+ * pipe(
1872
+ * { a: 1, b: 2, c: 3 },
1873
+ * Rec.filterMap((n) => (n % 2 === 0 ? Maybe.make.some(n * 10) : Maybe.make.none()))
1874
+ * ); // { b: 20 }
1875
+ * ```
1876
+ */
1389
1877
  const filterMap: <A, B>(f: (a: A) => Maybe<B>) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, B>>;
1390
1878
  /**
1391
1879
  * Transforms each value in a record, also receiving the key.
@@ -1428,14 +1916,29 @@ declare namespace Rec {
1428
1916
  const lookup: <K extends string>(key: K) => <V>(data: Record<string, V>) => Maybe<V>;
1429
1917
  /**
1430
1918
  * Returns all keys of a record.
1919
+ *
1920
+ * @example
1921
+ * ```ts
1922
+ * Rec.keys({ a: 1, b: 2 }); // ["a", "b"]
1923
+ * ```
1431
1924
  */
1432
1925
  const keys: <T extends Record<string, unknown>>(data: T) => readonly (keyof T & string)[];
1433
1926
  /**
1434
1927
  * Returns all values of a record.
1928
+ *
1929
+ * @example
1930
+ * ```ts
1931
+ * Rec.values({ a: 1, b: 2 }); // [1, 2]
1932
+ * ```
1435
1933
  */
1436
1934
  const values: <T extends Record<string, unknown>>(data: T) => readonly T[keyof T & string][];
1437
1935
  /**
1438
1936
  * Returns all key-value pairs of a record.
1937
+ *
1938
+ * @example
1939
+ * ```ts
1940
+ * Rec.entries({ a: 1, b: 2 }); // [["a", 1], ["b", 2]]
1941
+ * ```
1439
1942
  */
1440
1943
  const entries: <T extends Record<string, unknown>>(data: T) => readonly (readonly [keyof T, T[keyof T]])[];
1441
1944
  namespace from {
@@ -1492,8 +1995,28 @@ declare namespace Rec {
1492
1995
  * ```
1493
1996
  */
1494
1997
  const merge: <A>(other: Readonly<Record<string, A>>) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
1998
+ /**
1999
+ * Merges two records using a custom combination function on key collisions.
2000
+ * Supports both uncurried `Rec.mergeWith(combine)(first, second)` and curried `pipe(first, Rec.mergeWith(combine)(second))`.
2001
+ *
2002
+ * @example
2003
+ * ```ts
2004
+ * const combineStats = Rec.mergeWith((a: number, b: number) => a + b);
2005
+ * combineStats({ a: 1, b: 2 }, { b: 3, c: 4 }); // { a: 1, b: 5, c: 4 }
2006
+ * pipe({ a: 1, b: 2 }, combineStats({ b: 3, c: 4 })); // { a: 1, b: 5, c: 4 }
2007
+ * ```
2008
+ */
2009
+ function mergeWith<A>(combine: (a: A, b: A) => A): {
2010
+ (second: Readonly<Record<string, A>>): (first: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
2011
+ (first: Readonly<Record<string, A>>, second: Readonly<Record<string, A>>): Readonly<Record<string, A>>;
2012
+ };
1495
2013
  /**
1496
2014
  * Returns the number of keys in a record.
2015
+ *
2016
+ * @example
2017
+ * ```ts
2018
+ * Rec.size({ a: 1, b: 2 }); // 2
2019
+ * ```
1497
2020
  */
1498
2021
  const size: <A>(data: Readonly<Record<string, A>>) => number;
1499
2022
  /**
@@ -1518,6 +2041,30 @@ declare namespace Rec {
1518
2041
  * ```
1519
2042
  */
1520
2043
  const compact: <A>(data: Readonly<Record<string, Maybe<A>>>) => Readonly<Record<string, A>>;
2044
+ /**
2045
+ * Transforms key and value pairs simultaneously.
2046
+ *
2047
+ * @example
2048
+ * ```ts
2049
+ * pipe(
2050
+ * { a: 1, b: 2 },
2051
+ * Rec.mapEntries((k, v) => [k.toUpperCase(), v * 10])
2052
+ * ); // { A: 10, B: 20 }
2053
+ * ```
2054
+ */
2055
+ const mapEntries: <A, K2 extends string, B>(f: (key: string, value: A) => readonly [K2, B]) => (data: Readonly<Record<string, A>>) => Readonly<Record<K2, B>>;
2056
+ /**
2057
+ * Immutably updates a value at a deep nested path inside a record.
2058
+ *
2059
+ * @example
2060
+ * ```ts
2061
+ * pipe(
2062
+ * { user: { profile: { age: 30 } } },
2063
+ * Rec.updateIn(["user", "profile", "age"], (n: number) => n + 1)
2064
+ * ); // { user: { profile: { age: 31 } } }
2065
+ * ```
2066
+ */
2067
+ const updateIn: <T>(path: readonly [string, ...string[]], f: (val: T) => T) => (data: Readonly<Record<string, unknown>>) => Readonly<Record<string, unknown>>;
1521
2068
  namespace traverse {
1522
2069
  const Maybe: <A, B>(f: (a: A) => Maybe<B>) => (data: Readonly<Record<string, A>>) => Maybe<Readonly<Record<string, B>>>;
1523
2070
  const Result: <E, A, B>(f: (a: A) => Result<E, B>) => (data: Readonly<Record<string, A>>) => Result<E, Readonly<Record<string, B>>>;
@@ -1781,6 +2328,31 @@ declare namespace Str {
1781
2328
  * ```
1782
2329
  */
1783
2330
  const parseJson: (s: string) => Result<SyntaxError, unknown>;
2331
+ /**
2332
+ * Converts the first character of a string to lower case.
2333
+ *
2334
+ * @example
2335
+ * ```ts
2336
+ * Str.uncapitalize("Hello"); // "hello"
2337
+ * Str.uncapitalize(""); // ""
2338
+ * ```
2339
+ */
2340
+ const uncapitalize: (s: string) => string;
2341
+ /**
2342
+ * Truncates a string to a maximum length, appending an optional suffix (default `"..."`).
2343
+ * Data-last curried signature.
2344
+ *
2345
+ * @example
2346
+ * ```ts
2347
+ * pipe("Hello, world!", Str.truncate({ length: 8 })); // "Hello..."
2348
+ * pipe("Hello", Str.truncate({ length: 10 })); // "Hello"
2349
+ * pipe("Hello, world!", Str.truncate({ length: 8, suffix: "…" })); // "Hello, w…"
2350
+ * ```
2351
+ */
2352
+ const truncate: (options: {
2353
+ length: number;
2354
+ suffix?: string;
2355
+ }) => (s: string) => string;
1784
2356
  const NonEmpty: typeof StrNonEmpty;
1785
2357
  }
1786
2358
 
@@ -1876,6 +2448,12 @@ declare namespace Uniq {
1876
2448
  const empty: <A>(s: ReadonlySet<A>) => boolean;
1877
2449
  /**
1878
2450
  * Type guard to check if a unique collection is non-empty.
2451
+ *
2452
+ * @example
2453
+ * ```ts
2454
+ * Uniq.is.nonEmpty(Uniq.from.Array([1, 2])); // true
2455
+ * Uniq.is.nonEmpty(Uniq.empty()); // false
2456
+ * ```
1879
2457
  */
1880
2458
  const nonEmpty: <A>(s: ReadonlySet<A>) => s is NonEmpty<A>;
1881
2459
  }
@@ -2016,7 +2594,7 @@ declare namespace Uniq {
2016
2594
  *
2017
2595
  * @example
2018
2596
  * ```ts
2019
- * Uniq.reduce(0, (acc, n) => acc + n)(Uniq.from.Array([1, 2, 3])); // 6
2597
+ * Uniq.reduce(0, (acc, n: number) => acc + n)(Uniq.from.Array([1, 2, 3])); // 6
2020
2598
  * ```
2021
2599
  */
2022
2600
  const reduce: <A, B>(init: B, f: (acc: B, a: A) => B) => (s: ReadonlySet<A>) => B;
@@ -2034,4 +2612,4 @@ declare namespace Uniq {
2034
2612
  const NonEmpty: typeof UniqNonEmpty;
2035
2613
  }
2036
2614
 
2037
- export { Arr, Dict, type NonEmptyMap, type NonEmptyRecord, type NonEmptySet, type NonEmptyString, Num, Rec, Str, Uniq };
2615
+ export { Arr, BigNum, Dict, Json, type NonEmptyMap, type NonEmptyRecord, type NonEmptySet, type NonEmptyString, Num, Rec, Str, Uniq };