@nlozgachev/pipelined 0.63.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.
package/dist/data.d.cts CHANGED
@@ -1,144 +1,144 @@
1
- import { a as NonEmptyArr, N as NonEmpty } from './InternalTypes-GFn4RTwD.cjs';
2
- import { M as Maybe, R as Result, E as Equality, b as Ordering, T as Task } from './Validation-KFUpea_k.cjs';
3
- import { B as Brand } from './Duration-DeyxG6VQ.cjs';
4
- import './types.cjs';
5
-
1
+ import { r as Brand } from "./index-Bs8En5LJ.cjs";
2
+ import { n as NonEmpty, r as NonEmptyArr } from "./InternalTypes-B1Lh9uw_.cjs";
3
+ import { D as Maybe, N as Equality, a as Task, p as Result, w as Ordering } from "./index-DCK_VPog.cjs";
4
+ //#region src/Data/Arr.d.ts
6
5
  declare namespace ArrTaskResult {
7
- /**
8
- * Maps each element to a Task.Result and runs them sequentially.
9
- * Returns the first Err encountered, or Ok of all results if all succeed.
10
- *
11
- * @example
12
- * ```ts
13
- * const validate = (n: number): Task.Result<string, number> =>
14
- * n > 0 ? Task.Result.ok(n) : Task.Result.err("non-positive");
15
- *
16
- * pipe(
17
- * [1, 2, 3],
18
- * Arr.traverse.Task.Result(validate)
19
- * )(); // Deferred<Ok([1, 2, 3])>
20
- *
21
- * pipe(
22
- * [1, -1, 3],
23
- * Arr.traverse.Task.Result(validate)
24
- * )(); // Deferred<Err("non-positive")>
25
- * ```
26
- */
27
- const traverse: <E, A, B>(f: (a: A) => Task<Result<E, B>>) => (data: readonly A[]) => Task<Result<E, readonly B[]>>;
28
- /**
29
- * Collects an array of Task.Results into a Task.Result of array.
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
- * ```
39
- */
40
- const sequence: <E, A>(data: readonly Task<Result<E, A>>[]) => Task<Result<E, readonly A[]>>;
6
+ /**
7
+ * Maps each element to a Task.Result and runs them sequentially.
8
+ * Returns the first Err encountered, or Ok of all results if all succeed.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const validate = (n: number): Task.Result<string, number> =>
13
+ * n > 0 ? Task.Result.ok(n) : Task.Result.err("non-positive");
14
+ *
15
+ * pipe(
16
+ * [1, 2, 3],
17
+ * Arr.traverse.Task.Result(validate)
18
+ * )(); // Deferred<Ok([1, 2, 3])>
19
+ *
20
+ * pipe(
21
+ * [1, -1, 3],
22
+ * Arr.traverse.Task.Result(validate)
23
+ * )(); // Deferred<Err("non-positive")>
24
+ * ```
25
+ */
26
+ const traverse: <E, A, B>(f: (a: A) => Task.Result<E, B>) => (data: readonly A[]) => Task.Result<E, readonly B[]>;
27
+ /**
28
+ * Collects an array of Task.Results into a Task.Result of array.
29
+ * Returns the first Err if any element is Err, runs sequentially.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * pipe(
34
+ * [Task.Result.ok(1), Task.Result.ok(2)],
35
+ * Arr.sequence.Task.Result
36
+ * )(); // Deferred<Ok([1, 2])>
37
+ * ```
38
+ */
39
+ const sequence: <E, A>(data: readonly Task.Result<E, A>[]) => Task.Result<E, readonly A[]>;
41
40
  }
42
41
  interface TaskTraverse {
43
- <A, B>(f: (a: A) => Task<B>): (data: readonly A[]) => Task<readonly B[]>;
44
- Result: typeof ArrTaskResult.traverse;
42
+ <A, B>(f: (a: A) => Task<B>): (data: readonly A[]) => Task<readonly B[]>;
43
+ Result: typeof ArrTaskResult.traverse;
45
44
  }
46
45
  interface TaskSequence {
47
- <A>(data: readonly Task<A>[]): Task<readonly A[]>;
48
- Result: typeof ArrTaskResult.sequence;
46
+ <A>(data: readonly Task<A>[]): Task<readonly A[]>;
47
+ Result: typeof ArrTaskResult.sequence;
49
48
  }
50
- declare const Arr: {
51
- head: <A>(data: readonly A[]) => Maybe<A>;
52
- last: <A>(data: readonly A[]) => Maybe<A>;
53
- tail: <A>(data: readonly A[]) => Maybe<readonly A[]>;
54
- init: <A>(data: readonly A[]) => Maybe<readonly A[]>;
55
- findFirst: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Maybe<A>;
56
- findLast: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Maybe<A>;
57
- findIndex: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Maybe<number>;
58
- map: <A, B>(f: (a: A) => B) => (data: readonly A[]) => readonly B[];
59
- mapWithIndex: <A, B>(f: (i: number, a: A) => B) => (data: readonly A[]) => readonly B[];
60
- filter: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
61
- filterMap: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => readonly B[];
62
- partition: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly [readonly A[], readonly A[]];
63
- compact: <A>(data: readonly Maybe<A>[]) => readonly A[];
64
- separate: <E, A>(data: readonly Result<E, A>[]) => readonly [readonly E[], readonly A[]];
65
- partitionMap: <A, E, B>(f: (a: A) => Result<E, B>) => (data: readonly A[]) => readonly [readonly E[], readonly B[]];
66
- groupBy: <A>(f: (a: A) => string) => (data: readonly A[]) => Record<string, NonEmptyArr<A>>;
67
- uniq: <A>(data: readonly A[]) => readonly A[];
68
- uniqBy: <A, B>(f: (a: A) => B) => (data: readonly A[]) => readonly A[];
69
- uniqWith: <A>(eq: Equality<A>) => (data: readonly A[]) => readonly A[];
70
- sortBy: <A>(compare: (a: A, b: A) => number) => (data: readonly A[]) => readonly A[];
71
- sortWith: <A>(ord: Ordering<A>) => (data: readonly A[]) => readonly A[];
72
- zip: <B>(other: readonly B[]) => <A>(data: readonly A[]) => readonly (readonly [A, B])[];
73
- zipWith: <A, B, C>(f: (a: A, b: B) => C) => (other: readonly B[]) => (data: readonly A[]) => readonly C[];
74
- intersperse: <A>(sep: A) => (data: readonly A[]) => readonly A[];
75
- concat: <A>(other: readonly A[]) => (data: readonly A[]) => readonly A[];
76
- chunksOf: (n: number) => <A>(data: readonly A[]) => readonly (readonly A[])[];
77
- flatten: <A>(data: readonly (readonly A[])[]) => readonly A[];
78
- flatMap: <A, B>(f: (a: A) => readonly B[]) => (data: readonly A[]) => readonly B[];
79
- reduce: <A, B>(initial: B, f: (acc: B, a: A) => B) => (data: readonly A[]) => B;
80
- prepend: <A>(value: A) => (data: readonly A[]) => NonEmptyArr<A>;
81
- append: <A>(value: A) => (data: readonly A[]) => NonEmptyArr<A>;
82
- size: <A>(data: readonly A[]) => number;
83
- some: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => boolean;
84
- every: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => boolean;
85
- reverse: <A>(data: readonly A[]) => readonly A[];
86
- insertAt: <A>(index: number, item: A) => (data: readonly A[]) => readonly A[];
87
- removeAt: (index: number) => <A>(data: readonly A[]) => readonly A[];
88
- take: (n: number) => <A>(data: readonly A[]) => readonly A[];
89
- drop: (n: number) => <A>(data: readonly A[]) => readonly A[];
90
- takeWhile: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
91
- dropWhile: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
92
- scan: <A, B>(initial: B, f: (acc: B, a: A) => B) => (data: readonly A[]) => readonly B[];
93
- splitAt: (index: number) => <A>(data: readonly A[]) => readonly [readonly A[], readonly A[]];
94
- partitionMaybe: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => readonly [failures: readonly A[], successes: readonly B[]];
95
- at: (index: number) => <A>(data: readonly A[]) => Maybe<A>;
96
- findMap: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => Maybe<B>;
97
- indexBy: <A, K>(keyFn: (a: A) => K) => (data: readonly A[]) => ReadonlyMap<K, A>;
98
- frequencies: <A>(data: readonly A[]) => ReadonlyMap<A, number>;
99
- chunkBy: <A, K>(keyFn: (a: A) => K) => (data: readonly A[]) => readonly (readonly A[])[];
100
- dedupeAdjacent: <A>(eq?: Equality<A>) => (data: readonly A[]) => readonly A[];
101
- windowed: (windowSize: number, options?: {
102
- step?: number;
103
- }) => <A>(data: readonly A[]) => readonly (readonly A[])[];
104
- unfold: <A, S>(initial: S, f: (state: S) => Maybe<readonly [A, S]>) => readonly A[];
49
+ export declare const Arr: {
50
+ head: <A>(data: readonly A[]) => Maybe<A>;
51
+ last: <A>(data: readonly A[]) => Maybe<A>;
52
+ tail: <A>(data: readonly A[]) => Maybe<readonly A[]>;
53
+ init: <A>(data: readonly A[]) => Maybe<readonly A[]>;
54
+ findFirst: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Maybe<A>;
55
+ findLast: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Maybe<A>;
56
+ findIndex: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Maybe<number>;
57
+ map: <A, B>(f: (a: A) => B) => (data: readonly A[]) => readonly B[];
58
+ mapWithIndex: <A, B>(f: (i: number, a: A) => B) => (data: readonly A[]) => readonly B[];
59
+ filter: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
60
+ filterMap: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => readonly B[];
61
+ partition: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly [readonly A[], readonly A[]];
62
+ compact: <A>(data: readonly Maybe<A>[]) => readonly A[];
63
+ separate: <E, A>(data: readonly Result<E, A>[]) => readonly [readonly E[], readonly A[]];
64
+ partitionMap: <A, E, B>(f: (a: A) => Result<E, B>) => (data: readonly A[]) => readonly [readonly E[], readonly B[]];
65
+ groupBy: <A>(f: (a: A) => string) => (data: readonly A[]) => Record<string, NonEmptyArr<A>>;
66
+ uniq: <A>(data: readonly A[]) => readonly A[];
67
+ uniqBy: <A, B>(f: (a: A) => B) => (data: readonly A[]) => readonly A[];
68
+ uniqWith: <A>(eq: Equality<A>) => (data: readonly A[]) => readonly A[];
69
+ sortBy: <A>(compare: (a: A, b: A) => number) => (data: readonly A[]) => readonly A[];
70
+ sortWith: <A>(ord: Ordering<A>) => (data: readonly A[]) => readonly A[];
71
+ zip: <B>(other: readonly B[]) => <A>(data: readonly A[]) => readonly (readonly [A, B])[];
72
+ zipWith: <A, B, C>(f: (a: A, b: B) => C) => (other: readonly B[]) => (data: readonly A[]) => readonly C[];
73
+ intersperse: <A>(sep: A) => (data: readonly A[]) => readonly A[];
74
+ concat: <A>(other: readonly A[]) => (data: readonly A[]) => readonly A[];
75
+ chunksOf: (n: number) => <A>(data: readonly A[]) => readonly (readonly A[])[];
76
+ flatten: <A>(data: readonly (readonly A[])[]) => readonly A[];
77
+ flatMap: <A, B>(f: (a: A) => readonly B[]) => (data: readonly A[]) => readonly B[];
78
+ reduce: <A, B>(initial: B, f: (acc: B, a: A) => B) => (data: readonly A[]) => B;
79
+ prepend: <A>(value: A) => (data: readonly A[]) => NonEmptyArr<A>;
80
+ append: <A>(value: A) => (data: readonly A[]) => NonEmptyArr<A>;
81
+ size: <A>(data: readonly A[]) => number;
82
+ some: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => boolean;
83
+ every: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => boolean;
84
+ reverse: <A>(data: readonly A[]) => readonly A[];
85
+ insertAt: <A>(index: number, item: A) => (data: readonly A[]) => readonly A[];
86
+ removeAt: (index: number) => <A>(data: readonly A[]) => readonly A[];
87
+ take: (n: number) => <A>(data: readonly A[]) => readonly A[];
88
+ drop: (n: number) => <A>(data: readonly A[]) => readonly A[];
89
+ takeWhile: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
90
+ dropWhile: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
91
+ scan: <A, B>(initial: B, f: (acc: B, a: A) => B) => (data: readonly A[]) => readonly B[];
92
+ splitAt: (index: number) => <A>(data: readonly A[]) => readonly [readonly A[], readonly A[]];
93
+ partitionMaybe: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => readonly [failures: readonly A[], successes: readonly B[]];
94
+ at: (index: number) => <A>(data: readonly A[]) => Maybe<A>;
95
+ findMap: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => Maybe<B>;
96
+ indexBy: <A, K>(keyFn: (a: A) => K) => (data: readonly A[]) => ReadonlyMap<K, A>;
97
+ frequencies: <A>(data: readonly A[]) => ReadonlyMap<A, number>;
98
+ chunkBy: <A, K>(keyFn: (a: A) => K) => (data: readonly A[]) => readonly (readonly A[])[];
99
+ dedupeAdjacent: <A>(eq?: Equality<A>) => (data: readonly A[]) => readonly A[];
100
+ windowed: (windowSize: number, options?: {
101
+ step?: number;
102
+ }) => <A>(data: readonly A[]) => readonly (readonly A[])[];
103
+ unfold: <A, S>(initial: S, f: (state: S) => Maybe<readonly [A, S]>) => readonly A[];
104
+ from: {
105
+ Array: <A>(data: readonly A[]) => Maybe<NonEmptyArr<A>>;
106
+ };
107
+ is: {
108
+ empty: <A>(data: readonly A[]) => data is readonly [];
109
+ nonEmpty: <A>(data: readonly A[]) => data is NonEmptyArr<A>;
110
+ };
111
+ traverse: {
112
+ Maybe: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => Maybe<readonly B[]>;
113
+ Result: <E, A, B>(f: (a: A) => Result<E, B>) => (data: readonly A[]) => Result<E, readonly B[]>;
114
+ Task: TaskTraverse;
115
+ };
116
+ sequence: {
117
+ Maybe: <A>(data: readonly Maybe<A>[]) => Maybe<readonly A[]>;
118
+ Result: <E, A>(data: readonly Result<E, A>[]) => Result<E, readonly A[]>;
119
+ Task: TaskSequence;
120
+ };
121
+ NonEmpty: {
122
+ singleton: <A>(value: A) => NonEmptyArr<A>;
105
123
  from: {
106
- Array: <A>(data: readonly A[]) => Maybe<NonEmptyArr<A>>;
107
- };
108
- is: {
109
- empty: <A>(data: readonly A[]) => data is readonly [];
110
- nonEmpty: <A>(data: readonly A[]) => data is NonEmptyArr<A>;
111
- };
112
- traverse: {
113
- Maybe: <A, B>(f: (a: A) => Maybe<B>) => (data: readonly A[]) => Maybe<readonly B[]>;
114
- Result: <E, A, B>(f: (a: A) => Result<E, B>) => (data: readonly A[]) => Result<E, readonly B[]>;
115
- Task: TaskTraverse;
116
- };
117
- sequence: {
118
- Maybe: <A>(data: readonly Maybe<A>[]) => Maybe<readonly A[]>;
119
- Result: <E, A>(data: readonly Result<E, A>[]) => Result<E, readonly A[]>;
120
- Task: TaskSequence;
121
- };
122
- NonEmpty: {
123
- singleton: <A>(value: A) => NonEmptyArr<A>;
124
- from: {
125
- Array: <A>(data: readonly A[]) => Maybe<NonEmptyArr<A>>;
126
- };
127
- head: <A>(data: NonEmptyArr<A>) => A;
128
- last: <A>(data: NonEmptyArr<A>) => A;
129
- tail: <A>(data: NonEmptyArr<A>) => readonly A[];
130
- reduce: <A>(f: (acc: A, a: A) => A) => (data: NonEmptyArr<A>) => A;
131
- map: <A, B>(f: (a: A) => B) => (data: NonEmptyArr<A>) => NonEmptyArr<B>;
132
- mapWithIndex: <A, B>(f: (i: number, a: A) => B) => (data: NonEmptyArr<A>) => NonEmptyArr<B>;
133
- intersperse: <A>(sep: A) => (data: NonEmptyArr<A>) => NonEmptyArr<A>;
134
- concat: <A>(other: readonly A[]) => (data: NonEmptyArr<A>) => NonEmptyArr<A>;
135
- reverse: <A>(data: NonEmptyArr<A>) => NonEmptyArr<A>;
124
+ Array: <A>(data: readonly A[]) => Maybe<NonEmptyArr<A>>;
136
125
  };
126
+ head: <A>(data: NonEmptyArr<A>) => A;
127
+ last: <A>(data: NonEmptyArr<A>) => A;
128
+ tail: <A>(data: NonEmptyArr<A>) => readonly A[];
129
+ reduce: <A>(f: (acc: A, a: A) => A) => (data: NonEmptyArr<A>) => A;
130
+ map: <A, B>(f: (a: A) => B) => (data: NonEmptyArr<A>) => NonEmptyArr<B>;
131
+ mapWithIndex: <A, B>(f: (i: number, a: A) => B) => (data: NonEmptyArr<A>) => NonEmptyArr<B>;
132
+ intersperse: <A>(sep: A) => (data: NonEmptyArr<A>) => NonEmptyArr<A>;
133
+ concat: <A>(other: readonly A[]) => (data: NonEmptyArr<A>) => NonEmptyArr<A>;
134
+ reverse: <A>(data: NonEmptyArr<A>) => NonEmptyArr<A>;
135
+ };
137
136
  };
138
- declare namespace Arr {
139
- type NonEmpty<A> = NonEmptyArr<A>;
137
+ export declare namespace Arr {
138
+ type NonEmpty<A> = NonEmptyArr<A>;
140
139
  }
141
-
140
+ //#endregion
141
+ //#region src/Data/BigNum.d.ts
142
142
  /**
143
143
  * Safe conversion and arithmetic utilities for arbitrary-precision integers (`bigint`).
144
144
  * All functions are pure and data-last to compose cleanly with `pipe`.
@@ -154,561 +154,907 @@ declare namespace Arr {
154
154
  * ); // Some(150n)
155
155
  * ```
156
156
  */
157
- declare const BigNum: {
158
- from: {
159
- /**
160
- * Safely parses a string into a `bigint`. Returns `None` if parsing fails.
161
- *
162
- * @example
163
- * ```ts
164
- * BigNum.from.string("123"); // Some(123n)
165
- * BigNum.from.string("abc"); // None
166
- * ```
167
- */
168
- string: (s: string) => Maybe<bigint>;
169
- /**
170
- * Safely converts a number into a `bigint`. Returns `None` for floats, `NaN`, or non-safe integers.
171
- *
172
- * @example
173
- * ```ts
174
- * BigNum.from.number(42); // Some(42n)
175
- * BigNum.from.number(3.14); // None
176
- * ```
177
- */
178
- number: (n: number) => Maybe<bigint>;
179
- };
180
- to: {
181
- /**
182
- * Safely converts a `bigint` to a `number`. Returns `None` if the value is outside JavaScript's safe integer range.
183
- *
184
- * @example
185
- * ```ts
186
- * BigNum.to.number(42n); // Some(42)
187
- * BigNum.to.number(9007199254740993n); // None
188
- * ```
189
- */
190
- number: (b: bigint) => Maybe<number>;
191
- };
192
- /**
193
- * Adds `b` to `a`. Data-last curried signature: `add(b)(a)` = `a + b`.
194
- *
195
- * @example
196
- * ```ts
197
- * pipe(10n, BigNum.add(5n)); // 15n
198
- * ```
199
- */
200
- add: (b: bigint) => (a: bigint) => bigint;
201
- /**
202
- * Subtracts `b` from `a`. Data-last curried signature: `sub(b)(a)` = `a - b`.
203
- *
204
- * @example
205
- * ```ts
206
- * pipe(10n, BigNum.sub(3n)); // 7n
207
- * ```
208
- */
209
- sub: (b: bigint) => (a: bigint) => bigint;
157
+ export declare const BigNum: {
158
+ is: {
210
159
  /**
211
- * Multiplies `a` by `b`. Data-last curried signature: `mul(b)(a)` = `a * b`.
160
+ * Returns `true` when the bigint is equal to zero (`0n`).
212
161
  *
213
162
  * @example
214
163
  * ```ts
215
- * pipe(6n, BigNum.mul(7n)); // 42n
164
+ * BigNum.is.zero(0n); // true
165
+ * BigNum.is.zero(5n); // false
216
166
  * ```
217
167
  */
218
- mul: (b: bigint) => (a: bigint) => bigint;
168
+ zero: (b: bigint) => boolean;
219
169
  /**
220
- * Divides `a` by `b`. Returns `None` if `b` is `0n`.
170
+ * Returns `true` when the bigint is an even integer.
221
171
  *
222
172
  * @example
223
173
  * ```ts
224
- * pipe(20n, BigNum.div(4n)); // Some(5n)
225
- * pipe(5n, BigNum.div(0n)); // None
174
+ * BigNum.is.even(4n); // true
175
+ * BigNum.is.even(3n); // false
226
176
  * ```
227
177
  */
228
- div: (b: bigint) => (a: bigint) => Maybe<bigint>;
178
+ even: (b: bigint) => boolean;
229
179
  /**
230
- * Computes remainder of `a / b`. Returns `None` if `b` is `0n`.
180
+ * Returns `true` when the bigint is an odd integer.
231
181
  *
232
182
  * @example
233
183
  * ```ts
234
- * pipe(10n, BigNum.mod(3n)); // Some(1n)
235
- * pipe(5n, BigNum.mod(0n)); // None
184
+ * BigNum.is.odd(3n); // true
185
+ * BigNum.is.odd(4n); // false
236
186
  * ```
237
187
  */
238
- mod: (b: bigint) => (a: bigint) => Maybe<bigint>;
188
+ odd: (b: bigint) => boolean;
239
189
  /**
240
- * Clamps `a` between `min` and `max` (inclusive).
190
+ * Returns `true` when the bigint is strictly greater than zero (`0n`).
241
191
  *
242
192
  * @example
243
193
  * ```ts
244
- * pipe(150n, BigNum.clamp(0n, 100n)); // 100n
194
+ * BigNum.is.positive(5n); // true
195
+ * BigNum.is.positive(0n); // false
196
+ * BigNum.is.positive(-5n); // false
245
197
  * ```
246
198
  */
247
- clamp: (min: bigint, max: bigint) => (a: bigint) => bigint;
199
+ positive: (b: bigint) => boolean;
248
200
  /**
249
- * Returns `true` if `a` is in the range `[start, end)` (inclusive start, exclusive end).
201
+ * Returns `true` when the bigint is strictly less than zero (`0n`).
250
202
  *
251
203
  * @example
252
204
  * ```ts
253
- * pipe(5n, BigNum.inRange(1n, 10n)); // true
205
+ * BigNum.is.negative(-5n); // true
206
+ * BigNum.is.negative(0n); // false
207
+ * BigNum.is.negative(5n); // false
254
208
  * ```
255
209
  */
256
- inRange: (start: bigint, end: bigint) => (a: bigint) => boolean;
210
+ negative: (b: bigint) => boolean;
211
+ };
212
+ from: {
257
213
  /**
258
- * Returns absolute value of a `bigint`.
214
+ * Safely parses a string into a `bigint`. Returns `None` if parsing fails.
259
215
  *
260
216
  * @example
261
217
  * ```ts
262
- * BigNum.abs(-42n); // 42n
218
+ * BigNum.from.string("123"); // Some(123n)
219
+ * BigNum.from.string("abc"); // None
263
220
  * ```
264
221
  */
265
- abs: (a: bigint) => bigint;
222
+ string: (s: string) => Maybe<bigint>;
266
223
  /**
267
- * Returns the minimum of `a` and `b`.
224
+ * Safely converts a number into a `bigint`. Returns `None` for floats, `NaN`, or non-safe integers.
268
225
  *
269
226
  * @example
270
227
  * ```ts
271
- * pipe(10n, BigNum.min(5n)); // 5n
228
+ * BigNum.from.number(42); // Some(42n)
229
+ * BigNum.from.number(3.14); // None
272
230
  * ```
273
231
  */
274
- min: (b: bigint) => (a: bigint) => bigint;
232
+ number: (n: number) => Maybe<bigint>;
233
+ };
234
+ to: {
275
235
  /**
276
- * Returns the maximum of `a` and `b`.
236
+ * Safely converts a `bigint` to a `number`. Returns `None` if the value is outside JavaScript's safe integer range.
277
237
  *
278
238
  * @example
279
239
  * ```ts
280
- * pipe(10n, BigNum.max(5n)); // 10n
240
+ * BigNum.to.number(42n); // Some(42)
241
+ * BigNum.to.number(9007199254740993n); // None
281
242
  * ```
282
243
  */
283
- max: (b: bigint) => (a: bigint) => bigint;
244
+ number: (b: bigint) => Maybe<number>;
245
+ };
246
+ /**
247
+ * Adds `b` to `a`. Data-last curried signature: `add(b)(a)` = `a + b`.
248
+ *
249
+ * @example
250
+ * ```ts
251
+ * pipe(10n, BigNum.add(5n)); // 15n
252
+ * ```
253
+ */
254
+ add: (b: bigint) => (a: bigint) => bigint;
255
+ /**
256
+ * Subtracts `b` from `a`. Data-last curried signature: `sub(b)(a)` = `a - b`.
257
+ *
258
+ * @example
259
+ * ```ts
260
+ * pipe(10n, BigNum.sub(3n)); // 7n
261
+ * ```
262
+ */
263
+ sub: (b: bigint) => (a: bigint) => bigint;
264
+ /**
265
+ * Multiplies `a` by `b`. Data-last curried signature: `mul(b)(a)` = `a * b`.
266
+ *
267
+ * @example
268
+ * ```ts
269
+ * pipe(6n, BigNum.mul(7n)); // 42n
270
+ * ```
271
+ */
272
+ mul: (b: bigint) => (a: bigint) => bigint;
273
+ /**
274
+ * Divides `a` by `b`. Returns `None` if `b` is `0n`.
275
+ *
276
+ * @example
277
+ * ```ts
278
+ * pipe(20n, BigNum.div(4n)); // Some(5n)
279
+ * pipe(5n, BigNum.div(0n)); // None
280
+ * ```
281
+ */
282
+ div: (b: bigint) => (a: bigint) => Maybe<bigint>;
283
+ /**
284
+ * Computes remainder of `a / b`. Returns `None` if `b` is `0n`.
285
+ *
286
+ * @example
287
+ * ```ts
288
+ * pipe(10n, BigNum.mod(3n)); // Some(1n)
289
+ * pipe(5n, BigNum.mod(0n)); // None
290
+ * ```
291
+ */
292
+ mod: (b: bigint) => (a: bigint) => Maybe<bigint>;
293
+ /**
294
+ * Clamps `a` between `min` and `max` (inclusive).
295
+ *
296
+ * @example
297
+ * ```ts
298
+ * pipe(150n, BigNum.clamp(0n, 100n)); // 100n
299
+ * ```
300
+ */
301
+ clamp: (min: bigint, max: bigint) => (a: bigint) => bigint;
302
+ /**
303
+ * Returns `true` if `a` is in the range `[start, end)` (inclusive start, exclusive end).
304
+ *
305
+ * @example
306
+ * ```ts
307
+ * pipe(5n, BigNum.inRange(1n, 10n)); // true
308
+ * ```
309
+ */
310
+ inRange: (start: bigint, end: bigint) => (a: bigint) => boolean;
311
+ /**
312
+ * Returns absolute value of a `bigint`.
313
+ *
314
+ * @example
315
+ * ```ts
316
+ * BigNum.abs(-42n); // 42n
317
+ * ```
318
+ */
319
+ abs: (a: bigint) => bigint;
320
+ /**
321
+ * Returns the minimum of `a` and `b`.
322
+ *
323
+ * @example
324
+ * ```ts
325
+ * pipe(10n, BigNum.min(5n)); // 5n
326
+ * ```
327
+ */
328
+ min: (b: bigint) => (a: bigint) => bigint;
329
+ /**
330
+ * Returns the maximum of `a` and `b`.
331
+ *
332
+ * @example
333
+ * ```ts
334
+ * pipe(10n, BigNum.max(5n)); // 10n
335
+ * ```
336
+ */
337
+ max: (b: bigint) => (a: bigint) => bigint;
284
338
  };
285
-
286
- /**
287
- * A branded type representing a key-value dictionary with at least one entry.
288
- */
289
- type NonEmptyMap<K, V> = Brand<NonEmpty<"Dict">, ReadonlyMap<K, V>>;
290
- declare function mergeWith$1<V>(combine: (a: V, b: V) => V): {
291
- <K>(first: ReadonlyMap<K, V>, second: ReadonlyMap<K, V>): ReadonlyMap<K, V>;
292
- <K>(second: ReadonlyMap<K, V>): (first: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
339
+ //#endregion
340
+ //#region src/Data/Bool.d.ts
341
+ export type BoolMatchCases<A, B> = {
342
+ readonly true: () => A;
343
+ readonly false: () => B;
293
344
  };
294
- declare const Dict: {
295
- is: {
296
- empty: <K, V>(m: ReadonlyMap<K, V>) => boolean;
297
- nonEmpty: <K, V>(m: ReadonlyMap<K, V>) => m is NonEmptyMap<K, V>;
298
- };
299
- empty: <K, V>() => ReadonlyMap<K, V>;
300
- singleton: <K, V>(key: K, value: V) => ReadonlyMap<K, V>;
301
- from: {
302
- entries: <K, V>(entries: readonly (readonly [K, V])[]) => ReadonlyMap<K, V>;
303
- Record: <K extends string, V>(record: Readonly<Record<K, V>>) => ReadonlyMap<K, V>;
304
- Array: <K, V>(data: readonly (readonly [K, V])[]) => ReadonlyMap<K, V>;
305
- nullable: <K, V>(data: ReadonlyMap<K, V> | null | undefined) => Maybe<ReadonlyMap<K, V>>;
306
- };
307
- to: {
308
- Record: <K extends string, V>(map: ReadonlyMap<K, V>) => Readonly<Record<K, V>>;
309
- };
310
- groupBy: <A, K>(f: (a: A) => K) => (as: readonly A[]) => ReadonlyMap<K, NonEmptyArr<A>>;
311
- has: <K, V>(key: K) => (data: ReadonlyMap<K, V>) => boolean;
312
- lookup: <K, V>(key: K) => (data: ReadonlyMap<K, V>) => Maybe<V>;
313
- size: <K, V>(data: ReadonlyMap<K, V>) => number;
314
- keys: <K, V>(data: ReadonlyMap<K, V>) => readonly K[];
315
- values: <K, V>(data: ReadonlyMap<K, V>) => readonly V[];
316
- entries: <K, V>(data: ReadonlyMap<K, V>) => readonly (readonly [K, V])[];
317
- insert: <K, V>(key: K, value: V) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
318
- remove: <K, V>(key: K) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
319
- upsert: <K, V>(key: K, f: (existing: Maybe<V>) => V) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
320
- map: <A, B>(f: (a: A) => B) => <K>(data: ReadonlyMap<K, A>) => ReadonlyMap<K, B>;
321
- mapWithKey: <K, A, B>(f: (key: K, value: A) => B) => (data: ReadonlyMap<K, A>) => ReadonlyMap<K, B>;
322
- filter: <A>(predicate: (a: A) => boolean) => <K>(data: ReadonlyMap<K, A>) => ReadonlyMap<K, A>;
323
- filterWithKey: <K, A>(predicate: (key: K, value: A) => boolean) => (data: ReadonlyMap<K, A>) => ReadonlyMap<K, A>;
324
- compact: <K, A>(data: ReadonlyMap<K, Maybe<A>>) => ReadonlyMap<K, A>;
325
- filterMap: <A, B>(f: (a: A) => Maybe<B>) => <K>(data: ReadonlyMap<K, A>) => ReadonlyMap<K, B>;
326
- union: <K, V>(other: ReadonlyMap<K, V>) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
327
- intersection: <K, V>(other: ReadonlyMap<K, V>) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
328
- difference: <K, V>(other: ReadonlyMap<K, V>) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
329
- reduce: <B, V>(init: B, f: (acc: B, value: V) => B) => <K>(data: ReadonlyMap<K, V>) => B;
330
- reduceWithKey: <B, K, V>(init: B, f: (acc: B, value: V, key: K) => B) => (data: ReadonlyMap<K, V>) => B;
331
- mergeWith: typeof mergeWith$1;
332
- mapEntries: <K1, V1, K2, V2>(f: (key: K1, value: V1) => readonly [K2, V2]) => (data: ReadonlyMap<K1, V1>) => ReadonlyMap<K2, V2>;
333
- mapKeys: <K1, K2, V>(f: (key: K1) => K2) => (data: ReadonlyMap<K1, V>) => ReadonlyMap<K2, V>;
334
- NonEmpty: {
335
- singleton: <K, V>(key: K, value: V) => NonEmptyMap<K, V>;
336
- from: {
337
- Map: <K, V>(m: ReadonlyMap<K, V>) => Maybe<NonEmptyMap<K, V>>;
338
- };
339
- keys: <K, V>(m: NonEmptyMap<K, V>) => NonEmptyArr<K>;
340
- values: <K, V>(m: NonEmptyMap<K, V>) => NonEmptyArr<V>;
341
- entries: <K, V>(m: NonEmptyMap<K, V>) => NonEmptyArr<readonly [K, V]>;
342
- reduce: <V>(f: (acc: V, value: V) => V) => <K>(m: NonEmptyMap<K, V>) => V;
343
- map: <A, B>(f: (a: A) => B) => <K>(m: NonEmptyMap<K, A>) => NonEmptyMap<K, B>;
344
- mapWithKey: <K, A, B>(f: (key: K, a: A) => B) => (m: NonEmptyMap<K, A>) => NonEmptyMap<K, B>;
345
- };
346
- };
347
- declare namespace Dict {
348
- /**
349
- * A branded type representing a key-value dictionary with at least one entry.
350
- */
351
- type NonEmpty<K, V> = NonEmptyMap<K, V>;
352
- }
353
-
354
- /**
355
- * Pure, non-throwing JSON utilities.
356
- * Wraps runtime JSON parsing and stringifying in typed `Result` containers.
357
- *
358
- * @example
359
- * ```ts
360
- * import { Json } from "@nlozgachev/pipelined/data";
361
- * import { pipe } from "@nlozgachev/pipelined/composition";
362
- *
363
- * const result = pipe(
364
- * Json.parse('{"name":"Alice"}'),
365
- * Result.map((data: any) => data.name)
366
- * ); // Ok("Alice")
367
- * ```
368
- */
369
- declare const Json: {
345
+ export declare const Bool: {
346
+ is: {
370
347
  /**
371
- * Safely parses a JSON string into `unknown`.
372
- * Converts thrown exceptions into a `Result<SyntaxError, unknown>`.
348
+ * Type guard — checks if a value is a primitive boolean.
373
349
  *
374
350
  * @example
375
351
  * ```ts
376
- * Json.parse('{"a": 1}'); // Ok({ a: 1 })
377
- * Json.parse('{invalid}'); // Err(SyntaxError)
352
+ * Bool.is.boolean(true); // true
353
+ * Bool.is.boolean(false); // true
354
+ * Bool.is.boolean("true"); // false
355
+ * Bool.is.boolean(null); // false
378
356
  * ```
379
357
  */
380
- parse: (text: string) => Result<SyntaxError, unknown>;
358
+ boolean: (u: unknown) => u is boolean;
381
359
  /**
382
- * Safely stringifies a value into a JSON string.
383
- * Converts thrown exceptions (e.g. circular references) into a `Result<TypeError, string>`.
360
+ * Narrowing guard — checks if a value is strictly `true`.
384
361
  *
385
362
  * @example
386
363
  * ```ts
387
- * Json.stringify({ a: 1 }); // Ok('{"a":1}')
364
+ * Bool.is.true(true); // true
365
+ * Bool.is.true(false); // false
388
366
  * ```
389
367
  */
390
- stringify: (value: unknown, replacer?: (this: any, key: string, value: any) => any, space?: string | number) => Result<TypeError, string>;
391
- };
392
-
393
- declare const Num: {
394
- is: {
395
- /**
396
- * Returns `true` when the number is equal to zero.
397
- *
398
- * @example
399
- * ```ts
400
- * Num.is.zero(0); // true
401
- * Num.is.zero(5); // false
402
- * ```
403
- */
404
- zero: (n: number) => boolean;
405
- /**
406
- * Returns `true` when the number is a whole integer.
407
- *
408
- * @example
409
- * ```ts
410
- * Num.is.integer(5); // true
411
- * Num.is.integer(3.14); // false
412
- * ```
413
- */
414
- integer: (n: number) => boolean;
415
- /**
416
- * Returns `true` when the number is a finite float (fractional number).
417
- *
418
- * @example
419
- * ```ts
420
- * Num.is.float(3.14); // true
421
- * Num.is.float(5); // false
422
- * ```
423
- */
424
- float: (n: number) => boolean;
425
- /**
426
- * Returns `true` when the number is finite (not `Infinity`, `-Infinity`, or `NaN`).
427
- *
428
- * @example
429
- * ```ts
430
- * Num.is.finite(42); // true
431
- * Num.is.finite(Infinity); // false
432
- * ```
433
- */
434
- finite: (n: number) => boolean;
435
- /**
436
- * Returns `true` when the value is `NaN`.
437
- *
438
- * @example
439
- * ```ts
440
- * Num.is.nan(NaN); // true
441
- * Num.is.nan(42); // false
442
- * ```
443
- */
444
- nan: (n: number) => boolean;
445
- /**
446
- * Returns `true` when the number is an even integer.
447
- *
448
- * @example
449
- * ```ts
450
- * Num.is.even(4); // true
451
- * Num.is.even(3); // false
452
- * Num.is.even(2.5); // false
453
- * ```
454
- */
455
- even: (n: number) => boolean;
456
- /**
457
- * Returns `true` when the number is an odd integer.
458
- *
459
- * @example
460
- * ```ts
461
- * Num.is.odd(3); // true
462
- * Num.is.odd(4); // false
463
- * Num.is.odd(2.5); // false
464
- * ```
465
- */
466
- odd: (n: number) => boolean;
467
- /**
468
- * Returns `true` when the number is strictly greater than zero.
469
- *
470
- * @example
471
- * ```ts
472
- * Num.is.positive(5); // true
473
- * Num.is.positive(0); // false
474
- * Num.is.positive(-5); // false
475
- * ```
476
- */
477
- positive: (n: number) => boolean;
478
- /**
479
- * Returns `true` when the number is strictly less than zero.
480
- *
481
- * @example
482
- * ```ts
483
- * Num.is.negative(-5); // true
484
- * Num.is.negative(0); // false
485
- * Num.is.negative(5); // false
486
- * ```
487
- */
488
- negative: (n: number) => boolean;
489
- };
368
+ true: (u: unknown) => u is true;
490
369
  /**
491
- * Generates an array of numbers from `from` to `to` (both inclusive),
492
- * stepping by `step` (default `1`). If `step` is negative or zero, or `from > to`,
493
- * returns an empty array. When `step` does not land exactly on `to`, the last value
494
- * is the largest reachable value that does not exceed `to`.
370
+ * Narrowing guard — checks if a value is strictly `false`.
495
371
  *
496
372
  * @example
497
373
  * ```ts
498
- * Num.range(0, 5); // [0, 1, 2, 3, 4, 5]
499
- * Num.range(0, 10, 2); // [0, 2, 4, 6, 8, 10]
500
- * Num.range(0, 9, 2); // [0, 2, 4, 6, 8]
501
- * Num.range(5, 0); // []
502
- * Num.range(3, 3); // [3]
374
+ * Bool.is.false(false); // true
375
+ * Bool.is.false(true); // false
503
376
  * ```
504
377
  */
505
- range: (from: number, to: number, step?: number) => readonly number[];
378
+ false: (u: unknown) => u is false;
506
379
  /**
507
- * Clamps a number between `min` and `max` (both inclusive).
380
+ * Type guard — checks if a value is truthy (not `false`, `0`, `0n`, `""`, `null`, `undefined`, or `NaN`).
508
381
  *
509
382
  * @example
510
383
  * ```ts
511
- * pipe(150, Num.clamp(0, 100)); // 100
512
- * pipe(-5, Num.clamp(0, 100)); // 0
513
- * pipe(42, Num.clamp(0, 100)); // 42
384
+ * Bool.is.truthy("hello"); // true
385
+ * Bool.is.truthy(42); // true
386
+ * Bool.is.truthy(0); // false
387
+ * Bool.is.truthy(null); // false
514
388
  * ```
515
389
  */
516
- clamp: (min: number, max: number) => (n: number) => number;
390
+ truthy: <T>(u: T) => u is Exclude<T, false | 0 | 0n | "" | null | undefined>;
517
391
  /**
518
- * Returns `true` when the number is between `min` and `max` (both inclusive).
392
+ * Type guard — checks if a value is falsy (`false`, `0`, `0n`, `""`, `null`, `undefined`, or `NaN`).
519
393
  *
520
394
  * @example
521
395
  * ```ts
522
- * pipe(5, Num.between(1, 10)); // true
523
- * pipe(0, Num.between(1, 10)); // false
524
- * pipe(10, Num.between(1, 10)); // true
396
+ * Bool.is.falsy(""); // true
397
+ * Bool.is.falsy(null); // true
398
+ * Bool.is.falsy("content"); // false
525
399
  * ```
526
400
  */
527
- between: (min: number, max: number) => (n: number) => boolean;
401
+ falsy: (u: unknown) => u is false | 0 | 0n | "" | null | undefined;
402
+ };
403
+ /**
404
+ * Unary boolean negation: inverts the given boolean value.
405
+ *
406
+ * @example
407
+ * ```ts
408
+ * Bool.not(true); // false
409
+ * Bool.not(false); // true
410
+ * ```
411
+ */
412
+ not: (b: boolean) => boolean;
413
+ /**
414
+ * Logical AND combinator. Returns `true` only if both `self` and `that` are `true`.
415
+ *
416
+ * Data-last: `pipe(self, Bool.and(that))`.
417
+ *
418
+ * @example
419
+ * ```ts
420
+ * pipe(true, Bool.and(true)); // true
421
+ * pipe(true, Bool.and(false)); // false
422
+ * ```
423
+ */
424
+ and: (that: boolean) => (self: boolean) => boolean;
425
+ /**
426
+ * Logical OR combinator. Returns `true` if either `self` or `that` is `true`.
427
+ *
428
+ * Data-last: `pipe(self, Bool.or(that))`.
429
+ *
430
+ * @example
431
+ * ```ts
432
+ * pipe(false, Bool.or(true)); // true
433
+ * pipe(false, Bool.or(false)); // false
434
+ * ```
435
+ */
436
+ or: (that: boolean) => (self: boolean) => boolean;
437
+ /**
438
+ * Logical XOR (exclusive OR) combinator. Returns `true` if exactly one of `self` and `that` is `true`.
439
+ *
440
+ * Data-last: `pipe(self, Bool.xor(that))`.
441
+ *
442
+ * @example
443
+ * ```ts
444
+ * pipe(true, Bool.xor(false)); // true
445
+ * pipe(true, Bool.xor(true)); // false
446
+ * ```
447
+ */
448
+ xor: (that: boolean) => (self: boolean) => boolean;
449
+ /**
450
+ * Lazy logical AND combinator.
451
+ * If `self` is `false`, the `that` computation is never evaluated.
452
+ *
453
+ * Data-last: `pipe(self, Bool.andLazy(that))`.
454
+ *
455
+ * @example
456
+ * ```ts
457
+ * pipe(
458
+ * isCached,
459
+ * Bool.andLazy(() => checkPermissions())
460
+ * );
461
+ * ```
462
+ */
463
+ andLazy: (that: () => boolean) => (self: boolean) => boolean;
464
+ /**
465
+ * Lazy logical OR combinator.
466
+ * If `self` is `true`, the `that` computation is never evaluated.
467
+ *
468
+ * Data-last: `pipe(self, Bool.orLazy(that))`.
469
+ *
470
+ * @example
471
+ * ```ts
472
+ * pipe(
473
+ * isAdmin,
474
+ * Bool.orLazy(() => hasAccess(userId))
475
+ * );
476
+ * ```
477
+ */
478
+ orLazy: (that: () => boolean) => (self: boolean) => boolean;
479
+ /**
480
+ * N-ary AND aggregation across an array of booleans.
481
+ * Returns `true` if every boolean is `true`, or for an empty array (vacuous truth).
482
+ * Short-circuits on the first `false`.
483
+ *
484
+ * @example
485
+ * ```ts
486
+ * Bool.all([true, true, true]); // true
487
+ * Bool.all([true, false, true]); // false
488
+ * Bool.all([]); // true
489
+ * ```
490
+ */
491
+ all: (booleans: readonly boolean[]) => boolean;
492
+ /**
493
+ * N-ary OR aggregation across an array of booleans.
494
+ * Returns `true` if at least one boolean is `true`. Returns `false` for an empty array.
495
+ * Short-circuits on the first `true`.
496
+ *
497
+ * @example
498
+ * ```ts
499
+ * Bool.any([false, true, false]); // true
500
+ * Bool.any([false, false]); // false
501
+ * Bool.any([]); // false
502
+ * ```
503
+ */
504
+ any: (booleans: readonly boolean[]) => boolean;
505
+ /**
506
+ * Catamorphism for boolean: evaluates `onFalse()` when `false` and `onTrue()` when `true`.
507
+ *
508
+ * Positional ordering: `onFalse` first, `onTrue` second.
509
+ * Aligned with `Result.fold(onErr, onOk)` and `Maybe.fold(onNone, onSome)`.
510
+ *
511
+ * @example
512
+ * ```ts
513
+ * pipe(
514
+ * isDarkMode,
515
+ * Bool.fold(
516
+ * () => "light-theme",
517
+ * () => "dark-theme"
518
+ * )
519
+ * );
520
+ * ```
521
+ */
522
+ fold: <A, B>(onFalse: () => A, onTrue: () => B) => (b: boolean) => A | B;
523
+ /**
524
+ * Pattern matching on boolean using named cases `{ true, false }`.
525
+ *
526
+ * @example
527
+ * ```ts
528
+ * pipe(
529
+ * isEnabled,
530
+ * Bool.match({
531
+ * true: () => "Feature Active",
532
+ * false: () => "Feature Disabled",
533
+ * })
534
+ * );
535
+ * ```
536
+ */
537
+ match: <A, B>(cases: BoolMatchCases<A, B>) => (b: boolean) => A | B;
538
+ from: {
528
539
  /**
529
- * Returns `true` when the number is in the range `[start, end)` (inclusive of `start`, exclusive of `end`).
540
+ * Parses a string into a `Maybe<boolean>`.
541
+ * Returns `Some(true)` for `"true"`, `Some(false)` for `"false"` (case-insensitive & trimmed),
542
+ * and `None` for any other string.
530
543
  *
531
544
  * @example
532
545
  * ```ts
533
- * pipe(5, Num.inRange(1, 10)); // true
534
- * pipe(1, Num.inRange(1, 10)); // true
535
- * pipe(10, Num.inRange(1, 10)); // false
546
+ * Bool.from.string("true"); // Some(true)
547
+ * Bool.from.string("FALSE"); // Some(false)
548
+ * Bool.from.string("yes"); // None
536
549
  * ```
537
550
  */
538
- inRange: (start: number, end: number) => (n: number) => boolean;
551
+ string: (s: string) => Maybe<boolean>;
539
552
  /**
540
- * Parses a string as a number. Returns `None` when the result is `NaN`.
553
+ * Converts a number into a `Maybe<boolean>`.
554
+ * Returns `Some(true)` for `1`, `Some(false)` for `0`, and `None` for any other number.
541
555
  *
542
556
  * @example
543
557
  * ```ts
544
- * Num.parse("42"); // Some(42)
545
- * Num.parse("3.14"); // Some(3.14)
546
- * Num.parse("abc"); // None
547
- * Num.parse(""); // None
558
+ * Bool.from.number(1); // Some(true)
559
+ * Bool.from.number(0); // Some(false)
560
+ * Bool.from.number(42); // None
548
561
  * ```
549
562
  */
550
- parse: (s: string) => Maybe<number>;
563
+ number: (n: number) => Maybe<boolean>;
551
564
  /**
552
- * Adds `b` to a number. Data-last: use in `pipe` or `Arr.map`.
565
+ * Coerces any unknown value into a boolean via standard JS `Boolean(value)`.
553
566
  *
554
567
  * @example
555
568
  * ```ts
556
- * pipe(5, Num.add(3)); // 8
557
- * pipe([1, 2, 3], Arr.map(Num.add(10))); // [11, 12, 13]
569
+ * Bool.from.truthy("hello"); // true
570
+ * Bool.from.truthy(0); // false
558
571
  * ```
559
572
  */
560
- add: (b: number) => (a: number) => number;
573
+ truthy: (value: unknown) => boolean;
574
+ };
575
+ to: {
561
576
  /**
562
- * Subtracts `b` from a number. Data-last: `subtract(b)(a)` = `a - b`.
577
+ * Lifts a boolean condition into a `Maybe`.
578
+ * Returns `Some(onTrue())` when `true`, and `None` when `false`.
563
579
  *
564
580
  * @example
565
581
  * ```ts
566
- * pipe(10, Num.subtract(3)); // 7
567
- * pipe([5, 10, 15], Arr.map(Num.subtract(2))); // [3, 8, 13]
568
- * ```
569
- */
570
- subtract: (b: number) => (a: number) => number;
571
- /**
572
- * Multiplies a number by `b`. Data-last: use in `pipe` or `Arr.map`.
573
- *
574
- * @example
575
- * ```ts
576
- * pipe(6, Num.multiply(7)); // 42
577
- * pipe([1, 2, 3], Arr.map(Num.multiply(100))); // [100, 200, 300]
582
+ * pipe(
583
+ * user.isVerified,
584
+ * Bool.to.Maybe(() => user.profile)
585
+ * ); // Some(profile) or None
578
586
  * ```
579
587
  */
580
- multiply: (b: number) => (a: number) => number;
588
+ Maybe: <A>(onTrue: () => A) => (b: boolean) => Maybe<A>;
581
589
  /**
582
- * Divides a number by `b`. Returns `None` when `b` is zero. Data-last: `divide(b)(a)` = `a / b`.
590
+ * Lifts a boolean condition into a `Result`.
591
+ * Returns `Ok(onOk())` when `true`, and `Err(onErr())` when `false`.
583
592
  *
584
593
  * @example
585
594
  * ```ts
586
- * pipe(20, Num.divide(4)); // Some(5)
587
- * pipe(5, Num.divide(0)); // None
588
- * pipe([10, 20, 30], Arr.filterMap(Num.divide(10))); // [1, 2, 3]
595
+ * pipe(
596
+ * hasPermission,
597
+ * Bool.to.Result(
598
+ * () => "Permission denied",
599
+ * () => sessionData
600
+ * )
601
+ * ); // Ok(sessionData) or Err("Permission denied")
589
602
  * ```
590
603
  */
591
- divide: (b: number) => (a: number) => Maybe<number>;
604
+ Result: <E, A>(onErr: () => E, onOk: () => A) => (b: boolean) => Result<E, A>;
592
605
  /**
593
- * Returns the absolute value of a number.
606
+ * Converts a boolean to numeric `1` or `0`.
594
607
  *
595
608
  * @example
596
609
  * ```ts
597
- * pipe(-5, Num.abs); // 5
598
- * pipe(5, Num.abs); // 5
610
+ * Bool.to.number(true); // 1
611
+ * Bool.to.number(false); // 0
599
612
  * ```
600
613
  */
601
- abs: (n: number) => number;
614
+ number: (b: boolean) => 1 | 0;
602
615
  /**
603
- * Negates a number (arithmetic negation).
616
+ * Converts a boolean to literal string `"true"` or `"false"`.
604
617
  *
605
618
  * @example
606
619
  * ```ts
607
- * pipe(5, Num.negate); // -5
608
- * pipe(-5, Num.negate); // 5
620
+ * Bool.to.string(true); // "true"
621
+ * Bool.to.string(false); // "false"
609
622
  * ```
610
623
  */
611
- negate: (n: number) => number;
624
+ string: (b: boolean) => "true" | "false";
625
+ };
626
+ };
627
+ //#endregion
628
+ //#region src/Data/Dict.d.ts
629
+ /**
630
+ * A branded type representing a key-value dictionary with at least one entry.
631
+ */
632
+ export type NonEmptyMap<K, V> = Brand<NonEmpty<"Dict">, ReadonlyMap<K, V>>;
633
+ declare function mergeWith$1<V>(combine: (a: V, b: V) => V): {
634
+ <K>(first: ReadonlyMap<K, V>, second: ReadonlyMap<K, V>): ReadonlyMap<K, V>;
635
+ <K>(second: ReadonlyMap<K, V>): (first: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
636
+ };
637
+ export declare const Dict: {
638
+ is: {
639
+ empty: <K, V>(m: ReadonlyMap<K, V>) => boolean;
640
+ nonEmpty: <K, V>(m: ReadonlyMap<K, V>) => m is NonEmptyMap<K, V>;
641
+ };
642
+ empty: <K, V>() => ReadonlyMap<K, V>;
643
+ singleton: <K, V>(key: K, value: V) => ReadonlyMap<K, V>;
644
+ from: {
645
+ entries: <K, V>(entries: readonly (readonly [K, V])[]) => ReadonlyMap<K, V>;
646
+ Record: <K extends string, V>(record: Readonly<Record<K, V>>) => ReadonlyMap<K, V>;
647
+ Array: <K, V>(data: readonly (readonly [K, V])[]) => ReadonlyMap<K, V>;
648
+ nullable: <K, V>(data: ReadonlyMap<K, V> | null | undefined) => Maybe<ReadonlyMap<K, V>>;
649
+ };
650
+ to: {
651
+ Record: <K extends string, V>(map: ReadonlyMap<K, V>) => Readonly<Record<K, V>>;
652
+ };
653
+ groupBy: <A, K>(f: (a: A) => K) => (as: readonly A[]) => ReadonlyMap<K, NonEmptyArr<A>>;
654
+ has: <K, V>(key: K) => (data: ReadonlyMap<K, V>) => boolean;
655
+ lookup: <K, V>(key: K) => (data: ReadonlyMap<K, V>) => Maybe<V>;
656
+ size: <K, V>(data: ReadonlyMap<K, V>) => number;
657
+ keys: <K, V>(data: ReadonlyMap<K, V>) => readonly K[];
658
+ values: <K, V>(data: ReadonlyMap<K, V>) => readonly V[];
659
+ entries: <K, V>(data: ReadonlyMap<K, V>) => readonly (readonly [K, V])[];
660
+ insert: <K, V>(key: K, value: V) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
661
+ remove: <K, V>(key: K) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
662
+ upsert: <K, V>(key: K, f: (existing: Maybe<V>) => V) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
663
+ map: <A, B>(f: (a: A) => B) => <K>(data: ReadonlyMap<K, A>) => ReadonlyMap<K, B>;
664
+ mapWithKey: <K, A, B>(f: (key: K, value: A) => B) => (data: ReadonlyMap<K, A>) => ReadonlyMap<K, B>;
665
+ filter: <A>(predicate: (a: A) => boolean) => <K>(data: ReadonlyMap<K, A>) => ReadonlyMap<K, A>;
666
+ filterWithKey: <K, A>(predicate: (key: K, value: A) => boolean) => (data: ReadonlyMap<K, A>) => ReadonlyMap<K, A>;
667
+ compact: <K, A>(data: ReadonlyMap<K, Maybe<A>>) => ReadonlyMap<K, A>;
668
+ filterMap: <A, B>(f: (a: A) => Maybe<B>) => <K>(data: ReadonlyMap<K, A>) => ReadonlyMap<K, B>;
669
+ union: <K, V>(other: ReadonlyMap<K, V>) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
670
+ intersection: <K, V>(other: ReadonlyMap<K, V>) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
671
+ difference: <K, V>(other: ReadonlyMap<K, V>) => (data: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
672
+ reduce: <B, V>(init: B, f: (acc: B, value: V) => B) => <K>(data: ReadonlyMap<K, V>) => B;
673
+ reduceWithKey: <B, K, V>(init: B, f: (acc: B, value: V, key: K) => B) => (data: ReadonlyMap<K, V>) => B;
674
+ mergeWith: typeof mergeWith$1;
675
+ mapEntries: <K1, V1, K2, V2>(f: (key: K1, value: V1) => readonly [K2, V2]) => (data: ReadonlyMap<K1, V1>) => ReadonlyMap<K2, V2>;
676
+ mapKeys: <K1, K2, V>(f: (key: K1) => K2) => (data: ReadonlyMap<K1, V>) => ReadonlyMap<K2, V>;
677
+ NonEmpty: {
678
+ singleton: <K, V>(key: K, value: V) => NonEmptyMap<K, V>;
679
+ from: {
680
+ Map: <K, V>(m: ReadonlyMap<K, V>) => Maybe<NonEmptyMap<K, V>>;
681
+ };
682
+ keys: <K, V>(m: NonEmptyMap<K, V>) => NonEmptyArr<K>;
683
+ values: <K, V>(m: NonEmptyMap<K, V>) => NonEmptyArr<V>;
684
+ entries: <K, V>(m: NonEmptyMap<K, V>) => NonEmptyArr<readonly [K, V]>;
685
+ reduce: <V>(f: (acc: V, value: V) => V) => <K>(m: NonEmptyMap<K, V>) => V;
686
+ map: <A, B>(f: (a: A) => B) => <K>(m: NonEmptyMap<K, A>) => NonEmptyMap<K, B>;
687
+ mapWithKey: <K, A, B>(f: (key: K, a: A) => B) => (m: NonEmptyMap<K, A>) => NonEmptyMap<K, B>;
688
+ };
689
+ };
690
+ export declare namespace Dict {
691
+ /**
692
+ * A branded type representing a key-value dictionary with at least one entry.
693
+ */
694
+ type NonEmpty<K, V> = NonEmptyMap<K, V>;
695
+ }
696
+ //#endregion
697
+ //#region src/Data/Json.d.ts
698
+ /**
699
+ * Pure, non-throwing JSON utilities.
700
+ * Wraps runtime JSON parsing and stringifying in typed `Result` containers.
701
+ *
702
+ * @example
703
+ * ```ts
704
+ * import { Json } from "@nlozgachev/pipelined/data";
705
+ * import { pipe } from "@nlozgachev/pipelined/composition";
706
+ *
707
+ * const result = pipe(
708
+ * Json.parse('{"name":"Alice"}'),
709
+ * Result.map((data: any) => data.name)
710
+ * ); // Ok("Alice")
711
+ * ```
712
+ */
713
+ export declare const Json: {
714
+ /**
715
+ * Safely parses a JSON string into `unknown`.
716
+ * Converts thrown exceptions into a `Result<SyntaxError, unknown>`.
717
+ *
718
+ * @example
719
+ * ```ts
720
+ * Json.parse('{"a": 1}'); // Ok({ a: 1 })
721
+ * Json.parse('{invalid}'); // Err(SyntaxError)
722
+ * ```
723
+ */
724
+ parse: (text: string) => Result<SyntaxError, unknown>;
725
+ /**
726
+ * Safely stringifies a value into a JSON string.
727
+ * Converts thrown exceptions (e.g. circular references) into a `Result<TypeError, string>`.
728
+ *
729
+ * @example
730
+ * ```ts
731
+ * Json.stringify({ a: 1 }); // Ok('{"a":1}')
732
+ * ```
733
+ */
734
+ stringify: (value: unknown, replacer?: (this: any, key: string, value: any) => any, space?: string | number) => Result<TypeError, string>;
735
+ };
736
+ //#endregion
737
+ //#region src/Data/Num.d.ts
738
+ export declare const Num: {
739
+ is: {
612
740
  /**
613
- * Rounds a number to the nearest integer.
741
+ * Returns `true` when the number is equal to zero.
614
742
  *
615
743
  * @example
616
744
  * ```ts
617
- * pipe(3.5, Num.round); // 4
618
- * pipe(3.4, Num.round); // 3
745
+ * Num.is.zero(0); // true
746
+ * Num.is.zero(5); // false
619
747
  * ```
620
748
  */
621
- round: (n: number) => number;
749
+ zero: (n: number) => boolean;
622
750
  /**
623
- * Rounds a number down to the nearest integer.
751
+ * Returns `true` when the number is a whole integer.
624
752
  *
625
753
  * @example
626
754
  * ```ts
627
- * pipe(3.9, Num.floor); // 3
628
- * pipe(-3.2, Num.floor); // -4
755
+ * Num.is.integer(5); // true
756
+ * Num.is.integer(3.14); // false
629
757
  * ```
630
758
  */
631
- floor: (n: number) => number;
759
+ integer: (n: number) => boolean;
632
760
  /**
633
- * Rounds a number up to the nearest integer.
761
+ * Returns `true` when the number is a finite float (fractional number).
634
762
  *
635
763
  * @example
636
764
  * ```ts
637
- * pipe(3.1, Num.ceil); // 4
638
- * pipe(-3.9, Num.ceil); // -3
765
+ * Num.is.float(3.14); // true
766
+ * Num.is.float(5); // false
639
767
  * ```
640
768
  */
641
- ceil: (n: number) => number;
769
+ float: (n: number) => boolean;
642
770
  /**
643
- * Returns the remainder of dividing a number by `divisor`. Returns `None` when `divisor` is zero.
644
- * Data-last: `remainder(divisor)(a)` = `a % divisor`.
771
+ * Returns `true` when the number is finite (not `Infinity`, `-Infinity`, or `NaN`).
645
772
  *
646
773
  * @example
647
774
  * ```ts
648
- * pipe(10, Num.remainder(3)); // Some(1)
649
- * pipe(5, Num.remainder(0)); // None
650
- * pipe([10, 11, 12], Arr.filterMap(Num.remainder(3))); // [1, 2, 0]
775
+ * Num.is.finite(42); // true
776
+ * Num.is.finite(Infinity); // false
651
777
  * ```
652
778
  */
653
- remainder: (divisor: number) => (n: number) => Maybe<number>;
779
+ finite: (n: number) => boolean;
654
780
  /**
655
- * Computes the sum of a list of numbers. Returns `0` if the list is empty.
781
+ * Returns `true` when the value is `NaN`.
656
782
  *
657
783
  * @example
658
784
  * ```ts
659
- * Num.sum([1, 2, 3]); // 6
660
- * Num.sum([]); // 0
785
+ * Num.is.nan(NaN); // true
786
+ * Num.is.nan(42); // false
661
787
  * ```
662
788
  */
663
- sum: (ns: readonly number[]) => number;
789
+ nan: (n: number) => boolean;
664
790
  /**
665
- * Computes the mean of a list of numbers. Returns `None` if the list is empty.
791
+ * Returns `true` when the number is an even integer.
666
792
  *
667
793
  * @example
668
794
  * ```ts
669
- * Num.mean([1, 2, 3]); // Some(2)
670
- * Num.mean([]); // None
795
+ * Num.is.even(4); // true
796
+ * Num.is.even(3); // false
797
+ * Num.is.even(2.5); // false
671
798
  * ```
672
799
  */
673
- mean: (ns: readonly number[]) => Maybe<number>;
800
+ even: (n: number) => boolean;
674
801
  /**
675
- * Computes the minimum of a list of numbers. Returns `None` if the list is empty.
802
+ * Returns `true` when the number is an odd integer.
676
803
  *
677
804
  * @example
678
805
  * ```ts
679
- * Num.min([5, 1, 3]); // Some(1)
680
- * Num.min([]); // None
806
+ * Num.is.odd(3); // true
807
+ * Num.is.odd(4); // false
808
+ * Num.is.odd(2.5); // false
681
809
  * ```
682
810
  */
683
- min: (ns: readonly number[]) => Maybe<number>;
811
+ odd: (n: number) => boolean;
684
812
  /**
685
- * Computes the maximum of a list of numbers. Returns `None` if the list is empty.
813
+ * Returns `true` when the number is strictly greater than zero.
686
814
  *
687
815
  * @example
688
816
  * ```ts
689
- * Num.max([1, 5, 3]); // Some(5)
690
- * Num.max([]); // None
817
+ * Num.is.positive(5); // true
818
+ * Num.is.positive(0); // false
819
+ * Num.is.positive(-5); // false
691
820
  * ```
692
821
  */
693
- max: (ns: readonly number[]) => Maybe<number>;
822
+ positive: (n: number) => boolean;
694
823
  /**
695
- * Formats a number using `Intl.NumberFormat`. Returns `None` when `n` is `NaN` or non-finite.
696
- * Data-last curried signature.
824
+ * Returns `true` when the number is strictly less than zero.
697
825
  *
698
826
  * @example
699
827
  * ```ts
700
- * const formatCurrency = Num.format({ style: "currency", currency: "USD" }, "en-US");
701
- * pipe(1234.5, formatCurrency); // Some("$1,234.50")
702
- * pipe(NaN, formatCurrency); // None
828
+ * Num.is.negative(-5); // true
829
+ * Num.is.negative(0); // false
830
+ * Num.is.negative(5); // false
703
831
  * ```
704
832
  */
705
- format: (options?: Intl.NumberFormatOptions, locales?: string | string[]) => (n: number) => Maybe<string>;
833
+ negative: (n: number) => boolean;
834
+ };
835
+ /**
836
+ * Generates an array of numbers from `from` to `to` (both inclusive),
837
+ * stepping by `step` (default `1`). If `step` is negative or zero, or `from > to`,
838
+ * returns an empty array. When `step` does not land exactly on `to`, the last value
839
+ * is the largest reachable value that does not exceed `to`.
840
+ *
841
+ * @example
842
+ * ```ts
843
+ * Num.range(0, 5); // [0, 1, 2, 3, 4, 5]
844
+ * Num.range(0, 10, 2); // [0, 2, 4, 6, 8, 10]
845
+ * Num.range(0, 9, 2); // [0, 2, 4, 6, 8]
846
+ * Num.range(5, 0); // []
847
+ * Num.range(3, 3); // [3]
848
+ * ```
849
+ */
850
+ range: (from: number, to: number, step?: number) => readonly number[];
851
+ /**
852
+ * Clamps a number between `min` and `max` (both inclusive).
853
+ *
854
+ * @example
855
+ * ```ts
856
+ * pipe(150, Num.clamp(0, 100)); // 100
857
+ * pipe(-5, Num.clamp(0, 100)); // 0
858
+ * pipe(42, Num.clamp(0, 100)); // 42
859
+ * ```
860
+ */
861
+ clamp: (min: number, max: number) => (n: number) => number;
862
+ /**
863
+ * Returns `true` when the number is between `min` and `max` (both inclusive).
864
+ *
865
+ * @example
866
+ * ```ts
867
+ * pipe(5, Num.between(1, 10)); // true
868
+ * pipe(0, Num.between(1, 10)); // false
869
+ * pipe(10, Num.between(1, 10)); // true
870
+ * ```
871
+ */
872
+ between: (min: number, max: number) => (n: number) => boolean;
873
+ /**
874
+ * Returns `true` when the number is in the range `[start, end)` (inclusive of `start`, exclusive of `end`).
875
+ *
876
+ * @example
877
+ * ```ts
878
+ * pipe(5, Num.inRange(1, 10)); // true
879
+ * pipe(1, Num.inRange(1, 10)); // true
880
+ * pipe(10, Num.inRange(1, 10)); // false
881
+ * ```
882
+ */
883
+ inRange: (start: number, end: number) => (n: number) => boolean;
884
+ /**
885
+ * Parses a string as a number. Returns `None` when the result is `NaN`.
886
+ *
887
+ * @example
888
+ * ```ts
889
+ * Num.parse("42"); // Some(42)
890
+ * Num.parse("3.14"); // Some(3.14)
891
+ * Num.parse("abc"); // None
892
+ * Num.parse(""); // None
893
+ * ```
894
+ */
895
+ parse: (s: string) => Maybe<number>;
896
+ /**
897
+ * Adds `b` to a number. Data-last: use in `pipe` or `Arr.map`.
898
+ *
899
+ * @example
900
+ * ```ts
901
+ * pipe(5, Num.add(3)); // 8
902
+ * pipe([1, 2, 3], Arr.map(Num.add(10))); // [11, 12, 13]
903
+ * ```
904
+ */
905
+ add: (b: number) => (a: number) => number;
906
+ /**
907
+ * Subtracts `b` from a number. Data-last: `subtract(b)(a)` = `a - b`.
908
+ *
909
+ * @example
910
+ * ```ts
911
+ * pipe(10, Num.subtract(3)); // 7
912
+ * pipe([5, 10, 15], Arr.map(Num.subtract(2))); // [3, 8, 13]
913
+ * ```
914
+ */
915
+ subtract: (b: number) => (a: number) => number;
916
+ /**
917
+ * Multiplies a number by `b`. Data-last: use in `pipe` or `Arr.map`.
918
+ *
919
+ * @example
920
+ * ```ts
921
+ * pipe(6, Num.multiply(7)); // 42
922
+ * pipe([1, 2, 3], Arr.map(Num.multiply(100))); // [100, 200, 300]
923
+ * ```
924
+ */
925
+ multiply: (b: number) => (a: number) => number;
926
+ /**
927
+ * Divides a number by `b`. Returns `None` when `b` is zero. Data-last: `divide(b)(a)` = `a / b`.
928
+ *
929
+ * @example
930
+ * ```ts
931
+ * pipe(20, Num.divide(4)); // Some(5)
932
+ * pipe(5, Num.divide(0)); // None
933
+ * pipe([10, 20, 30], Arr.filterMap(Num.divide(10))); // [1, 2, 3]
934
+ * ```
935
+ */
936
+ divide: (b: number) => (a: number) => Maybe<number>;
937
+ /**
938
+ * Returns the absolute value of a number.
939
+ *
940
+ * @example
941
+ * ```ts
942
+ * pipe(-5, Num.abs); // 5
943
+ * pipe(5, Num.abs); // 5
944
+ * ```
945
+ */
946
+ abs: (n: number) => number;
947
+ /**
948
+ * Negates a number (arithmetic negation).
949
+ *
950
+ * @example
951
+ * ```ts
952
+ * pipe(5, Num.negate); // -5
953
+ * pipe(-5, Num.negate); // 5
954
+ * ```
955
+ */
956
+ negate: (n: number) => number;
957
+ /**
958
+ * Rounds a number to the nearest integer.
959
+ *
960
+ * @example
961
+ * ```ts
962
+ * pipe(3.5, Num.round); // 4
963
+ * pipe(3.4, Num.round); // 3
964
+ * ```
965
+ */
966
+ round: (n: number) => number;
967
+ /**
968
+ * Rounds a number down to the nearest integer.
969
+ *
970
+ * @example
971
+ * ```ts
972
+ * pipe(3.9, Num.floor); // 3
973
+ * pipe(-3.2, Num.floor); // -4
974
+ * ```
975
+ */
976
+ floor: (n: number) => number;
977
+ /**
978
+ * Rounds a number up to the nearest integer.
979
+ *
980
+ * @example
981
+ * ```ts
982
+ * pipe(3.1, Num.ceil); // 4
983
+ * pipe(-3.9, Num.ceil); // -3
984
+ * ```
985
+ */
986
+ ceil: (n: number) => number;
987
+ /**
988
+ * Returns the remainder of dividing a number by `divisor`. Returns `None` when `divisor` is zero.
989
+ * Data-last: `remainder(divisor)(a)` = `a % divisor`.
990
+ *
991
+ * @example
992
+ * ```ts
993
+ * pipe(10, Num.remainder(3)); // Some(1)
994
+ * pipe(5, Num.remainder(0)); // None
995
+ * pipe([10, 11, 12], Arr.filterMap(Num.remainder(3))); // [1, 2, 0]
996
+ * ```
997
+ */
998
+ remainder: (divisor: number) => (n: number) => Maybe<number>;
999
+ /**
1000
+ * Computes the sum of a list of numbers. Returns `0` if the list is empty.
1001
+ *
1002
+ * @example
1003
+ * ```ts
1004
+ * Num.sum([1, 2, 3]); // 6
1005
+ * Num.sum([]); // 0
1006
+ * ```
1007
+ */
1008
+ sum: (ns: readonly number[]) => number;
1009
+ /**
1010
+ * Computes the mean of a list of numbers. Returns `None` if the list is empty.
1011
+ *
1012
+ * @example
1013
+ * ```ts
1014
+ * Num.mean([1, 2, 3]); // Some(2)
1015
+ * Num.mean([]); // None
1016
+ * ```
1017
+ */
1018
+ mean: (ns: readonly number[]) => Maybe<number>;
1019
+ /**
1020
+ * Computes the minimum of a list of numbers. Returns `None` if the list is empty.
1021
+ *
1022
+ * @example
1023
+ * ```ts
1024
+ * Num.min([5, 1, 3]); // Some(1)
1025
+ * Num.min([]); // None
1026
+ * ```
1027
+ */
1028
+ min: (ns: readonly number[]) => Maybe<number>;
1029
+ /**
1030
+ * Computes the maximum of a list of numbers. Returns `None` if the list is empty.
1031
+ *
1032
+ * @example
1033
+ * ```ts
1034
+ * Num.max([1, 5, 3]); // Some(5)
1035
+ * Num.max([]); // None
1036
+ * ```
1037
+ */
1038
+ max: (ns: readonly number[]) => Maybe<number>;
1039
+ /**
1040
+ * Formats a number using `Intl.NumberFormat`. Returns `None` when `n` is `NaN` or non-finite.
1041
+ * Data-last curried signature.
1042
+ *
1043
+ * @example
1044
+ * ```ts
1045
+ * const formatCurrency = Num.format({ style: "currency", currency: "USD" }, "en-US");
1046
+ * pipe(1234.5, formatCurrency); // Some("$1,234.50")
1047
+ * pipe(NaN, formatCurrency); // None
1048
+ * ```
1049
+ */
1050
+ format: (options?: Intl.NumberFormatOptions, locales?: string | string[]) => (n: number) => Maybe<string>;
706
1051
  };
707
-
1052
+ //#endregion
1053
+ //#region src/Data/Rec.d.ts
708
1054
  /**
709
1055
  * A branded type representing a record with at least one key-value pair.
710
1056
  */
711
- type NonEmptyRecord<A, K extends string = string> = Brand<NonEmpty<"Rec">, Readonly<Record<K, A>>>;
1057
+ export type NonEmptyRecord<A, K extends string = string> = Brand<NonEmpty<"Rec">, Readonly<Record<K, A>>>;
712
1058
  /**
713
1059
  * Merges two records using a custom combination function on key collisions.
714
1060
  * Supports both uncurried `Rec.mergeWith(combine)(first, second)` and curried `pipe(first, Rec.mergeWith(combine)(second))`.
@@ -721,407 +1067,408 @@ type NonEmptyRecord<A, K extends string = string> = Brand<NonEmpty<"Rec">, Reado
721
1067
  * ```
722
1068
  */
723
1069
  declare function mergeWith<A>(combine: (a: A, b: A) => A): {
724
- (second: Readonly<Record<string, A>>): (first: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
725
- (first: Readonly<Record<string, A>>, second: Readonly<Record<string, A>>): Readonly<Record<string, A>>;
1070
+ (second: Readonly<Record<string, A>>): (first: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
1071
+ (first: Readonly<Record<string, A>>, second: Readonly<Record<string, A>>): Readonly<Record<string, A>>;
726
1072
  };
727
- declare const Rec: {
728
- is: {
729
- /**
730
- * Returns true if the record has no keys.
731
- *
732
- * @example
733
- * ```ts
734
- * Rec.is.empty({}); // true
735
- * Rec.is.empty({ a: 1 }); // false
736
- * ```
737
- */
738
- empty: <A>(data: Readonly<Record<string, A>>) => boolean;
739
- /**
740
- * Type guard to check if a record is non-empty.
741
- *
742
- * @example
743
- * ```ts
744
- * Rec.is.nonEmpty({ a: 1 }); // true
745
- * Rec.is.nonEmpty({}); // false
746
- * ```
747
- */
748
- nonEmpty: <A, K extends string>(data: Readonly<Record<K, A>>) => data is NonEmptyRecord<A, K>;
749
- };
750
- from: {
751
- /**
752
- * Creates a record from key-value pairs.
753
- *
754
- * @example
755
- * ```ts
756
- * Rec.from.entries([["a", 1], ["b", 2]]); // { a: 1, b: 2 }
757
- * ```
758
- */
759
- entries: <A>(data: readonly (readonly [string, A])[]) => Readonly<Record<string, A>>;
760
- };
761
- to: {
762
- Dict: <A, K extends string = string>(data: Readonly<Record<K, A>>) => ReadonlyMap<K, A>;
763
- };
764
- map: <A, B>(f: (a: A) => B) => <K extends string>(data: Readonly<Record<K, A>>) => Readonly<Record<K, B>>;
765
- filterMap: <A, B>(f: (a: A) => Maybe<B>) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, B>>;
766
- mapWithKey: <A, B>(f: (key: string, a: A) => B) => <K extends string>(data: Readonly<Record<K, A>>) => Readonly<Record<K, B>>;
767
- filter: <A>(predicate: (a: A) => boolean) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
768
- filterWithKey: <A>(predicate: (key: string, a: A) => boolean) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
769
- lookup: <K extends string>(key: K) => <V>(data: Record<string, V>) => Maybe<V>;
770
- keys: <T extends Record<string, unknown>>(data: T) => readonly (keyof T & string)[];
771
- values: <T extends Record<string, unknown>>(data: T) => readonly T[keyof T & string][];
772
- entries: <T extends Record<string, unknown>>(data: T) => readonly (readonly [keyof T, T[keyof T]])[];
773
- groupBy: <A>(keyFn: (a: A) => string) => (items: readonly A[]) => Readonly<Record<string, readonly A[]>>;
774
- pick: <K extends string>(...pickedKeys: K[]) => <A extends Record<K, unknown>>(data: A) => Pick<A, K>;
775
- omit: <K extends string>(...omittedKeys: K[]) => <A extends Record<K, unknown>>(data: A) => Omit<A, K>;
776
- merge: <A>(other: Readonly<Record<string, A>>) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
777
- mergeWith: typeof mergeWith;
778
- size: <A>(data: Readonly<Record<string, A>>) => number;
779
- mapKeys: (f: (key: string) => string) => <A>(data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
780
- compact: <A>(data: Readonly<Record<string, Maybe<A>>>) => Readonly<Record<string, A>>;
781
- mapEntries: <A, K2 extends string, B>(f: (key: string, value: A) => readonly [K2, B]) => (data: Readonly<Record<string, A>>) => Readonly<Record<K2, B>>;
782
- updateIn: <T>(path: readonly [string, ...string[]], f: (val: T) => T) => (data: Readonly<Record<string, unknown>>) => Readonly<Record<string, unknown>>;
783
- traverse: {
784
- Maybe: <A, B>(f: (a: A) => Maybe<B>) => (data: Readonly<Record<string, A>>) => Maybe<Readonly<Record<string, B>>>;
785
- Result: <E, A, B>(f: (a: A) => Result<E, B>) => (data: Readonly<Record<string, A>>) => Result<E, Readonly<Record<string, B>>>;
786
- };
787
- sequence: {
788
- Maybe: <A>(data: Readonly<Record<string, Maybe<A>>>) => Maybe<Readonly<Record<string, A>>>;
789
- Result: <E, A>(data: Readonly<Record<string, Result<E, A>>>) => Result<E, Readonly<Record<string, A>>>;
790
- };
791
- NonEmpty: {
792
- singleton: <K extends string, A>(key: K, value: A) => NonEmptyRecord<A, K>;
793
- from: {
794
- Record: <K extends string, A>(data: Readonly<Record<K, A>>) => Maybe<NonEmptyRecord<A, K>>;
795
- };
796
- keys: <K extends string, A>(data: NonEmptyRecord<A, K>) => NonEmptyArr<K>;
797
- values: <K extends string, A>(data: NonEmptyRecord<A, K>) => NonEmptyArr<A>;
798
- entries: <K extends string, A>(data: NonEmptyRecord<A, K>) => NonEmptyArr<readonly [K, A]>;
799
- reduce: <A>(f: (acc: A, a: A) => A) => <K extends string>(data: NonEmptyRecord<A, K>) => A;
800
- map: <A, B>(f: (a: A) => B) => <K extends string>(data: NonEmptyRecord<A, K>) => NonEmptyRecord<B, K>;
801
- mapWithKey: <A, B>(f: (key: string, a: A) => B) => <K extends string>(data: NonEmptyRecord<A, K>) => NonEmptyRecord<B, K>;
802
- };
803
- };
804
- declare namespace Rec {
805
- type NonEmpty<A, K extends string = string> = NonEmptyRecord<A, K>;
806
- }
807
-
808
- /**
809
- * A branded type representing a string with at least one character.
810
- */
811
- type NonEmptyString = Brand<NonEmpty<"Str">, string>;
812
- declare const Str: {
813
- is: {
814
- /**
815
- * Returns `true` when the string is empty.
816
- *
817
- * @example
818
- * ```ts
819
- * pipe("", Str.is.empty); // true
820
- * pipe("hi", Str.is.empty); // false
821
- * ```
822
- */
823
- empty: (s: string) => boolean;
824
- /**
825
- * Type guard to check if a string is non-empty.
826
- */
827
- nonEmpty: (s: string) => s is NonEmptyString;
828
- };
829
- /**
830
- * Splits a string by a separator. Data-last: use in `pipe`.
831
- *
832
- * @example
833
- * ```ts
834
- * pipe("a,b,c", Str.split(",")); // ["a", "b", "c"]
835
- * ```
836
- */
837
- split: (separator: string | RegExp) => (s: string) => readonly string[];
838
- /**
839
- * Removes leading and trailing whitespace from a string.
840
- *
841
- * @example
842
- * ```ts
843
- * pipe(" hello ", Str.trim); // "hello"
844
- * ```
845
- */
846
- trim: (s: string) => string;
847
- /**
848
- * Returns `true` when the string contains the given substring.
849
- *
850
- * @example
851
- * ```ts
852
- * pipe("hello world", Str.includes("world")); // true
853
- * pipe("hello world", Str.includes("xyz")); // false
854
- * ```
855
- */
856
- includes: (substring: string) => (s: string) => boolean;
857
- /**
858
- * Replaces the first occurrence of a pattern in a string. Data-last: use in `pipe`.
859
- *
860
- * @example
861
- * ```ts
862
- * pipe("foo foo foo", Str.replace("foo", "bar")); // "bar foo foo"
863
- * pipe("Hello World", Str.replace(/world/i, "Earth")); // "Hello Earth"
864
- * ```
865
- */
866
- replace: (pattern: string | RegExp, replacement: string) => (s: string) => string;
867
- /**
868
- * Replaces all occurrences of a pattern in a string. Data-last: use in `pipe`.
869
- *
870
- * @example
871
- * ```ts
872
- * pipe("foo foo foo", Str.replaceAll("foo", "bar")); // "bar bar bar"
873
- * pipe("aAbBaA", Str.replaceAll(/a/gi, "x")); // "xxBBxx"
874
- * ```
875
- */
876
- replaceAll: (pattern: string | RegExp, replacement: string) => (s: string) => string;
1073
+ export declare const Rec: {
1074
+ is: {
877
1075
  /**
878
- * Returns `true` when the string starts with the given prefix.
1076
+ * Returns true if the record has no keys.
879
1077
  *
880
1078
  * @example
881
1079
  * ```ts
882
- * pipe("hello world", Str.startsWith("hello")); // true
883
- * pipe("hello world", Str.startsWith("world")); // false
1080
+ * Rec.is.empty({}); // true
1081
+ * Rec.is.empty({ a: 1 }); // false
884
1082
  * ```
885
1083
  */
886
- startsWith: (prefix: string) => (s: string) => boolean;
1084
+ empty: <A>(data: Readonly<Record<string, A>>) => boolean;
887
1085
  /**
888
- * Returns `true` when the string ends with the given suffix.
1086
+ * Type guard to check if a record is non-empty.
889
1087
  *
890
1088
  * @example
891
1089
  * ```ts
892
- * pipe("hello world", Str.endsWith("world")); // true
893
- * pipe("hello world", Str.endsWith("hello")); // false
1090
+ * Rec.is.nonEmpty({ a: 1 }); // true
1091
+ * Rec.is.nonEmpty({}); // false
894
1092
  * ```
895
1093
  */
896
- endsWith: (suffix: string) => (s: string) => boolean;
1094
+ nonEmpty: <A, K extends string>(data: Readonly<Record<K, A>>) => data is NonEmptyRecord<A, K>;
1095
+ };
1096
+ from: {
897
1097
  /**
898
- * Converts a string to uppercase.
1098
+ * Creates a record from key-value pairs.
899
1099
  *
900
1100
  * @example
901
1101
  * ```ts
902
- * pipe("hello", Str.toUpperCase); // "HELLO"
1102
+ * Rec.from.entries([["a", 1], ["b", 2]]); // { a: 1, b: 2 }
903
1103
  * ```
904
1104
  */
905
- toUpperCase: (s: string) => string;
906
- /**
907
- * Converts a string to lowercase.
908
- *
909
- * @example
910
- * ```ts
911
- * pipe("HELLO", Str.toLowerCase); // "hello"
912
- * ```
913
- */
914
- toLowerCase: (s: string) => string;
915
- /**
916
- * Converts the first character of a string to uppercase.
917
- *
918
- * @example
919
- * ```ts
920
- * pipe("hello", Str.capitalize); // "Hello"
921
- * ```
922
- */
923
- capitalize: (s: string) => string;
924
- /**
925
- * Splits a string into lines, normalising `\r\n` and `\r` line endings.
926
- *
927
- * @example
928
- * ```ts
929
- * Str.lines("one\ntwo\nthree"); // ["one", "two", "three"]
930
- * Str.lines("a\r\nb"); // ["a", "b"]
931
- * ```
932
- */
933
- lines: (s: string) => readonly string[];
934
- /**
935
- * Splits a string into words on any whitespace boundary, filtering out empty strings.
936
- *
937
- * @example
938
- * ```ts
939
- * Str.words(" hello world "); // ["hello", "world"]
940
- * ```
941
- */
942
- words: (s: string) => readonly string[];
943
- /**
944
- * Returns `true` when the string is empty or contains only whitespace.
945
- *
946
- * @example
947
- * ```ts
948
- * pipe(" ", Str.isBlank); // true
949
- * pipe("hi", Str.isBlank); // false
950
- * ```
951
- */
952
- isBlank: (s: string) => boolean;
953
- /**
954
- * Returns the length of the string.
955
- *
956
- * @example
957
- * ```ts
958
- * pipe("hello", Str.length); // 5
959
- * pipe("", Str.length); // 0
960
- * ```
961
- */
962
- length: (s: string) => number;
963
- /**
964
- * Extracts a substring between two indices. Data-last: use in `pipe`.
965
- *
966
- * @example
967
- * ```ts
968
- * pipe("hello", Str.slice(1, 3)); // "el"
969
- * pipe("hello", Str.slice(2)); // "llo"
970
- * ```
971
- */
972
- slice: (start: number, end?: number) => (s: string) => string;
973
- /**
974
- * Pads the start of a string to a specified length. Data-last: use in `pipe`.
975
- *
976
- * @example
977
- * ```ts
978
- * pipe("5", Str.padStart(3, "0")); // "005"
979
- * pipe("hi", Str.padStart(5)); // " hi"
980
- * ```
981
- */
982
- padStart: (maxLength: number, fillString?: string) => (s: string) => string;
1105
+ entries: <A>(data: readonly (readonly [string, A])[]) => Readonly<Record<string, A>>;
1106
+ };
1107
+ to: {
1108
+ Dict: <A, K extends string = string>(data: Readonly<Record<K, A>>) => ReadonlyMap<K, A>;
1109
+ };
1110
+ map: <A, B>(f: (a: A) => B) => <K extends string>(data: Readonly<Record<K, A>>) => Readonly<Record<K, B>>;
1111
+ filterMap: <A, B>(f: (a: A) => Maybe<B>) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, B>>;
1112
+ mapWithKey: <A, B>(f: (key: string, a: A) => B) => <K extends string>(data: Readonly<Record<K, A>>) => Readonly<Record<K, B>>;
1113
+ filter: <A>(predicate: (a: A) => boolean) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
1114
+ filterWithKey: <A>(predicate: (key: string, a: A) => boolean) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
1115
+ lookup: <K extends string>(key: K) => <V>(data: Record<string, V>) => Maybe<V>;
1116
+ keys: <T extends Record<string, unknown>>(data: T) => readonly (keyof T & string)[];
1117
+ values: <T extends Record<string, unknown>>(data: T) => readonly T[keyof T & string][];
1118
+ entries: <T extends Record<string, unknown>>(data: T) => readonly (readonly [keyof T, T[keyof T]])[];
1119
+ groupBy: <A>(keyFn: (a: A) => string) => (items: readonly A[]) => Readonly<Record<string, readonly A[]>>;
1120
+ pick: <K extends string>(...pickedKeys: K[]) => <A extends Record<K, unknown>>(data: A) => Pick<A, K>;
1121
+ omit: <K extends string>(...omittedKeys: K[]) => <A extends Record<K, unknown>>(data: A) => Omit<A, K>;
1122
+ merge: <A>(other: Readonly<Record<string, A>>) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
1123
+ mergeWith: typeof mergeWith;
1124
+ size: <A>(data: Readonly<Record<string, A>>) => number;
1125
+ mapKeys: (f: (key: string) => string) => <A>(data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
1126
+ compact: <A>(data: Readonly<Record<string, Maybe<A>>>) => Readonly<Record<string, A>>;
1127
+ mapEntries: <A, K2 extends string, B>(f: (key: string, value: A) => readonly [K2, B]) => (data: Readonly<Record<string, A>>) => Readonly<Record<K2, B>>;
1128
+ updateIn: <T>(path: readonly [string, ...string[]], f: (val: T) => T) => (data: Readonly<Record<string, unknown>>) => Readonly<Record<string, unknown>>;
1129
+ traverse: {
1130
+ Maybe: <A, B>(f: (a: A) => Maybe<B>) => (data: Readonly<Record<string, A>>) => Maybe<Readonly<Record<string, B>>>;
1131
+ Result: <E, A, B>(f: (a: A) => Result<E, B>) => (data: Readonly<Record<string, A>>) => Result<E, Readonly<Record<string, B>>>;
1132
+ };
1133
+ sequence: {
1134
+ Maybe: <A>(data: Readonly<Record<string, Maybe<A>>>) => Maybe<Readonly<Record<string, A>>>;
1135
+ Result: <E, A>(data: Readonly<Record<string, Result<E, A>>>) => Result<E, Readonly<Record<string, A>>>;
1136
+ };
1137
+ NonEmpty: {
1138
+ singleton: <K extends string, A>(key: K, value: A) => NonEmptyRecord<A, K>;
1139
+ from: {
1140
+ Record: <K extends string, A>(data: Readonly<Record<K, A>>) => Maybe<NonEmptyRecord<A, K>>;
1141
+ };
1142
+ keys: <K extends string, A>(data: NonEmptyRecord<A, K>) => NonEmptyArr<K>;
1143
+ values: <K extends string, A>(data: NonEmptyRecord<A, K>) => NonEmptyArr<A>;
1144
+ entries: <K extends string, A>(data: NonEmptyRecord<A, K>) => NonEmptyArr<readonly [K, A]>;
1145
+ reduce: <A>(f: (acc: A, a: A) => A) => <K extends string>(data: NonEmptyRecord<A, K>) => A;
1146
+ map: <A, B>(f: (a: A) => B) => <K extends string>(data: NonEmptyRecord<A, K>) => NonEmptyRecord<B, K>;
1147
+ mapWithKey: <A, B>(f: (key: string, a: A) => B) => <K extends string>(data: NonEmptyRecord<A, K>) => NonEmptyRecord<B, K>;
1148
+ };
1149
+ };
1150
+ export declare namespace Rec {
1151
+ type NonEmpty<A, K extends string = string> = NonEmptyRecord<A, K>;
1152
+ }
1153
+ //#endregion
1154
+ //#region src/Data/Str.d.ts
1155
+ /**
1156
+ * A branded type representing a string with at least one character.
1157
+ */
1158
+ export type NonEmptyString = Brand<NonEmpty<"Str">, string>;
1159
+ export declare const Str: {
1160
+ is: {
983
1161
  /**
984
- * Pads the end of a string to a specified length. Data-last: use in `pipe`.
1162
+ * Returns `true` when the string is empty.
985
1163
  *
986
1164
  * @example
987
1165
  * ```ts
988
- * pipe("hi", Str.padEnd(5, ".")); // "hi..."
989
- * pipe("hi", Str.padEnd(5)); // "hi "
1166
+ * pipe("", Str.is.empty); // true
1167
+ * pipe("hi", Str.is.empty); // false
990
1168
  * ```
991
1169
  */
992
- padEnd: (maxLength: number, fillString?: string) => (s: string) => string;
993
- /**
994
- * Safe number parsers that return `Maybe` instead of `NaN`.
995
- */
996
- parse: {
997
- /**
998
- * Parses a string as an integer (base 10). Returns `None` if the result is `NaN`.
999
- *
1000
- * @example
1001
- * ```ts
1002
- * Str.parse.int("42"); // Some(42)
1003
- * Str.parse.int("3.7"); // Some(3)
1004
- * Str.parse.int("abc"); // None
1005
- * ```
1006
- */
1007
- int: (s: string) => Maybe<number>;
1008
- /**
1009
- * Parses a string as a floating-point number. Returns `None` if the result is `NaN`.
1010
- *
1011
- * @example
1012
- * ```ts
1013
- * Str.parse.float("3.14"); // Some(3.14)
1014
- * Str.parse.float("42"); // Some(42)
1015
- * Str.parse.float("abc"); // None
1016
- * ```
1017
- */
1018
- float: (s: string) => Maybe<number>;
1019
- };
1170
+ empty: (s: string) => boolean;
1020
1171
  /**
1021
- * Safely parses a JSON string, returning a `Result<SyntaxError, unknown>`.
1022
- *
1023
- * @example
1024
- * ```ts
1025
- * Str.parseJson('{"a": 1}'); // Ok({ a: 1 })
1026
- * Str.parseJson('invalid'); // Err(SyntaxError)
1027
- * ```
1172
+ * Type guard to check if a string is non-empty.
1028
1173
  */
1029
- parseJson: (s: string) => Result<SyntaxError, unknown>;
1174
+ nonEmpty: (s: string) => s is NonEmptyString;
1175
+ };
1176
+ /**
1177
+ * Splits a string by a separator. Data-last: use in `pipe`.
1178
+ *
1179
+ * @example
1180
+ * ```ts
1181
+ * pipe("a,b,c", Str.split(",")); // ["a", "b", "c"]
1182
+ * ```
1183
+ */
1184
+ split: (separator: string | RegExp) => (s: string) => readonly string[];
1185
+ /**
1186
+ * Removes leading and trailing whitespace from a string.
1187
+ *
1188
+ * @example
1189
+ * ```ts
1190
+ * pipe(" hello ", Str.trim); // "hello"
1191
+ * ```
1192
+ */
1193
+ trim: (s: string) => string;
1194
+ /**
1195
+ * Returns `true` when the string contains the given substring.
1196
+ *
1197
+ * @example
1198
+ * ```ts
1199
+ * pipe("hello world", Str.includes("world")); // true
1200
+ * pipe("hello world", Str.includes("xyz")); // false
1201
+ * ```
1202
+ */
1203
+ includes: (substring: string) => (s: string) => boolean;
1204
+ /**
1205
+ * Replaces the first occurrence of a pattern in a string. Data-last: use in `pipe`.
1206
+ *
1207
+ * @example
1208
+ * ```ts
1209
+ * pipe("foo foo foo", Str.replace("foo", "bar")); // "bar foo foo"
1210
+ * pipe("Hello World", Str.replace(/world/i, "Earth")); // "Hello Earth"
1211
+ * ```
1212
+ */
1213
+ replace: (pattern: string | RegExp, replacement: string) => (s: string) => string;
1214
+ /**
1215
+ * Replaces all occurrences of a pattern in a string. Data-last: use in `pipe`.
1216
+ *
1217
+ * @example
1218
+ * ```ts
1219
+ * pipe("foo foo foo", Str.replaceAll("foo", "bar")); // "bar bar bar"
1220
+ * pipe("aAbBaA", Str.replaceAll(/a/gi, "x")); // "xxBBxx"
1221
+ * ```
1222
+ */
1223
+ replaceAll: (pattern: string | RegExp, replacement: string) => (s: string) => string;
1224
+ /**
1225
+ * Returns `true` when the string starts with the given prefix.
1226
+ *
1227
+ * @example
1228
+ * ```ts
1229
+ * pipe("hello world", Str.startsWith("hello")); // true
1230
+ * pipe("hello world", Str.startsWith("world")); // false
1231
+ * ```
1232
+ */
1233
+ startsWith: (prefix: string) => (s: string) => boolean;
1234
+ /**
1235
+ * Returns `true` when the string ends with the given suffix.
1236
+ *
1237
+ * @example
1238
+ * ```ts
1239
+ * pipe("hello world", Str.endsWith("world")); // true
1240
+ * pipe("hello world", Str.endsWith("hello")); // false
1241
+ * ```
1242
+ */
1243
+ endsWith: (suffix: string) => (s: string) => boolean;
1244
+ /**
1245
+ * Converts a string to uppercase.
1246
+ *
1247
+ * @example
1248
+ * ```ts
1249
+ * pipe("hello", Str.toUpperCase); // "HELLO"
1250
+ * ```
1251
+ */
1252
+ toUpperCase: (s: string) => string;
1253
+ /**
1254
+ * Converts a string to lowercase.
1255
+ *
1256
+ * @example
1257
+ * ```ts
1258
+ * pipe("HELLO", Str.toLowerCase); // "hello"
1259
+ * ```
1260
+ */
1261
+ toLowerCase: (s: string) => string;
1262
+ /**
1263
+ * Converts the first character of a string to uppercase.
1264
+ *
1265
+ * @example
1266
+ * ```ts
1267
+ * pipe("hello", Str.capitalize); // "Hello"
1268
+ * ```
1269
+ */
1270
+ capitalize: (s: string) => string;
1271
+ /**
1272
+ * Splits a string into lines, normalising `\r\n` and `\r` line endings.
1273
+ *
1274
+ * @example
1275
+ * ```ts
1276
+ * Str.lines("one\ntwo\nthree"); // ["one", "two", "three"]
1277
+ * Str.lines("a\r\nb"); // ["a", "b"]
1278
+ * ```
1279
+ */
1280
+ lines: (s: string) => readonly string[];
1281
+ /**
1282
+ * Splits a string into words on any whitespace boundary, filtering out empty strings.
1283
+ *
1284
+ * @example
1285
+ * ```ts
1286
+ * Str.words(" hello world "); // ["hello", "world"]
1287
+ * ```
1288
+ */
1289
+ words: (s: string) => readonly string[];
1290
+ /**
1291
+ * Returns `true` when the string is empty or contains only whitespace.
1292
+ *
1293
+ * @example
1294
+ * ```ts
1295
+ * pipe(" ", Str.isBlank); // true
1296
+ * pipe("hi", Str.isBlank); // false
1297
+ * ```
1298
+ */
1299
+ isBlank: (s: string) => boolean;
1300
+ /**
1301
+ * Returns the length of the string.
1302
+ *
1303
+ * @example
1304
+ * ```ts
1305
+ * pipe("hello", Str.length); // 5
1306
+ * pipe("", Str.length); // 0
1307
+ * ```
1308
+ */
1309
+ length: (s: string) => number;
1310
+ /**
1311
+ * Extracts a substring between two indices. Data-last: use in `pipe`.
1312
+ *
1313
+ * @example
1314
+ * ```ts
1315
+ * pipe("hello", Str.slice(1, 3)); // "el"
1316
+ * pipe("hello", Str.slice(2)); // "llo"
1317
+ * ```
1318
+ */
1319
+ slice: (start: number, end?: number) => (s: string) => string;
1320
+ /**
1321
+ * Pads the start of a string to a specified length. Data-last: use in `pipe`.
1322
+ *
1323
+ * @example
1324
+ * ```ts
1325
+ * pipe("5", Str.padStart(3, "0")); // "005"
1326
+ * pipe("hi", Str.padStart(5)); // " hi"
1327
+ * ```
1328
+ */
1329
+ padStart: (maxLength: number, fillString?: string) => (s: string) => string;
1330
+ /**
1331
+ * Pads the end of a string to a specified length. Data-last: use in `pipe`.
1332
+ *
1333
+ * @example
1334
+ * ```ts
1335
+ * pipe("hi", Str.padEnd(5, ".")); // "hi..."
1336
+ * pipe("hi", Str.padEnd(5)); // "hi "
1337
+ * ```
1338
+ */
1339
+ padEnd: (maxLength: number, fillString?: string) => (s: string) => string;
1340
+ /**
1341
+ * Safe number parsers that return `Maybe` instead of `NaN`.
1342
+ */
1343
+ parse: {
1030
1344
  /**
1031
- * Converts the first character of a string to lower case.
1345
+ * Parses a string as an integer (base 10). Returns `None` if the result is `NaN`.
1032
1346
  *
1033
1347
  * @example
1034
1348
  * ```ts
1035
- * Str.uncapitalize("Hello"); // "hello"
1036
- * Str.uncapitalize(""); // ""
1349
+ * Str.parse.int("42"); // Some(42)
1350
+ * Str.parse.int("3.7"); // Some(3)
1351
+ * Str.parse.int("abc"); // None
1037
1352
  * ```
1038
1353
  */
1039
- uncapitalize: (s: string) => string;
1354
+ int: (s: string) => Maybe<number>;
1040
1355
  /**
1041
- * Truncates a string to a maximum length, appending an optional suffix (default `"..."`).
1042
- * Data-last curried signature.
1356
+ * Parses a string as a floating-point number. Returns `None` if the result is `NaN`.
1043
1357
  *
1044
1358
  * @example
1045
1359
  * ```ts
1046
- * pipe("Hello, world!", Str.truncate({ length: 8 })); // "Hello..."
1047
- * pipe("Hello", Str.truncate({ length: 10 })); // "Hello"
1048
- * pipe("Hello, world!", Str.truncate({ length: 8, suffix: "…" })); // "Hello, w…"
1360
+ * Str.parse.float("3.14"); // Some(3.14)
1361
+ * Str.parse.float("42"); // Some(42)
1362
+ * Str.parse.float("abc"); // None
1049
1363
  * ```
1050
1364
  */
1051
- truncate: (options: {
1052
- length: number;
1053
- suffix?: string;
1054
- }) => (s: string) => string;
1055
- NonEmpty: {
1056
- from: {
1057
- /**
1058
- * Returns Some containing NonEmptyString if the string is not empty, None otherwise.
1059
- *
1060
- * @example
1061
- * ```ts
1062
- * Str.NonEmpty.from.String("hello"); // Some("hello")
1063
- * Str.NonEmpty.from.String(""); // None
1064
- * ```
1065
- */
1066
- String: (s: string) => Maybe<NonEmptyString>;
1067
- };
1365
+ float: (s: string) => Maybe<number>;
1366
+ };
1367
+ /**
1368
+ * Safely parses a JSON string, returning a `Result<SyntaxError, unknown>`.
1369
+ *
1370
+ * @example
1371
+ * ```ts
1372
+ * Str.parseJson('{"a": 1}'); // Ok({ a: 1 })
1373
+ * Str.parseJson('invalid'); // Err(SyntaxError)
1374
+ * ```
1375
+ */
1376
+ parseJson: (s: string) => Result<SyntaxError, unknown>;
1377
+ /**
1378
+ * Converts the first character of a string to lower case.
1379
+ *
1380
+ * @example
1381
+ * ```ts
1382
+ * Str.uncapitalize("Hello"); // "hello"
1383
+ * Str.uncapitalize(""); // ""
1384
+ * ```
1385
+ */
1386
+ uncapitalize: (s: string) => string;
1387
+ /**
1388
+ * Truncates a string to a maximum length, appending an optional suffix (default `"..."`).
1389
+ * Data-last curried signature.
1390
+ *
1391
+ * @example
1392
+ * ```ts
1393
+ * pipe("Hello, world!", Str.truncate({ length: 8 })); // "Hello..."
1394
+ * pipe("Hello", Str.truncate({ length: 10 })); // "Hello"
1395
+ * pipe("Hello, world!", Str.truncate({ length: 8, suffix: "…" })); // "Hello, w…"
1396
+ * ```
1397
+ */
1398
+ truncate: (options: {
1399
+ length: number;
1400
+ suffix?: string;
1401
+ }) => (s: string) => string;
1402
+ NonEmpty: {
1403
+ from: {
1404
+ /**
1405
+ * Returns Some containing NonEmptyString if the string is not empty, None otherwise.
1406
+ *
1407
+ * @example
1408
+ * ```ts
1409
+ * Str.NonEmpty.from.String("hello"); // Some("hello")
1410
+ * Str.NonEmpty.from.String(""); // None
1411
+ * ```
1412
+ */
1413
+ String: (s: string) => Maybe<NonEmptyString>;
1068
1414
  };
1415
+ };
1069
1416
  };
1070
- declare namespace Str {
1071
- /**
1072
- * A branded type representing a string with at least one character.
1073
- */
1074
- type NonEmpty = NonEmptyString;
1417
+ export declare namespace Str {
1418
+ /**
1419
+ * A branded type representing a string with at least one character.
1420
+ */
1421
+ type NonEmpty = NonEmptyString;
1075
1422
  }
1076
-
1423
+ //#endregion
1424
+ //#region src/Data/Uniq.d.ts
1077
1425
  /**
1078
1426
  * A branded type representing a unique collection with at least one element.
1079
1427
  */
1080
- type NonEmptySet<A> = Brand<NonEmpty<"Uniq">, ReadonlySet<A>>;
1081
- declare const Uniq: {
1082
- is: {
1083
- empty: <A>(s: ReadonlySet<A>) => boolean;
1084
- nonEmpty: <A>(s: ReadonlySet<A>) => s is NonEmptySet<A>;
1085
- };
1086
- empty: <A>() => ReadonlySet<A>;
1087
- singleton: <A>(item: A) => ReadonlySet<A>;
1428
+ export type NonEmptySet<A> = Brand<NonEmpty<"Uniq">, ReadonlySet<A>>;
1429
+ export declare const Uniq: {
1430
+ is: {
1431
+ empty: <A>(s: ReadonlySet<A>) => boolean;
1432
+ nonEmpty: <A>(s: ReadonlySet<A>) => s is NonEmptySet<A>;
1433
+ };
1434
+ empty: <A>() => ReadonlySet<A>;
1435
+ singleton: <A>(item: A) => ReadonlySet<A>;
1436
+ from: {
1437
+ Array: <A>(arr: readonly A[]) => ReadonlySet<A>;
1438
+ };
1439
+ has: <A>(item: A) => (s: ReadonlySet<A>) => boolean;
1440
+ size: <A>(s: ReadonlySet<A>) => number;
1441
+ add: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1442
+ insert: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1443
+ remove: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1444
+ toggle: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1445
+ map: <A, B>(f: (a: A) => B) => (s: ReadonlySet<A>) => ReadonlySet<B>;
1446
+ filter: <A>(predicate: (a: A) => boolean) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1447
+ filterMap: <A, B>(f: (a: A) => Maybe<B>) => (s: ReadonlySet<A>) => ReadonlySet<B>;
1448
+ union: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1449
+ intersection: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1450
+ difference: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1451
+ isSubsetOf: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => boolean;
1452
+ reduce: <A, B>(init: B, f: (acc: B, a: A) => B) => (s: ReadonlySet<A>) => B;
1453
+ to: {
1454
+ Array: <A>(s: ReadonlySet<A>) => readonly A[];
1455
+ };
1456
+ NonEmpty: {
1457
+ singleton: <A>(item: A) => NonEmptySet<A>;
1088
1458
  from: {
1089
- Array: <A>(arr: readonly A[]) => ReadonlySet<A>;
1459
+ Set: <A>(s: ReadonlySet<A>) => Maybe<NonEmptySet<A>>;
1090
1460
  };
1091
- has: <A>(item: A) => (s: ReadonlySet<A>) => boolean;
1092
- size: <A>(s: ReadonlySet<A>) => number;
1093
- add: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1094
- insert: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1095
- remove: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1096
- toggle: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1097
- map: <A, B>(f: (a: A) => B) => (s: ReadonlySet<A>) => ReadonlySet<B>;
1098
- filter: <A>(predicate: (a: A) => boolean) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1099
- filterMap: <A, B>(f: (a: A) => Maybe<B>) => (s: ReadonlySet<A>) => ReadonlySet<B>;
1100
- union: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1101
- intersection: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1102
- difference: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
1103
- isSubsetOf: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => boolean;
1104
- reduce: <A, B>(init: B, f: (acc: B, a: A) => B) => (s: ReadonlySet<A>) => B;
1461
+ reduce: <A>(f: (acc: A, a: A) => A) => (s: NonEmptySet<A>) => A;
1462
+ map: <A, B>(f: (a: A) => B) => (s: NonEmptySet<A>) => NonEmptySet<B>;
1105
1463
  to: {
1106
- Array: <A>(s: ReadonlySet<A>) => readonly A[];
1107
- };
1108
- NonEmpty: {
1109
- singleton: <A>(item: A) => NonEmptySet<A>;
1110
- from: {
1111
- Set: <A>(s: ReadonlySet<A>) => Maybe<NonEmptySet<A>>;
1112
- };
1113
- reduce: <A>(f: (acc: A, a: A) => A) => (s: NonEmptySet<A>) => A;
1114
- map: <A, B>(f: (a: A) => B) => (s: NonEmptySet<A>) => NonEmptySet<B>;
1115
- to: {
1116
- Array: <A>(s: NonEmptySet<A>) => NonEmptyArr<A>;
1117
- };
1464
+ Array: <A>(s: NonEmptySet<A>) => NonEmptyArr<A>;
1118
1465
  };
1466
+ };
1119
1467
  };
1120
- declare namespace Uniq {
1121
- /**
1122
- * A branded type representing a unique collection with at least one element.
1123
- */
1124
- type NonEmpty<A> = NonEmptySet<A>;
1468
+ export declare namespace Uniq {
1469
+ /**
1470
+ * A branded type representing a unique collection with at least one element.
1471
+ */
1472
+ type NonEmpty<A> = NonEmptySet<A>;
1125
1473
  }
1126
-
1127
- export { Arr, BigNum, Dict, Json, type NonEmptyMap, type NonEmptyRecord, type NonEmptySet, type NonEmptyString, Num, Rec, Str, Uniq };
1474
+ //#endregion