@nlozgachev/pipelined 0.6.4

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.
Files changed (144) hide show
  1. package/README.md +85 -0
  2. package/esm/mod.js +3 -0
  3. package/esm/package.json +3 -0
  4. package/esm/src/Composition/compose.js +3 -0
  5. package/esm/src/Composition/converge.js +3 -0
  6. package/esm/src/Composition/curry.js +42 -0
  7. package/esm/src/Composition/flip.js +20 -0
  8. package/esm/src/Composition/flow.js +8 -0
  9. package/esm/src/Composition/fn.js +85 -0
  10. package/esm/src/Composition/index.js +13 -0
  11. package/esm/src/Composition/juxt.js +3 -0
  12. package/esm/src/Composition/memoize.js +66 -0
  13. package/esm/src/Composition/not.js +25 -0
  14. package/esm/src/Composition/on.js +12 -0
  15. package/esm/src/Composition/pipe.js +3 -0
  16. package/esm/src/Composition/tap.js +33 -0
  17. package/esm/src/Composition/uncurry.js +32 -0
  18. package/esm/src/Core/Arr.js +463 -0
  19. package/esm/src/Core/Deferred.js +26 -0
  20. package/esm/src/Core/InternalTypes.js +1 -0
  21. package/esm/src/Core/Lens.js +98 -0
  22. package/esm/src/Core/Option.js +186 -0
  23. package/esm/src/Core/Optional.js +160 -0
  24. package/esm/src/Core/Reader.js +134 -0
  25. package/esm/src/Core/Rec.js +167 -0
  26. package/esm/src/Core/RemoteData.js +206 -0
  27. package/esm/src/Core/Result.js +164 -0
  28. package/esm/src/Core/Task.js +187 -0
  29. package/esm/src/Core/TaskOption.js +105 -0
  30. package/esm/src/Core/TaskResult.js +125 -0
  31. package/esm/src/Core/TaskValidation.js +101 -0
  32. package/esm/src/Core/These.js +241 -0
  33. package/esm/src/Core/Validation.js +214 -0
  34. package/esm/src/Core/index.js +15 -0
  35. package/esm/src/Types/Brand.js +28 -0
  36. package/esm/src/Types/NonEmptyList.js +14 -0
  37. package/esm/src/Types/index.js +2 -0
  38. package/package.json +61 -0
  39. package/script/mod.js +19 -0
  40. package/script/package.json +3 -0
  41. package/script/src/Composition/compose.js +6 -0
  42. package/script/src/Composition/converge.js +6 -0
  43. package/script/src/Composition/curry.js +48 -0
  44. package/script/src/Composition/flip.js +24 -0
  45. package/script/src/Composition/flow.js +11 -0
  46. package/script/src/Composition/fn.js +98 -0
  47. package/script/src/Composition/index.js +29 -0
  48. package/script/src/Composition/juxt.js +6 -0
  49. package/script/src/Composition/memoize.js +71 -0
  50. package/script/src/Composition/not.js +29 -0
  51. package/script/src/Composition/on.js +16 -0
  52. package/script/src/Composition/pipe.js +6 -0
  53. package/script/src/Composition/tap.js +37 -0
  54. package/script/src/Composition/uncurry.js +38 -0
  55. package/script/src/Core/Arr.js +466 -0
  56. package/script/src/Core/Deferred.js +29 -0
  57. package/script/src/Core/InternalTypes.js +2 -0
  58. package/script/src/Core/Lens.js +101 -0
  59. package/script/src/Core/Option.js +189 -0
  60. package/script/src/Core/Optional.js +163 -0
  61. package/script/src/Core/Reader.js +137 -0
  62. package/script/src/Core/Rec.js +170 -0
  63. package/script/src/Core/RemoteData.js +209 -0
  64. package/script/src/Core/Result.js +167 -0
  65. package/script/src/Core/Task.js +190 -0
  66. package/script/src/Core/TaskOption.js +108 -0
  67. package/script/src/Core/TaskResult.js +128 -0
  68. package/script/src/Core/TaskValidation.js +104 -0
  69. package/script/src/Core/These.js +244 -0
  70. package/script/src/Core/Validation.js +217 -0
  71. package/script/src/Core/index.js +31 -0
  72. package/script/src/Types/Brand.js +31 -0
  73. package/script/src/Types/NonEmptyList.js +18 -0
  74. package/script/src/Types/index.js +18 -0
  75. package/types/mod.d.ts +4 -0
  76. package/types/mod.d.ts.map +1 -0
  77. package/types/src/Composition/compose.d.ts +33 -0
  78. package/types/src/Composition/compose.d.ts.map +1 -0
  79. package/types/src/Composition/converge.d.ts +21 -0
  80. package/types/src/Composition/converge.d.ts.map +1 -0
  81. package/types/src/Composition/curry.d.ts +43 -0
  82. package/types/src/Composition/curry.d.ts.map +1 -0
  83. package/types/src/Composition/flip.d.ts +21 -0
  84. package/types/src/Composition/flip.d.ts.map +1 -0
  85. package/types/src/Composition/flow.d.ts +56 -0
  86. package/types/src/Composition/flow.d.ts.map +1 -0
  87. package/types/src/Composition/fn.d.ts +76 -0
  88. package/types/src/Composition/fn.d.ts.map +1 -0
  89. package/types/src/Composition/index.d.ts +14 -0
  90. package/types/src/Composition/index.d.ts.map +1 -0
  91. package/types/src/Composition/juxt.d.ts +18 -0
  92. package/types/src/Composition/juxt.d.ts.map +1 -0
  93. package/types/src/Composition/memoize.d.ts +46 -0
  94. package/types/src/Composition/memoize.d.ts.map +1 -0
  95. package/types/src/Composition/not.d.ts +26 -0
  96. package/types/src/Composition/not.d.ts.map +1 -0
  97. package/types/src/Composition/on.d.ts +13 -0
  98. package/types/src/Composition/on.d.ts.map +1 -0
  99. package/types/src/Composition/pipe.d.ts +56 -0
  100. package/types/src/Composition/pipe.d.ts.map +1 -0
  101. package/types/src/Composition/tap.d.ts +31 -0
  102. package/types/src/Composition/tap.d.ts.map +1 -0
  103. package/types/src/Composition/uncurry.d.ts +54 -0
  104. package/types/src/Composition/uncurry.d.ts.map +1 -0
  105. package/types/src/Core/Arr.d.ts +355 -0
  106. package/types/src/Core/Arr.d.ts.map +1 -0
  107. package/types/src/Core/Deferred.d.ts +49 -0
  108. package/types/src/Core/Deferred.d.ts.map +1 -0
  109. package/types/src/Core/InternalTypes.d.ts +20 -0
  110. package/types/src/Core/InternalTypes.d.ts.map +1 -0
  111. package/types/src/Core/Lens.d.ts +118 -0
  112. package/types/src/Core/Lens.d.ts.map +1 -0
  113. package/types/src/Core/Option.d.ts +205 -0
  114. package/types/src/Core/Option.d.ts.map +1 -0
  115. package/types/src/Core/Optional.d.ts +158 -0
  116. package/types/src/Core/Optional.d.ts.map +1 -0
  117. package/types/src/Core/Reader.d.ts +156 -0
  118. package/types/src/Core/Reader.d.ts.map +1 -0
  119. package/types/src/Core/Rec.d.ts +121 -0
  120. package/types/src/Core/Rec.d.ts.map +1 -0
  121. package/types/src/Core/RemoteData.d.ts +192 -0
  122. package/types/src/Core/RemoteData.d.ts.map +1 -0
  123. package/types/src/Core/Result.d.ts +176 -0
  124. package/types/src/Core/Result.d.ts.map +1 -0
  125. package/types/src/Core/Task.d.ts +189 -0
  126. package/types/src/Core/Task.d.ts.map +1 -0
  127. package/types/src/Core/TaskOption.d.ts +120 -0
  128. package/types/src/Core/TaskOption.d.ts.map +1 -0
  129. package/types/src/Core/TaskResult.d.ts +117 -0
  130. package/types/src/Core/TaskResult.d.ts.map +1 -0
  131. package/types/src/Core/TaskValidation.d.ts +119 -0
  132. package/types/src/Core/TaskValidation.d.ts.map +1 -0
  133. package/types/src/Core/These.d.ts +221 -0
  134. package/types/src/Core/These.d.ts.map +1 -0
  135. package/types/src/Core/Validation.d.ts +213 -0
  136. package/types/src/Core/Validation.d.ts.map +1 -0
  137. package/types/src/Core/index.d.ts +16 -0
  138. package/types/src/Core/index.d.ts.map +1 -0
  139. package/types/src/Types/Brand.d.ts +52 -0
  140. package/types/src/Types/Brand.d.ts.map +1 -0
  141. package/types/src/Types/NonEmptyList.d.ts +29 -0
  142. package/types/src/Types/NonEmptyList.d.ts.map +1 -0
  143. package/types/src/Types/index.d.ts +3 -0
  144. package/types/src/Types/index.d.ts.map +1 -0
@@ -0,0 +1,466 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Arr = void 0;
4
+ const Deferred_js_1 = require("./Deferred.js");
5
+ const Option_js_1 = require("./Option.js");
6
+ const Result_js_1 = require("./Result.js");
7
+ const Task_js_1 = require("./Task.js");
8
+ const NonEmptyList_js_1 = require("../Types/NonEmptyList.js");
9
+ /**
10
+ * Functional array utilities that compose well with pipe.
11
+ * All functions are data-last and curried where applicable.
12
+ * Safe access functions return Option instead of throwing or returning undefined.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * pipe(
17
+ * [1, 2, 3, 4, 5],
18
+ * Arr.filter(n => n > 2),
19
+ * Arr.map(n => n * 10),
20
+ * Arr.head
21
+ * ); // Some(30)
22
+ * ```
23
+ */
24
+ var Arr;
25
+ (function (Arr) {
26
+ // --- Safe access ---
27
+ /**
28
+ * Returns the first element of an array, or None if the array is empty.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * Arr.head([1, 2, 3]); // Some(1)
33
+ * Arr.head([]); // None
34
+ * ```
35
+ */
36
+ Arr.head = (data) => data.length > 0 ? Option_js_1.Option.some(data[0]) : Option_js_1.Option.none();
37
+ /**
38
+ * Returns the last element of an array, or None if the array is empty.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * Arr.last([1, 2, 3]); // Some(3)
43
+ * Arr.last([]); // None
44
+ * ```
45
+ */
46
+ Arr.last = (data) => data.length > 0 ? Option_js_1.Option.some(data[data.length - 1]) : Option_js_1.Option.none();
47
+ /**
48
+ * Returns all elements except the first, or None if the array is empty.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * Arr.tail([1, 2, 3]); // Some([2, 3])
53
+ * Arr.tail([]); // None
54
+ * ```
55
+ */
56
+ Arr.tail = (data) => data.length > 0 ? Option_js_1.Option.some(data.slice(1)) : Option_js_1.Option.none();
57
+ /**
58
+ * Returns all elements except the last, or None if the array is empty.
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * Arr.init([1, 2, 3]); // Some([1, 2])
63
+ * Arr.init([]); // None
64
+ * ```
65
+ */
66
+ Arr.init = (data) => data.length > 0 ? Option_js_1.Option.some(data.slice(0, -1)) : Option_js_1.Option.none();
67
+ // --- Search ---
68
+ /**
69
+ * Returns the first element matching the predicate, or None.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * pipe([1, 2, 3, 4], Arr.findFirst(n => n > 2)); // Some(3)
74
+ * ```
75
+ */
76
+ Arr.findFirst = (predicate) => (data) => {
77
+ const idx = data.findIndex(predicate);
78
+ return idx >= 0 ? Option_js_1.Option.some(data[idx]) : Option_js_1.Option.none();
79
+ };
80
+ /**
81
+ * Returns the last element matching the predicate, or None.
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * pipe([1, 2, 3, 4], Arr.findLast(n => n > 2)); // Some(4)
86
+ * ```
87
+ */
88
+ Arr.findLast = (predicate) => (data) => {
89
+ for (let i = data.length - 1; i >= 0; i--) {
90
+ if (predicate(data[i]))
91
+ return Option_js_1.Option.some(data[i]);
92
+ }
93
+ return Option_js_1.Option.none();
94
+ };
95
+ /**
96
+ * Returns the index of the first element matching the predicate, or None.
97
+ *
98
+ * @example
99
+ * ```ts
100
+ * pipe([1, 2, 3, 4], Arr.findIndex(n => n > 2)); // Some(2)
101
+ * ```
102
+ */
103
+ Arr.findIndex = (predicate) => (data) => {
104
+ const idx = data.findIndex(predicate);
105
+ return idx >= 0 ? Option_js_1.Option.some(idx) : Option_js_1.Option.none();
106
+ };
107
+ // --- Transform ---
108
+ /**
109
+ * Transforms each element of an array.
110
+ *
111
+ * @example
112
+ * ```ts
113
+ * pipe([1, 2, 3], Arr.map(n => n * 2)); // [2, 4, 6]
114
+ * ```
115
+ */
116
+ Arr.map = (f) => (data) => data.map(f);
117
+ /**
118
+ * Filters elements that satisfy the predicate.
119
+ *
120
+ * @example
121
+ * ```ts
122
+ * pipe([1, 2, 3, 4], Arr.filter(n => n % 2 === 0)); // [2, 4]
123
+ * ```
124
+ */
125
+ Arr.filter = (predicate) => (data) => data.filter(predicate);
126
+ /**
127
+ * Splits an array into two groups based on a predicate.
128
+ * First group contains elements that satisfy the predicate,
129
+ * second group contains the rest.
130
+ *
131
+ * @example
132
+ * ```ts
133
+ * pipe([1, 2, 3, 4], Arr.partition(n => n % 2 === 0)); // [[2, 4], [1, 3]]
134
+ * ```
135
+ */
136
+ Arr.partition = (predicate) => (data) => {
137
+ const pass = [];
138
+ const fail = [];
139
+ for (const a of data) {
140
+ (predicate(a) ? pass : fail).push(a);
141
+ }
142
+ return [pass, fail];
143
+ };
144
+ /**
145
+ * Groups elements by a key function.
146
+ *
147
+ * @example
148
+ * ```ts
149
+ * pipe(
150
+ * ["apple", "avocado", "banana"],
151
+ * Arr.groupBy(s => s[0])
152
+ * ); // { a: ["apple", "avocado"], b: ["banana"] }
153
+ * ```
154
+ */
155
+ Arr.groupBy = (f) => (data) => {
156
+ const result = {};
157
+ for (const a of data) {
158
+ const key = f(a);
159
+ if (!result[key])
160
+ result[key] = [];
161
+ result[key].push(a);
162
+ }
163
+ return result;
164
+ };
165
+ /**
166
+ * Removes duplicate elements using strict equality.
167
+ *
168
+ * @example
169
+ * ```ts
170
+ * Arr.uniq([1, 2, 2, 3, 1]); // [1, 2, 3]
171
+ * ```
172
+ */
173
+ Arr.uniq = (data) => [
174
+ ...new Set(data),
175
+ ];
176
+ /**
177
+ * Removes duplicate elements by comparing the result of a key function.
178
+ *
179
+ * @example
180
+ * ```ts
181
+ * pipe(
182
+ * [{id: 1, name: "a"}, {id: 1, name: "b"}, {id: 2, name: "c"}],
183
+ * Arr.uniqBy(x => x.id)
184
+ * ); // [{id: 1, name: "a"}, {id: 2, name: "c"}]
185
+ * ```
186
+ */
187
+ Arr.uniqBy = (f) => (data) => {
188
+ const seen = new Set();
189
+ const result = [];
190
+ for (const a of data) {
191
+ const key = f(a);
192
+ if (!seen.has(key)) {
193
+ seen.add(key);
194
+ result.push(a);
195
+ }
196
+ }
197
+ return result;
198
+ };
199
+ /**
200
+ * Sorts an array using a comparison function. Returns a new array.
201
+ *
202
+ * @example
203
+ * ```ts
204
+ * pipe([3, 1, 2], Arr.sortBy((a, b) => a - b)); // [1, 2, 3]
205
+ * ```
206
+ */
207
+ Arr.sortBy = (compare) => (data) => [...data].sort(compare);
208
+ // --- Combine ---
209
+ /**
210
+ * Pairs up elements from two arrays. Stops at the shorter array.
211
+ *
212
+ * @example
213
+ * ```ts
214
+ * pipe([1, 2, 3], Arr.zip(["a", "b"])); // [[1, "a"], [2, "b"]]
215
+ * ```
216
+ */
217
+ Arr.zip = (other) => (data) => {
218
+ const len = Math.min(data.length, other.length);
219
+ const result = [];
220
+ for (let i = 0; i < len; i++) {
221
+ result.push([data[i], other[i]]);
222
+ }
223
+ return result;
224
+ };
225
+ /**
226
+ * Combines elements from two arrays using a function. Stops at the shorter array.
227
+ *
228
+ * @example
229
+ * ```ts
230
+ * pipe([1, 2], Arr.zipWith((a, b) => a + b, ["a", "b"])); // ["1a", "2b"]
231
+ * ```
232
+ */
233
+ Arr.zipWith = (f, other) => (data) => {
234
+ const len = Math.min(data.length, other.length);
235
+ const result = [];
236
+ for (let i = 0; i < len; i++) {
237
+ result.push(f(data[i], other[i]));
238
+ }
239
+ return result;
240
+ };
241
+ /**
242
+ * Inserts a separator between every element.
243
+ *
244
+ * @example
245
+ * ```ts
246
+ * pipe([1, 2, 3], Arr.intersperse(0)); // [1, 0, 2, 0, 3]
247
+ * ```
248
+ */
249
+ Arr.intersperse = (sep) => (data) => {
250
+ if (data.length <= 1)
251
+ return data;
252
+ const result = [data[0]];
253
+ for (let i = 1; i < data.length; i++) {
254
+ result.push(sep, data[i]);
255
+ }
256
+ return result;
257
+ };
258
+ /**
259
+ * Splits an array into chunks of the given size.
260
+ *
261
+ * @example
262
+ * ```ts
263
+ * pipe([1, 2, 3, 4, 5], Arr.chunksOf(2)); // [[1, 2], [3, 4], [5]]
264
+ * ```
265
+ */
266
+ Arr.chunksOf = (n) => (data) => {
267
+ if (n <= 0)
268
+ return [];
269
+ const result = [];
270
+ for (let i = 0; i < data.length; i += n) {
271
+ result.push(data.slice(i, i + n));
272
+ }
273
+ return result;
274
+ };
275
+ /**
276
+ * Flattens a nested array by one level.
277
+ *
278
+ * @example
279
+ * ```ts
280
+ * Arr.flatten([[1, 2], [3], [4, 5]]); // [1, 2, 3, 4, 5]
281
+ * ```
282
+ */
283
+ Arr.flatten = (data) => [].concat(...data);
284
+ /**
285
+ * Maps each element to an array and flattens the result.
286
+ *
287
+ * @example
288
+ * ```ts
289
+ * pipe([1, 2, 3], Arr.flatMap(n => [n, n * 10])); // [1, 10, 2, 20, 3, 30]
290
+ * ```
291
+ */
292
+ Arr.flatMap = (f) => (data) => [].concat(...data.map(f));
293
+ /**
294
+ * Reduces an array from the left.
295
+ *
296
+ * @example
297
+ * ```ts
298
+ * pipe([1, 2, 3], Arr.reduce(0, (acc, n) => acc + n)); // 6
299
+ * ```
300
+ */
301
+ Arr.reduce = (initial, f) => (data) => data.reduce(f, initial);
302
+ // --- Traverse / Sequence ---
303
+ /**
304
+ * Maps each element to an Option and collects the results.
305
+ * Returns None if any mapping returns None.
306
+ *
307
+ * @example
308
+ * ```ts
309
+ * const parseNum = (s: string): Option<number> => {
310
+ * const n = Number(s);
311
+ * return isNaN(n) ? Option.none() : Option.some(n);
312
+ * };
313
+ *
314
+ * pipe(["1", "2", "3"], Arr.traverse(parseNum)); // Some([1, 2, 3])
315
+ * pipe(["1", "x", "3"], Arr.traverse(parseNum)); // None
316
+ * ```
317
+ */
318
+ Arr.traverse = (f) => (data) => {
319
+ const result = [];
320
+ for (const a of data) {
321
+ const mapped = f(a);
322
+ if (Option_js_1.Option.isNone(mapped))
323
+ return Option_js_1.Option.none();
324
+ result.push(mapped.value);
325
+ }
326
+ return Option_js_1.Option.some(result);
327
+ };
328
+ /**
329
+ * Maps each element to a Result and collects the results.
330
+ * Returns the first Err if any mapping fails.
331
+ *
332
+ * @example
333
+ * ```ts
334
+ * pipe(
335
+ * [1, 2, 3],
336
+ * Arr.traverseResult(n => n > 0 ? Result.ok(n) : Result.err("negative"))
337
+ * ); // Ok([1, 2, 3])
338
+ * ```
339
+ */
340
+ Arr.traverseResult = (f) => (data) => {
341
+ const result = [];
342
+ for (const a of data) {
343
+ const mapped = f(a);
344
+ if (Result_js_1.Result.isErr(mapped))
345
+ return mapped;
346
+ result.push(mapped.value);
347
+ }
348
+ return Result_js_1.Result.ok(result);
349
+ };
350
+ /**
351
+ * Maps each element to a Task and runs all in parallel.
352
+ *
353
+ * @example
354
+ * ```ts
355
+ * pipe(
356
+ * [1, 2, 3],
357
+ * Arr.traverseTask(n => Task.resolve(n * 2))
358
+ * )(); // Promise<[2, 4, 6]>
359
+ * ```
360
+ */
361
+ Arr.traverseTask = (f) => (data) => Task_js_1.Task.from(() => Promise.all(data.map((a) => Deferred_js_1.Deferred.toPromise(f(a)()))));
362
+ /**
363
+ * Collects an array of Options into an Option of array.
364
+ * Returns None if any element is None.
365
+ *
366
+ * @example
367
+ * ```ts
368
+ * Arr.sequence([Option.some(1), Option.some(2)]); // Some([1, 2])
369
+ * Arr.sequence([Option.some(1), Option.none()]); // None
370
+ * ```
371
+ */
372
+ Arr.sequence = (data) => Arr.traverse((a) => a)(data);
373
+ /**
374
+ * Collects an array of Results into a Result of array.
375
+ * Returns the first Err if any element is Err.
376
+ */
377
+ Arr.sequenceResult = (data) => Arr.traverseResult((a) => a)(data);
378
+ /**
379
+ * Collects an array of Tasks into a Task of array. Runs in parallel.
380
+ */
381
+ Arr.sequenceTask = (data) => Arr.traverseTask((a) => a)(data);
382
+ /**
383
+ * Returns true if the array is non-empty (type guard).
384
+ */
385
+ Arr.isNonEmpty = (data) => (0, NonEmptyList_js_1.isNonEmptyList)(data);
386
+ /**
387
+ * Returns the length of an array.
388
+ */
389
+ Arr.size = (data) => data.length;
390
+ /**
391
+ * Returns true if any element satisfies the predicate.
392
+ *
393
+ * @example
394
+ * ```ts
395
+ * pipe([1, 2, 3], Arr.some(n => n > 2)); // true
396
+ * ```
397
+ */
398
+ Arr.some = (predicate) => (data) => data.some(predicate);
399
+ /**
400
+ * Returns true if all elements satisfy the predicate.
401
+ *
402
+ * @example
403
+ * ```ts
404
+ * pipe([1, 2, 3], Arr.every(n => n > 0)); // true
405
+ * ```
406
+ */
407
+ Arr.every = (predicate) => (data) => data.every(predicate);
408
+ /**
409
+ * Reverses an array. Returns a new array.
410
+ *
411
+ * @example
412
+ * ```ts
413
+ * Arr.reverse([1, 2, 3]); // [3, 2, 1]
414
+ * ```
415
+ */
416
+ Arr.reverse = (data) => [...data].reverse();
417
+ /**
418
+ * Takes the first n elements from an array.
419
+ *
420
+ * @example
421
+ * ```ts
422
+ * pipe([1, 2, 3, 4], Arr.take(2)); // [1, 2]
423
+ * ```
424
+ */
425
+ Arr.take = (n) => (data) => n <= 0 ? [] : data.slice(0, n);
426
+ /**
427
+ * Drops the first n elements from an array.
428
+ *
429
+ * @example
430
+ * ```ts
431
+ * pipe([1, 2, 3, 4], Arr.drop(2)); // [3, 4]
432
+ * ```
433
+ */
434
+ Arr.drop = (n) => (data) => data.slice(n);
435
+ /**
436
+ * Takes elements from the start while the predicate holds.
437
+ *
438
+ * @example
439
+ * ```ts
440
+ * pipe([1, 2, 3, 1], Arr.takeWhile(n => n < 3)); // [1, 2]
441
+ * ```
442
+ */
443
+ Arr.takeWhile = (predicate) => (data) => {
444
+ const result = [];
445
+ for (const a of data) {
446
+ if (!predicate(a))
447
+ break;
448
+ result.push(a);
449
+ }
450
+ return result;
451
+ };
452
+ /**
453
+ * Drops elements from the start while the predicate holds.
454
+ *
455
+ * @example
456
+ * ```ts
457
+ * pipe([1, 2, 3, 1], Arr.dropWhile(n => n < 3)); // [3, 1]
458
+ * ```
459
+ */
460
+ Arr.dropWhile = (predicate) => (data) => {
461
+ let i = 0;
462
+ while (i < data.length && predicate(data[i]))
463
+ i++;
464
+ return data.slice(i);
465
+ };
466
+ })(Arr || (exports.Arr = Arr = {}));
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Deferred = void 0;
4
+ var Deferred;
5
+ (function (Deferred) {
6
+ /**
7
+ * Wraps a `Promise` into a `Deferred`, structurally excluding rejection handlers,
8
+ * `.catch()`, `.finally()`, and chainable `.then()`.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const d = Deferred.fromPromise(Promise.resolve("hello"));
13
+ * const value = await d; // "hello"
14
+ * ```
15
+ */
16
+ Deferred.fromPromise = (p) => ({
17
+ then: ((f) => p.then(f)),
18
+ });
19
+ /**
20
+ * Converts a `Deferred` back into a `Promise`.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * const p = Deferred.toPromise(Deferred.fromPromise(Promise.resolve(42)));
25
+ * // p is Promise<42>
26
+ * ```
27
+ */
28
+ Deferred.toPromise = (d) => new Promise((resolve) => d.then(resolve));
29
+ })(Deferred || (exports.Deferred = Deferred = {}));
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Lens = void 0;
4
+ var Lens;
5
+ (function (Lens) {
6
+ /**
7
+ * Constructs a Lens from a getter and a setter.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const nameLens = Lens.make(
12
+ * (user: User) => user.name,
13
+ * (name) => (user) => ({ ...user, name }),
14
+ * );
15
+ * ```
16
+ */
17
+ Lens.make = (get, set) => ({ get, set });
18
+ /**
19
+ * Creates a Lens that focuses on a property of an object.
20
+ * Call with the structure type first, then the key.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * const nameLens = Lens.prop<User>()("name");
25
+ * ```
26
+ */
27
+ Lens.prop = () => (key) => Lens.make((s) => s[key], (a) => (s) => ({ ...s, [key]: a }));
28
+ /**
29
+ * Reads the focused value from a structure.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * pipe(user, Lens.get(nameLens)); // "Alice"
34
+ * ```
35
+ */
36
+ Lens.get = (lens) => (s) => lens.get(s);
37
+ /**
38
+ * Replaces the focused value within a structure, returning a new structure.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * pipe(user, Lens.set(nameLens)("Bob")); // new User with name "Bob"
43
+ * ```
44
+ */
45
+ Lens.set = (lens) => (a) => (s) => lens.set(a)(s);
46
+ /**
47
+ * Applies a function to the focused value, returning a new structure.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * pipe(user, Lens.modify(nameLens)(n => n.toUpperCase())); // "ALICE"
52
+ * ```
53
+ */
54
+ Lens.modify = (lens) => (f) => (s) => lens.set(f(lens.get(s)))(s);
55
+ /**
56
+ * Composes two Lenses: focuses through the outer, then through the inner.
57
+ * Use in a pipe chain to build up a deep focus step by step.
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * const userCityLens = pipe(
62
+ * Lens.prop<User>()("address"),
63
+ * Lens.andThen(Lens.prop<Address>()("city")),
64
+ * );
65
+ * ```
66
+ */
67
+ Lens.andThen = (inner) => (outer) => Lens.make((s) => inner.get(outer.get(s)), (b) => (s) => outer.set(inner.set(b)(outer.get(s)))(s));
68
+ /**
69
+ * Composes a Lens with an Optional, producing an Optional.
70
+ * Use when the next step in the focus is optional (may be absent).
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * const userBioOpt = pipe(
75
+ * Lens.prop<User>()("profile"),
76
+ * Lens.andThenOptional(Optional.prop<Profile>()("bio")),
77
+ * );
78
+ * ```
79
+ */
80
+ Lens.andThenOptional = (inner) => (outer) => ({
81
+ get: (s) => inner.get(outer.get(s)),
82
+ set: (b) => (s) => outer.set(inner.set(b)(outer.get(s)))(s),
83
+ });
84
+ /**
85
+ * Converts a Lens to an Optional. Every Lens is a valid Optional
86
+ * whose get always returns Some.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * pipe(
91
+ * Lens.prop<User>()("address"),
92
+ * Lens.toOptional,
93
+ * Optional.andThen(Optional.prop<Address>()("landmark")),
94
+ * );
95
+ * ```
96
+ */
97
+ Lens.toOptional = (lens) => ({
98
+ get: (s) => ({ kind: "Some", value: lens.get(s) }),
99
+ set: lens.set,
100
+ });
101
+ })(Lens || (exports.Lens = Lens = {}));