@nunofyobiz/effect-extras 2.0.0 → 3.0.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.
Files changed (133) hide show
  1. package/README.md +38 -3
  2. package/dist/ArrayX.d.ts +381 -0
  3. package/dist/ArrayX.d.ts.map +1 -0
  4. package/dist/ArrayX.js +493 -0
  5. package/dist/ArrayX.js.map +1 -0
  6. package/dist/BigIntX.d.ts +24 -0
  7. package/dist/BigIntX.d.ts.map +1 -0
  8. package/dist/BigIntX.js +30 -0
  9. package/dist/BigIntX.js.map +1 -0
  10. package/dist/BooleanX.d.ts +25 -0
  11. package/dist/BooleanX.d.ts.map +1 -0
  12. package/dist/BooleanX.js +25 -0
  13. package/dist/BooleanX.js.map +1 -0
  14. package/dist/DurationX.d.ts +73 -0
  15. package/dist/DurationX.d.ts.map +1 -0
  16. package/dist/DurationX.js +91 -0
  17. package/dist/DurationX.js.map +1 -0
  18. package/dist/EffectX.d.ts +120 -0
  19. package/dist/EffectX.d.ts.map +1 -0
  20. package/dist/EffectX.js +140 -0
  21. package/dist/EffectX.js.map +1 -0
  22. package/dist/FormDataX.d.ts +49 -0
  23. package/dist/FormDataX.d.ts.map +1 -0
  24. package/dist/FormDataX.js +42 -0
  25. package/dist/FormDataX.js.map +1 -0
  26. package/dist/InclusiveOr.d.ts +1123 -0
  27. package/dist/InclusiveOr.d.ts.map +1 -0
  28. package/dist/InclusiveOr.js +1074 -0
  29. package/dist/InclusiveOr.js.map +1 -0
  30. package/dist/MapX.d.ts +32 -0
  31. package/dist/MapX.d.ts.map +1 -0
  32. package/dist/MapX.js +49 -0
  33. package/dist/MapX.js.map +1 -0
  34. package/dist/NonNullableX.d.ts +174 -0
  35. package/dist/NonNullableX.d.ts.map +1 -0
  36. package/dist/NonNullableX.js +217 -0
  37. package/dist/NonNullableX.js.map +1 -0
  38. package/dist/NumberX.d.ts +178 -0
  39. package/dist/NumberX.d.ts.map +1 -0
  40. package/dist/NumberX.js +214 -0
  41. package/dist/NumberX.js.map +1 -0
  42. package/dist/OptionX.d.ts +187 -0
  43. package/dist/OptionX.d.ts.map +1 -0
  44. package/dist/OptionX.js +201 -0
  45. package/dist/OptionX.js.map +1 -0
  46. package/dist/OrderX.d.ts +32 -0
  47. package/dist/OrderX.d.ts.map +1 -0
  48. package/dist/OrderX.js +32 -0
  49. package/dist/OrderX.js.map +1 -0
  50. package/dist/PredicateX.d.ts +108 -0
  51. package/dist/PredicateX.d.ts.map +1 -0
  52. package/dist/PredicateX.js +111 -0
  53. package/dist/PredicateX.js.map +1 -0
  54. package/dist/PromiseX.d.ts +32 -0
  55. package/dist/PromiseX.d.ts.map +1 -0
  56. package/dist/PromiseX.js +32 -0
  57. package/dist/PromiseX.js.map +1 -0
  58. package/dist/RecordX.d.ts +450 -0
  59. package/dist/RecordX.d.ts.map +1 -0
  60. package/dist/RecordX.js +487 -0
  61. package/dist/RecordX.js.map +1 -0
  62. package/dist/ResultX.d.ts +50 -0
  63. package/dist/ResultX.d.ts.map +1 -0
  64. package/dist/ResultX.js +50 -0
  65. package/dist/ResultX.js.map +1 -0
  66. package/dist/SchemaX.d.ts +249 -0
  67. package/dist/SchemaX.d.ts.map +1 -0
  68. package/dist/SchemaX.js +243 -0
  69. package/dist/SchemaX.js.map +1 -0
  70. package/dist/SetX.d.ts +121 -0
  71. package/dist/SetX.d.ts.map +1 -0
  72. package/dist/SetX.js +137 -0
  73. package/dist/SetX.js.map +1 -0
  74. package/dist/StringX.d.ts +131 -0
  75. package/dist/StringX.d.ts.map +1 -0
  76. package/dist/StringX.js +149 -0
  77. package/dist/StringX.js.map +1 -0
  78. package/dist/StructX.d.ts +219 -0
  79. package/dist/StructX.d.ts.map +1 -0
  80. package/dist/StructX.js +173 -0
  81. package/dist/StructX.js.map +1 -0
  82. package/dist/WarnResult.d.ts +1191 -0
  83. package/dist/WarnResult.d.ts.map +1 -0
  84. package/dist/WarnResult.js +991 -0
  85. package/dist/WarnResult.js.map +1 -0
  86. package/dist/index.d.ts +23 -3772
  87. package/dist/index.d.ts.map +1 -0
  88. package/dist/index.js +22 -1011
  89. package/dist/index.js.map +1 -1
  90. package/package.json +18 -5
  91. package/src/{ArrayX/ArrayX.ts → ArrayX.ts} +6 -88
  92. package/src/{DurationX/DurationX.ts → DurationX.ts} +1 -1
  93. package/src/InclusiveOr.ts +1255 -0
  94. package/src/{NonNullableX/NonNullableX.ts → NonNullableX.ts} +5 -0
  95. package/src/{OptionX/OptionX.ts → OptionX.ts} +8 -2
  96. package/src/{PredicateX/PredicateX.ts → PredicateX.ts} +41 -0
  97. package/src/{RecordX/RecordX.ts → RecordX.ts} +184 -2
  98. package/src/StringX.ts +210 -0
  99. package/src/{WarnResult/WarnResult.ts → WarnResult.ts} +297 -227
  100. package/src/index.ts +22 -20
  101. package/src/ArrayX/index.ts +0 -1
  102. package/src/BigIntX/index.ts +0 -1
  103. package/src/BooleanX/index.ts +0 -1
  104. package/src/DurationX/index.ts +0 -1
  105. package/src/EffectX/index.ts +0 -1
  106. package/src/FormDataX/index.ts +0 -1
  107. package/src/MapX/index.ts +0 -1
  108. package/src/NonNullableX/index.ts +0 -2
  109. package/src/NumberX/index.ts +0 -1
  110. package/src/OptionX/index.ts +0 -1
  111. package/src/OrderX/index.ts +0 -1
  112. package/src/PredicateX/index.ts +0 -1
  113. package/src/PromiseX/index.ts +0 -1
  114. package/src/RecordX/index.ts +0 -1
  115. package/src/ResultX/index.ts +0 -1
  116. package/src/SchemaX/index.ts +0 -1
  117. package/src/SetX/index.ts +0 -1
  118. package/src/StringX/StringX.ts +0 -97
  119. package/src/StringX/index.ts +0 -1
  120. package/src/StructX/index.ts +0 -1
  121. package/src/WarnResult/index.ts +0 -1
  122. /package/src/{BigIntX/BigIntX.ts → BigIntX.ts} +0 -0
  123. /package/src/{BooleanX/BooleanX.ts → BooleanX.ts} +0 -0
  124. /package/src/{EffectX/EffectX.ts → EffectX.ts} +0 -0
  125. /package/src/{FormDataX/FormDataX.ts → FormDataX.ts} +0 -0
  126. /package/src/{MapX/MapX.ts → MapX.ts} +0 -0
  127. /package/src/{NumberX/NumberX.ts → NumberX.ts} +0 -0
  128. /package/src/{OrderX/OrderX.ts → OrderX.ts} +0 -0
  129. /package/src/{PromiseX/PromiseX.ts → PromiseX.ts} +0 -0
  130. /package/src/{ResultX/ResultX.ts → ResultX.ts} +0 -0
  131. /package/src/{SchemaX/SchemaX.ts → SchemaX.ts} +0 -0
  132. /package/src/{SetX/SetX.ts → SetX.ts} +0 -0
  133. /package/src/{StructX/StructX.ts → StructX.ts} +0 -0
package/dist/ArrayX.js ADDED
@@ -0,0 +1,493 @@
1
+ /**
2
+ * Generic, framework-agnostic extensions to Effect's `Array` module.
3
+ *
4
+ * @since 0.0.0
5
+ */
6
+ import { Array, Option, Predicate, Record, pipe } from "effect";
7
+ import { dual, identity } from "effect/Function";
8
+ import * as RecordX from "./RecordX.js";
9
+ import * as ResultX from "./ResultX.js";
10
+ /**
11
+ * Returns a shallow copy of `array` between `start` (inclusive) and `end`
12
+ * (exclusive), as a pipeable, dual-form alias for `Array.prototype.slice`.
13
+ *
14
+ * `Array.prototype.slice` is already non-mutating (it returns a shallow copy),
15
+ * but it isn't pipeable. This helper makes it composable inside `pipe(...)`
16
+ * chains alongside the rest of the codebase's Effect-style utilities.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * import { pipe } from "effect"
21
+ * import { ArrayX } from "@nunofyobiz/effect-extras"
22
+ *
23
+ * // data-first
24
+ * assert.deepStrictEqual(ArrayX.slice([1, 2, 3, 4], 1, 3), [2, 3])
25
+ *
26
+ * // data-last (pipeable)
27
+ * assert.deepStrictEqual(pipe([1, 2, 3, 4], ArrayX.slice(1, 3)), [2, 3])
28
+ * ```
29
+ *
30
+ * @category getters
31
+ * @since 0.0.0
32
+ */
33
+ export const slice = /*#__PURE__*/dual(3, (array, start, end) => array.slice(start, end));
34
+ /**
35
+ * Moves a unique item within an array to a new position, using a custom identification function.
36
+ *
37
+ * **Assumption**: Items should be unique in the array based on the identification function.
38
+ *
39
+ * **Happy case**: If the source item is found exactly once and the destination reference item is found (or null, to move to the end):
40
+ * The source item is moved from its current position to the new position
41
+ *
42
+ * **Source item not found**: The array is returned unchanged, regardless of whether the destination reference item exists.
43
+ *
44
+ * **Source item found but duplicated**:
45
+ * - If destination reference item is found: All copies of the source item are removed, then a single copy is inserted before the destination reference item
46
+ * - If destination reference item is not found: The array is returned completely unchanged (no items are moved or removed)
47
+ *
48
+ * Used internally by {@link insertUniq}; not exported as the codebase has no
49
+ * direct callers.
50
+ */
51
+ const moveUniqWith = /*#__PURE__*/dual(2, (inputArray, {
52
+ identify,
53
+ sourceId,
54
+ moveToBeLeftOfId
55
+ }) => {
56
+ const array = [...inputArray];
57
+ // Find the source item and its index
58
+ const sourceIndex = array.findIndex(item => identify(item) === sourceId);
59
+ // Unreachable via the public API: the only caller (`insertUniq`) appends the
60
+ // item before delegating here, so `sourceId` is always present. Kept as a
61
+ // defensive no-op for direct (internal) callers.
62
+ /* v8 ignore next 3 */
63
+ if (sourceIndex < 0) {
64
+ return array;
65
+ }
66
+ const sourceItem = array[sourceIndex];
67
+ // Remove ALL occurrences of the source item from the array
68
+ const arrayWithoutSource = array.filter(item => identify(item) !== sourceId);
69
+ // If moveToBeLeftOfId is null, move to end
70
+ if (moveToBeLeftOfId === null) {
71
+ return [...arrayWithoutSource, sourceItem];
72
+ }
73
+ // Find the destination index in the array without the source item
74
+ const destinationIndex = arrayWithoutSource.findIndex(item => identify(item) === moveToBeLeftOfId);
75
+ if (destinationIndex < 0) {
76
+ // If destination not found, leave array completely unchanged
77
+ return array;
78
+ }
79
+ // Insert the source item before the destination index
80
+ return [...slice(arrayWithoutSource, 0, destinationIndex), sourceItem, ...slice(arrayWithoutSource, destinationIndex, arrayWithoutSource.length)];
81
+ });
82
+ /**
83
+ * Inserts or moves a unique item in an array at a specified position.
84
+ *
85
+ * **Assumption**: Items should be unique in the array based on standard equality.
86
+ *
87
+ * **Happy case**: If the item doesn't exist in the array and the destination reference item is found:
88
+ * The new item is inserted before the destination reference item
89
+ *
90
+ * **Item not found in array**:
91
+ * - If destination reference item is found: The new item is inserted before the destination reference item
92
+ * - If destination reference item is not found: The new item is inserted at the end of the array
93
+ *
94
+ * **Item found but duplicated**:
95
+ * - If destination reference item is found: All existing copies are removed, then a single copy is inserted before the destination reference item
96
+ * - If destination reference item is not found: All existing copies are removed, then a single copy is inserted at the end of the array
97
+ *
98
+ * @param array - The input array to modify
99
+ * @param config - Configuration object containing:
100
+ * - `item`: The item to insert or update (must be a string or number)
101
+ * - `insertToBeLeftOf`: The item to position the new/updated item before,
102
+ * or null to insert at the end
103
+ *
104
+ * @returns A new array with the item inserted or moved to the specified position
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * import { ArrayX } from "@nunofyobiz/effect-extras"
109
+ *
110
+ * // Move an existing item to sit just before "c"
111
+ * assert.deepStrictEqual(
112
+ * ArrayX.insertUniq(["a", "b", "c", "d"], { item: "a", insertToBeLeftOf: "c" }),
113
+ * ["b", "a", "c", "d"],
114
+ * )
115
+ *
116
+ * // Insert a brand-new item; unknown destination falls through to the end
117
+ * assert.deepStrictEqual(
118
+ * ArrayX.insertUniq(["a", "b"], { item: "new", insertToBeLeftOf: null }),
119
+ * ["a", "b", "new"],
120
+ * )
121
+ * ```
122
+ *
123
+ * @category combinators
124
+ * @since 0.0.0
125
+ */
126
+ export const insertUniq = /*#__PURE__*/dual(2, (array, {
127
+ item,
128
+ insertToBeLeftOf
129
+ }) => {
130
+ // Always deduplicate and append the item to the end for insertUniq
131
+ // This ensures we always have exactly one copy of the item, regardless of destination
132
+ const arrayWithNewItem = pipe(array, Array.filter(existingItem => existingItem !== item), Array.append(item));
133
+ // Now move that new item to the desired position
134
+ return moveUniqWith(arrayWithNewItem, {
135
+ identify: identity,
136
+ sourceId: item,
137
+ moveToBeLeftOfId: insertToBeLeftOf
138
+ });
139
+ });
140
+ /**
141
+ * Maps over `array` while threading an accumulator, iterating from right to
142
+ * left instead of left to right.
143
+ *
144
+ * Identical to `Array.mapAccum`, except the traversal order is reversed: `f` is
145
+ * called on the last element first, and the resulting array is returned in the
146
+ * original (left-to-right) order. Use it when each element's mapped value
147
+ * depends on state accumulated from the elements that follow it.
148
+ *
149
+ * @example
150
+ * ```ts
151
+ * import { ArrayX } from "@nunofyobiz/effect-extras"
152
+ *
153
+ * // Running suffix-sum: each slot holds the sum of itself and everything after it
154
+ * assert.deepStrictEqual(
155
+ * ArrayX.mapRightAccum([1, 2, 3], 0, (total, n) => [total + n, total + n]),
156
+ * [6, [6, 5, 3]],
157
+ * )
158
+ * ```
159
+ *
160
+ * @category folding
161
+ * @since 0.0.0
162
+ */
163
+ export const mapRightAccum = /*#__PURE__*/dual(3, (array, initialAccumulator, f) => {
164
+ const [accumulator, result] = pipe(array, Array.reverse, Array.mapAccum(initialAccumulator, f));
165
+ return [accumulator, Array.reverse(result)];
166
+ });
167
+ /**
168
+ * Returns the maximum element of `array` according to `order`, wrapped in an
169
+ * `Option` so that empty arrays are handled safely.
170
+ *
171
+ * Effect's `Array.max` throws on an empty array; this returns `Option.none()`
172
+ * instead, and `Option.some(max)` otherwise. Reach for it whenever the input
173
+ * array might be empty.
174
+ *
175
+ * @example
176
+ * ```ts
177
+ * import { Option, Order, pipe } from "effect"
178
+ * import { ArrayX } from "@nunofyobiz/effect-extras"
179
+ *
180
+ * assert.deepStrictEqual(
181
+ * pipe([3, 7, 2], ArrayX.maxOption(Order.Number)),
182
+ * Option.some(7),
183
+ * )
184
+ * assert.deepStrictEqual(
185
+ * pipe([], ArrayX.maxOption(Order.Number)),
186
+ * Option.none(),
187
+ * )
188
+ * ```
189
+ *
190
+ * @category getters
191
+ * @since 0.0.0
192
+ */
193
+ export const maxOption = /*#__PURE__*/dual(2, (array, order) => pipe(
194
+ // If the array is empty, there is no max
195
+ array, Option.liftPredicate(Array.isArrayNonEmpty),
196
+ // If it is non-empty, get the max
197
+ Option.map(Array.max(order))));
198
+ const takeFirstOrLastWhere = /*#__PURE__*/dual(3, (array, predicate, takeOne) => pipe(
199
+ // Keep only the items that match
200
+ array, Array.filter(predicate),
201
+ // If there is anything left, take one
202
+ Option.liftPredicate(Array.isArrayNonEmpty), Option.map(takeOne)));
203
+ /**
204
+ * Returns the smallest element of `array` (per `order`) that matches
205
+ * `predicate`, narrowed to the refined type `B`, or `Option.none()` if none
206
+ * match.
207
+ *
208
+ * Combines a refinement filter with `Array.min`: only elements satisfying
209
+ * `predicate` are considered, and the minimum of those (by `order`) is
210
+ * returned. The refinement narrows the element type, so the resulting `Option`
211
+ * carries the more specific `B`.
212
+ *
213
+ * @example
214
+ * ```ts
215
+ * import { Option, Order, pipe } from "effect"
216
+ * import { ArrayX } from "@nunofyobiz/effect-extras"
217
+ *
218
+ * const isEven = (n: number): n is number => n % 2 === 0
219
+ *
220
+ * assert.deepStrictEqual(
221
+ * pipe([3, 4, 1, 2, 5], ArrayX.takeFirstWhere(isEven, Order.Number)),
222
+ * Option.some(2),
223
+ * )
224
+ * assert.deepStrictEqual(
225
+ * pipe([1, 3, 5], ArrayX.takeFirstWhere(isEven, Order.Number)),
226
+ * Option.none(),
227
+ * )
228
+ * ```
229
+ *
230
+ * @category getters
231
+ * @since 0.0.0
232
+ */
233
+ export const takeFirstWhere = /*#__PURE__*/dual(3, (array, predicate, order) => takeFirstOrLastWhere(array, predicate, Array.min(order)));
234
+ /**
235
+ * Returns the largest element of `array` (per `order`) that matches
236
+ * `predicate`, narrowed to the refined type `B`, or `Option.none()` if none
237
+ * match.
238
+ *
239
+ * The mirror of {@link takeFirstWhere}: only elements satisfying `predicate`
240
+ * are considered, and the maximum of those (by `order`) is returned. The
241
+ * refinement narrows the element type, so the resulting `Option` carries the
242
+ * more specific `B`.
243
+ *
244
+ * @example
245
+ * ```ts
246
+ * import { Option, Order, pipe } from "effect"
247
+ * import { ArrayX } from "@nunofyobiz/effect-extras"
248
+ *
249
+ * const isEven = (n: number): n is number => n % 2 === 0
250
+ *
251
+ * assert.deepStrictEqual(
252
+ * pipe([3, 4, 1, 2, 5], ArrayX.takeLastWhere(isEven, Order.Number)),
253
+ * Option.some(4),
254
+ * )
255
+ * assert.deepStrictEqual(
256
+ * pipe([1, 3, 5], ArrayX.takeLastWhere(isEven, Order.Number)),
257
+ * Option.none(),
258
+ * )
259
+ * ```
260
+ *
261
+ * @category getters
262
+ * @since 0.0.0
263
+ */
264
+ export const takeLastWhere = /*#__PURE__*/dual(3, (array, predicate, order) => takeFirstOrLastWhere(array, predicate, Array.max(order)));
265
+ /**
266
+ * Groups `items` into a partial record keyed by the category each item maps to
267
+ * via `categorize`.
268
+ *
269
+ * Each item is appended to the array under its category, preserving input
270
+ * order. The result is `Partial<Record<C, A[]>>` because not every possible
271
+ * category `C` is guaranteed to appear — only categories that received at least
272
+ * one item are present.
273
+ *
274
+ * @example
275
+ * ```ts
276
+ * import { ArrayX } from "@nunofyobiz/effect-extras"
277
+ *
278
+ * const parity = (n: number) => (n % 2 === 0 ? "even" : "odd")
279
+ *
280
+ * assert.deepStrictEqual(ArrayX.categorize([1, 2, 3, 4], parity), {
281
+ * odd: [1, 3],
282
+ * even: [2, 4],
283
+ * })
284
+ * ```
285
+ *
286
+ * @category folding
287
+ * @since 0.0.0
288
+ */
289
+ export const categorize = (items, categorize) => Array.reduce(items,
290
+ // Start with an empty record of categorized items. `Record.empty()`
291
+ // returns a `NonLiteralKey<C>`-keyed record, which is structurally
292
+ // equivalent to `Partial<Record<C, A[]>>`; the cast tells TypeScript
293
+ // we'll be writing typed keys back via the reducer below.
294
+ Record.empty(),
295
+ // For each item, add it to the appropriate category
296
+ (categorizedItems, item) => RecordX.upsert(categorizedItems, categorize(item),
297
+ // This is the next item's category
298
+ Option.match({
299
+ // This is the first item in this category, so create a new array
300
+ onNone: () => Array.of(item),
301
+ // Append the item to the existing array
302
+ onSome: Array.append(item)
303
+ })));
304
+ /**
305
+ * Removes all `null` and `undefined` elements from `array`, narrowing the
306
+ * element type to `NonNullable<A>`.
307
+ *
308
+ * Falsy-but-present values such as `0` and `""` are kept — only nullish values
309
+ * are dropped. Use it to clean up an array of optionals into a dense array of
310
+ * known-present values.
311
+ *
312
+ * @example
313
+ * ```ts
314
+ * import { ArrayX } from "@nunofyobiz/effect-extras"
315
+ *
316
+ * assert.deepStrictEqual(
317
+ * ArrayX.compactNullable([1, null, 2, undefined, 0, ""]),
318
+ * [1, 2, 0, ""],
319
+ * )
320
+ * ```
321
+ *
322
+ * @category filtering
323
+ * @since 0.0.0
324
+ */
325
+ export const compactNullable = array => Array.filter(array, Predicate.isNotNullish);
326
+ /**
327
+ * Drops the leading elements of `array` until `predicate` first holds, keeping
328
+ * everything from the first match onward.
329
+ *
330
+ * The first matching element and all subsequent elements are retained
331
+ * regardless of whether they match — only the prefix *before* the first match
332
+ * is trimmed. If nothing matches, returns an empty array.
333
+ *
334
+ * @example
335
+ * ```ts
336
+ * import { Predicate } from "effect"
337
+ * import { ArrayX } from "@nunofyobiz/effect-extras"
338
+ *
339
+ * // Trims the leading strings, then keeps everything (including the trailing "b")
340
+ * assert.deepStrictEqual(
341
+ * ArrayX.filterHead(["a", 1, 2, "b"], Predicate.isNumber),
342
+ * [1, 2, "b"],
343
+ * )
344
+ * ```
345
+ *
346
+ * @category filtering
347
+ * @since 0.0.0
348
+ */
349
+ export const filterHead = /*#__PURE__*/dual(2, (array, predicate) => {
350
+ const firstMatchingIndex = Array.findFirstIndex(array, predicate);
351
+ return Option.match(firstMatchingIndex, {
352
+ onSome: index => slice(array, index, array.length),
353
+ onNone: () => []
354
+ });
355
+ });
356
+ /**
357
+ * Drops the trailing elements of `array` after `predicate` last holds, keeping
358
+ * everything up to and including the last match.
359
+ *
360
+ * The mirror of {@link filterHead}: the last matching element and all preceding
361
+ * elements are retained regardless of whether they match — only the suffix
362
+ * *after* the last match is trimmed. If nothing matches, returns an empty
363
+ * array.
364
+ *
365
+ * @example
366
+ * ```ts
367
+ * import { Predicate } from "effect"
368
+ * import { ArrayX } from "@nunofyobiz/effect-extras"
369
+ *
370
+ * // Keeps the leading "a" and trims the trailing strings after the last number
371
+ * assert.deepStrictEqual(
372
+ * ArrayX.filterTail(["a", 1, 2, "b"], Predicate.isNumber),
373
+ * ["a", 1, 2],
374
+ * )
375
+ * ```
376
+ *
377
+ * @category filtering
378
+ * @since 0.0.0
379
+ */
380
+ export const filterTail = /*#__PURE__*/dual(2, (array, predicate) => {
381
+ const lastMatchingIndex = Array.findLastIndex(array, predicate);
382
+ return Option.match(lastMatchingIndex, {
383
+ onSome: index => slice(array, 0, index + 1),
384
+ onNone: () => []
385
+ });
386
+ });
387
+ /**
388
+ * Maps `f` over `array` and drops every result that is `null` or `undefined`,
389
+ * narrowing the element type to `NonNullable<B>`.
390
+ *
391
+ * A nullable-friendly `Array.filterMap`: where `filterMap` expects `f` to
392
+ * return an `Option`, this accepts a function returning `B | null` (or
393
+ * `undefined`) and treats nullish results as "skip this element". Falsy-but-
394
+ * present values such as `0` and `""` are kept.
395
+ *
396
+ * @example
397
+ * ```ts
398
+ * import { ArrayX } from "@nunofyobiz/effect-extras"
399
+ *
400
+ * // Keep only the even numbers, mapped to their halves
401
+ * assert.deepStrictEqual(
402
+ * ArrayX.filterMapNullable([1, 2, 3, 4], (n) => (n % 2 === 0 ? n / 2 : null)),
403
+ * [1, 2],
404
+ * )
405
+ * ```
406
+ *
407
+ * @category filtering
408
+ * @since 0.0.0
409
+ */
410
+ export const filterMapNullable = /*#__PURE__*/dual(2, (array, f) => pipe(array, Array.filterMap(value => pipe(f(value), Option.fromNullishOr, ResultX.fromOption))));
411
+ /**
412
+ * Finds the first element of a 2-dimensional array (row-major order) matching
413
+ * `predicate`, returning it alongside its row and column indices.
414
+ *
415
+ * Scans rows top-to-bottom and, within each row, left-to-right. On a match
416
+ * returns `Option.some([value, rowIndex, columnIndex])`; if no element matches
417
+ * (or the grid is empty), returns `Option.none()`.
418
+ *
419
+ * @example
420
+ * ```ts
421
+ * import { Option } from "effect"
422
+ * import { ArrayX } from "@nunofyobiz/effect-extras"
423
+ *
424
+ * const grid = [
425
+ * ["A", "B", "C"],
426
+ * ["D", "E", "F"],
427
+ * ]
428
+ *
429
+ * assert.deepStrictEqual(
430
+ * ArrayX.findFirstWithIndex2d(grid, (cell) => cell === "E"),
431
+ * Option.some(["E", 1, 1]),
432
+ * )
433
+ * ```
434
+ *
435
+ * @category getters
436
+ * @since 0.0.0
437
+ */
438
+ export const findFirstWithIndex2d = /*#__PURE__*/dual(2, (array, predicate) => Array.findFirstWithIndex(array, row => Array.findFirstWithIndex(row, predicate)).pipe(Option.map(([[value, secondIndex], firstIndex]) => [value, firstIndex, secondIndex])));
439
+ /**
440
+ * Splits `array` into runs of consecutive elements that share the same group
441
+ * value, where the group is derived by `chunk` and compared with the provided
442
+ * `Equivalence`.
443
+ *
444
+ * Only *adjacent* elements are grouped: a new run starts every time the group
445
+ * value changes from the previous element. Each entry in the result carries the
446
+ * `group` value and the non-empty array of `values` that produced it, preserving
447
+ * input order. An empty input yields an empty array. Use it for run-length-style
448
+ * segmentation; reach for `Array.groupBy` instead when you want all elements
449
+ * with the same key collapsed regardless of position.
450
+ *
451
+ * @example
452
+ * ```ts
453
+ * import { Equivalence } from "effect"
454
+ * import { ArrayX } from "@nunofyobiz/effect-extras"
455
+ *
456
+ * // Group adjacent numbers by parity
457
+ * assert.deepStrictEqual(
458
+ * ArrayX.chunkBy([2, 4, 1, 3, 6], (n) => n % 2 === 0, Equivalence.Boolean),
459
+ * [
460
+ * { group: true, values: [2, 4] },
461
+ * { group: false, values: [1, 3] },
462
+ * { group: true, values: [6] },
463
+ * ],
464
+ * )
465
+ * ```
466
+ *
467
+ * @category folding
468
+ * @since 0.0.0
469
+ */
470
+ export const chunkBy = /*#__PURE__*/dual(3, (array, chunk, chunkEquals) => {
471
+ if (array.length === 0) {
472
+ return [];
473
+ }
474
+ const result = [];
475
+ for (const item of array) {
476
+ const groupValue = chunk(item);
477
+ if (result.length > 0) {
478
+ const lastGroup = result.at(-1);
479
+ if (lastGroup && chunkEquals(lastGroup.group, groupValue)) {
480
+ // Add to current group
481
+ lastGroup.values.push(item);
482
+ continue;
483
+ }
484
+ }
485
+ // Start a new group
486
+ result.push({
487
+ group: groupValue,
488
+ values: Array.of(item)
489
+ });
490
+ }
491
+ return result;
492
+ });
493
+ //# sourceMappingURL=ArrayX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArrayX.js","names":["Array","Option","Predicate","Record","pipe","dual","identity","RecordX","ResultX","slice","array","start","end","moveUniqWith","inputArray","identify","sourceId","moveToBeLeftOfId","sourceIndex","findIndex","item","sourceItem","arrayWithoutSource","filter","destinationIndex","length","insertUniq","insertToBeLeftOf","arrayWithNewItem","existingItem","append","mapRightAccum","initialAccumulator","f","accumulator","result","reverse","mapAccum","maxOption","order","liftPredicate","isArrayNonEmpty","map","max","takeFirstOrLastWhere","predicate","takeOne","takeFirstWhere","min","takeLastWhere","categorize","items","reduce","empty","categorizedItems","upsert","match","onNone","of","onSome","compactNullable","isNotNullish","filterHead","firstMatchingIndex","findFirstIndex","index","filterTail","lastMatchingIndex","findLastIndex","filterMapNullable","filterMap","value","fromNullishOr","fromOption","findFirstWithIndex2d","findFirstWithIndex","row","secondIndex","firstIndex","chunkBy","chunk","chunkEquals","groupValue","lastGroup","at","group","values","push"],"sources":["../src/ArrayX.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Converts a `bigint` to a `number`, throwing when the value cannot be
3
+ * represented exactly.
4
+ *
5
+ * Delegates to Effect's `BigInt.toNumber`, which returns `None` once the
6
+ * `bigint` falls outside the safe integer range (`Number.MAX_SAFE_INTEGER`).
7
+ * This unwraps that `Option`, throwing instead of silently losing precision —
8
+ * use it only when the value is known to fit.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { BigIntX } from "@nunofyobiz/effect-extras"
13
+ *
14
+ * assert.deepStrictEqual(BigIntX.toNumberOrThrow(42n), 42)
15
+ *
16
+ * // throws when outside the safe integer range
17
+ * assert.throws(() => BigIntX.toNumberOrThrow(9007199254740993n))
18
+ * ```
19
+ *
20
+ * @category unsafe
21
+ * @since 0.0.0
22
+ */
23
+ export declare const toNumberOrThrow: (value: bigint) => number;
24
+ //# sourceMappingURL=BigIntX.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BigIntX.d.ts","sourceRoot":"","sources":["../src/BigIntX.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,KAAG,MAK7C,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Generic, framework-agnostic extensions to Effect's `BigInt` module.
3
+ *
4
+ * @since 0.0.0
5
+ */
6
+ import { BigInt, Option } from "effect";
7
+ /**
8
+ * Converts a `bigint` to a `number`, throwing when the value cannot be
9
+ * represented exactly.
10
+ *
11
+ * Delegates to Effect's `BigInt.toNumber`, which returns `None` once the
12
+ * `bigint` falls outside the safe integer range (`Number.MAX_SAFE_INTEGER`).
13
+ * This unwraps that `Option`, throwing instead of silently losing precision —
14
+ * use it only when the value is known to fit.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { BigIntX } from "@nunofyobiz/effect-extras"
19
+ *
20
+ * assert.deepStrictEqual(BigIntX.toNumberOrThrow(42n), 42)
21
+ *
22
+ * // throws when outside the safe integer range
23
+ * assert.throws(() => BigIntX.toNumberOrThrow(9007199254740993n))
24
+ * ```
25
+ *
26
+ * @category unsafe
27
+ * @since 0.0.0
28
+ */
29
+ export const toNumberOrThrow = value => BigInt.toNumber(value).pipe(Option.getOrThrowWith(() => new Error(`Value ${value} is outside safe integer range`)));
30
+ //# sourceMappingURL=BigIntX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BigIntX.js","names":["BigInt","Option","toNumberOrThrow","value","toNumber","pipe","getOrThrowWith","Error"],"sources":["../src/BigIntX.ts"],"sourcesContent":[null],"mappings":"AAAA;;;;;AAKA,SAASA,MAAM,EAAEC,MAAM,QAAQ,QAAQ;AAEvC;;;;;;;;;;;;;;;;;;;;;;AAsBA,OAAO,MAAMC,eAAe,GAAIC,KAAa,IAC3CH,MAAM,CAACI,QAAQ,CAACD,KAAK,CAAC,CAACE,IAAI,CACzBJ,MAAM,CAACK,cAAc,CACnB,MAAM,IAAIC,KAAK,CAAC,SAASJ,KAAK,gCAAgC,CAAC,CAChE,CACF","ignoreList":[]}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Generic, framework-agnostic extensions to Effect's `Boolean` module.
3
+ *
4
+ * @since 0.0.0
5
+ */
6
+ /**
7
+ * Converts a `boolean` to its binary digit: `1` for `true`, `0` for `false`.
8
+ *
9
+ * Useful when a numeric flag is required — summing booleans to count how many
10
+ * predicates hold, or feeding a bit into bitwise math or an external API that
11
+ * expects `0`/`1` rather than `false`/`true`.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { BooleanX } from "@nunofyobiz/effect-extras"
16
+ *
17
+ * assert.deepStrictEqual(BooleanX.toBinary(true), 1)
18
+ * assert.deepStrictEqual(BooleanX.toBinary(false), 0)
19
+ * ```
20
+ *
21
+ * @category conversions
22
+ * @since 0.0.0
23
+ */
24
+ export declare const toBinary: (value: boolean) => 0 | 1;
25
+ //# sourceMappingURL=BooleanX.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BooleanX.d.ts","sourceRoot":"","sources":["../src/BooleanX.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,CAAC,GAAG,CAAoB,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Generic, framework-agnostic extensions to Effect's `Boolean` module.
3
+ *
4
+ * @since 0.0.0
5
+ */
6
+ /**
7
+ * Converts a `boolean` to its binary digit: `1` for `true`, `0` for `false`.
8
+ *
9
+ * Useful when a numeric flag is required — summing booleans to count how many
10
+ * predicates hold, or feeding a bit into bitwise math or an external API that
11
+ * expects `0`/`1` rather than `false`/`true`.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { BooleanX } from "@nunofyobiz/effect-extras"
16
+ *
17
+ * assert.deepStrictEqual(BooleanX.toBinary(true), 1)
18
+ * assert.deepStrictEqual(BooleanX.toBinary(false), 0)
19
+ * ```
20
+ *
21
+ * @category conversions
22
+ * @since 0.0.0
23
+ */
24
+ export const toBinary = value => value ? 1 : 0;
25
+ //# sourceMappingURL=BooleanX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BooleanX.js","names":["toBinary","value"],"sources":["../src/BooleanX.ts"],"sourcesContent":[null],"mappings":"AAAA;;;;;AAKA;;;;;;;;;;;;;;;;;;AAkBA,OAAO,MAAMA,QAAQ,GAAIC,KAAc,IAAaA,KAAK,GAAG,CAAC,GAAG,CAAE","ignoreList":[]}