@catstral/levy-utils 1.0.0 → 2.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 (94) hide show
  1. package/README.md +1370 -59
  2. package/dist/array/index.d.ts +20 -7
  3. package/dist/array/utils/cluster/index.d.ts +2 -3
  4. package/dist/array/utils/concat/index.d.ts +14 -0
  5. package/dist/array/utils/counting/index.d.ts +2 -2
  6. package/dist/array/utils/filter/index.d.ts +55 -0
  7. package/dist/array/utils/filterMap/index.d.ts +14 -0
  8. package/dist/array/utils/first/index.d.ts +13 -0
  9. package/dist/array/utils/group/index.d.ts +14 -0
  10. package/dist/array/utils/hasItems/index.d.ts +13 -0
  11. package/dist/array/utils/isArray/index.d.ts +9 -0
  12. package/dist/array/utils/last/index.d.ts +14 -0
  13. package/dist/array/utils/list/index.d.ts +2 -2
  14. package/dist/array/utils/map/index.d.ts +29 -0
  15. package/dist/array/utils/max/index.d.ts +24 -0
  16. package/dist/array/utils/min/index.d.ts +24 -0
  17. package/dist/array/utils/overflow/index.d.ts +20 -0
  18. package/dist/array/utils/reduce/index.d.ts +44 -0
  19. package/dist/array/utils/select/index.d.ts +126 -9
  20. package/dist/array/utils/sift/index.d.ts +1 -1
  21. package/dist/array/utils/sum/index.d.ts +13 -0
  22. package/dist/array/utils/toggle/index.d.ts +2 -2
  23. package/dist/callback/index.d.ts +8 -3
  24. package/dist/callback/utils/compose/index.d.ts +43 -0
  25. package/dist/callback/utils/noop/index.d.ts +8 -0
  26. package/dist/callback/utils/pipe/index.d.ts +12 -0
  27. package/dist/callback/utils/preset/index.d.ts +15 -0
  28. package/dist/callback/utils/retry/index.d.ts +2 -2
  29. package/dist/callback/utils/task/index.d.ts +12 -0
  30. package/dist/index.d.ts +9 -8
  31. package/dist/index.js +5 -0
  32. package/dist/misc/index.d.ts +17 -5
  33. package/dist/misc/utils/identity/index.d.ts +10 -0
  34. package/dist/misc/utils/isNull/index.d.ts +9 -0
  35. package/dist/misc/utils/isNullish/index.d.ts +13 -0
  36. package/dist/misc/utils/isPrimitive/index.d.ts +2 -2
  37. package/dist/misc/utils/isPromise/index.d.ts +9 -0
  38. package/dist/misc/utils/isPromiseLike/index.d.ts +9 -0
  39. package/dist/misc/utils/isUndefined/index.d.ts +9 -0
  40. package/dist/misc/utils/match/index.d.ts +22 -0
  41. package/dist/misc/utils/option/index.d.ts +54 -0
  42. package/dist/misc/utils/raise/index.d.ts +19 -0
  43. package/dist/misc/utils/range/index.d.ts +218 -11
  44. package/dist/misc/utils/readOnly/index.d.ts +47 -0
  45. package/dist/misc/utils/sleep/index.d.ts +2 -2
  46. package/dist/misc/utils/timeout/index.d.ts +40 -0
  47. package/dist/misc/utils/values/index.d.ts +13 -0
  48. package/dist/number/index.d.ts +13 -2
  49. package/dist/number/math/index.d.ts +2 -0
  50. package/dist/number/math/utils/isPrime/index.d.ts +9 -0
  51. package/dist/number/math/utils/mod/index.d.ts +10 -0
  52. package/dist/number/types.d.ts +11 -0
  53. package/dist/number/utils/clamp/index.d.ts +13 -0
  54. package/dist/number/utils/isDecimal/index.d.ts +11 -0
  55. package/dist/number/utils/isEven/index.d.ts +9 -0
  56. package/dist/number/utils/isInteger/index.d.ts +11 -0
  57. package/dist/number/utils/isOdd/index.d.ts +9 -0
  58. package/dist/number/utils/negative/index.d.ts +21 -0
  59. package/dist/number/utils/positive/index.d.ts +21 -0
  60. package/dist/number/utils/sign/index.d.ts +14 -0
  61. package/dist/number/utils/toInt/index.d.ts +1 -1
  62. package/dist/number/utils/trunc/index.d.ts +16 -0
  63. package/dist/object/index.d.ts +6 -5
  64. package/dist/object/utils/extend/index.d.ts +21 -0
  65. package/dist/random/helper.d.ts +6 -0
  66. package/dist/random/index.d.ts +6 -0
  67. package/dist/random/utils/chance/index.d.ts +13 -0
  68. package/dist/random/utils/draw/index.d.ts +13 -0
  69. package/dist/random/utils/maybe/index.d.ts +8 -0
  70. package/dist/random/utils/random/index.d.ts +14 -0
  71. package/dist/random/utils/scatter/index.d.ts +30 -0
  72. package/dist/random/utils/shuffle/index.d.ts +11 -0
  73. package/dist/random/utils/uid/index.d.ts +12 -0
  74. package/dist/random/uuid/helpers.d.ts +4 -0
  75. package/dist/random/uuid/index.d.ts +5 -0
  76. package/dist/random/uuid/types.d.ts +16 -0
  77. package/dist/random/uuid/utils/max/index.d.ts +8 -0
  78. package/dist/random/uuid/utils/nil/index.d.ts +8 -0
  79. package/dist/random/uuid/utils/v1/index.d.ts +46 -0
  80. package/dist/random/uuid/utils/v4/index.d.ts +22 -0
  81. package/dist/random/uuid/utils/v7/index.d.ts +34 -0
  82. package/dist/string/casing/index.d.ts +11 -11
  83. package/dist/string/casing/utils/camel/index.d.ts +1 -1
  84. package/dist/string/casing/utils/custom/index.d.ts +1 -1
  85. package/dist/string/casing/utils/http/index.d.ts +1 -1
  86. package/dist/string/casing/utils/kebab/index.d.ts +1 -1
  87. package/dist/string/casing/utils/pascal/index.d.ts +1 -1
  88. package/dist/string/casing/utils/snake/index.d.ts +1 -1
  89. package/dist/string/casing/utils/title/index.d.ts +1 -1
  90. package/dist/string/index.d.ts +4 -4
  91. package/dist/types.d.ts +2 -0
  92. package/package.json +8 -13
  93. package/dist/levyUtils.cjs +0 -5
  94. package/dist/levyUtils.js +0 -1198
package/README.md CHANGED
@@ -1,56 +1,131 @@
1
- # levy-utils
2
- levy-utils is a lightweight, dependency-light library of common JS/TS utility functions covering everyday needs: array/object manipulation, type checks, async helpers, and value conversion.
1
+ # @catstral/levy-utils
2
+ @catstral/levy-utils is a lightweight, dependency-light library of common JS/TS utility functions covering everyday needs: array/object manipulation, type checks, async helpers, and value conversion.
3
3
 
4
4
  ## How to install
5
5
  Install with a package manager
6
6
  ```bash
7
7
  # using npm
8
- npm install levy-utils
8
+ npm install @catstral/levy-utils
9
9
 
10
10
  # using yarn
11
- yarn add levy-utils
11
+ yarn add @catstral/levy-utils
12
12
 
13
13
  # using pnpm
14
- pnpm add levy-utils
14
+ pnpm add @catstral/levy-utils
15
15
 
16
16
  # using bun
17
- bun add levy-utils
17
+ bun add @catstral/levy-utils
18
18
  ```
19
19
 
20
20
  ## Usage
21
21
  ```ts
22
- import { range, sift, toggle } from "levy-utils";
22
+ import { range, sift, toggle } from "@catstral/levy-utils";
23
23
  ```
24
24
 
25
25
  ## Utils
26
26
  A list of all the utilities supported:
27
27
  - [Array utilities](#array-utilities)
28
28
  - [cluster](#clusteritems-size)
29
+ - [concat](#concatvalues)
29
30
  - [counting](#countinglist-identity)
31
+ - [filter](#filterlist-predicate)
32
+ - [filterMap](#filtermaplist-filter-mapper)
33
+ - [first](#firstlist-fallback)
30
34
  - [fork](#forklist-condition)
35
+ - [group](#grouplist-identity)
36
+ - [hasItems](#hasitemslist)
37
+ - [last](#lastlist-fallback)
31
38
  - [list](#liststartorlength-end-options)
32
- - [select](#selectlist-filter-mapper)
39
+ - [map](#maplist-callback)
40
+ - [max](#maxlist-mapper-options)
41
+ - [min](#minlist-mapper-options)
42
+ - [overflow](#overflowlist-clamplength)
43
+ - [reduce](#reducelist-initial-callback-options)
44
+ - [select](#selectlist-callback)
33
45
  - [sift](#siftlist)
46
+ - [sum](#sumlist-mapper)
34
47
  - [toggle](#togglelist-itemtotoggle-options)
35
48
  - [Callback utilities](#callback-utilities)
36
49
  - [chain](#chaincallbacks)
50
+ - [compose](#composecallbacks)
37
51
  - [defer](#defercallback)
52
+ - [noop](#noop)
53
+ - [pipe](#pipevalue-callback)
54
+ - [preset](#presetcallback-parameters)
38
55
  - [retry](#retrycallback-options)
56
+ - [task](#taskcallback)
39
57
  - [Miscellaneous utilities](#miscellaneous-utilities)
40
58
  - [compute / isComputation](#computevalue-args--iscomputationvalue)
59
+ - [identity](#identityvalue)
41
60
  - [isEmpty](#isemptyvalue)
61
+ - [isNull](#isnullvalue)
62
+ - [isNullish](#isnullishvalue)
42
63
  - [isPrimitive](#isprimitivevalue)
64
+ - [isPromise](#ispromisevalue)
65
+ - [isPromiseLike](#ispromiselikevalue)
66
+ - [isUndefined](#isundefinedvalue)
67
+ - [match](#matchvalue-clause-fallback)
68
+ - [Range (class)](#rangerangestring)
69
+ - [static from](#static-fromrange)
70
+ - [details (getter)](#details-getter)
71
+ - [start (getter)](#start-getter)
72
+ - [end (getter)](#end-getter)
73
+ - [step (getter)](#step-getter)
74
+ - [mapper (getter)](#mapper-getter)
75
+ - [start](#startstart)
76
+ - [end](#endend)
77
+ - [step](#stepstep)
78
+ - [map](#mapmapper)
79
+ - [includes](#includesvalue)
80
+ - [excludes](#excludesvalue)
81
+ - [toArray](#toarray)
82
+ - [clone](#clone)
43
83
  - [range](#rangestartorlength-end-options)
84
+ - [raise](#raisevalue)
85
+ - [readOnly / isReadOnly](#readonlyvalue-deepfreeze--isreadonlyvalue)
86
+ - [safe](#safecallback)
44
87
  - [sleep](#sleepdelay)
88
+ - [timeout / isTimeoutError](#timeoutvalue-delayms-options--istimeouterrorvalue)
89
+ - [unwrap](#unwrapoption-fallback)
90
+ - [values](#valuestarget)
45
91
  - [Number utilities](#number-utilities)
92
+ - [Math utilities](#math-utilities)
93
+ - [isPrime](#isPrimevalue)
94
+ - [mod](#moddividend-divisor)
95
+ - [clamp](#clampmin-value-max)
96
+ - [isDecimal](#isdecimalvalue)
97
+ - [isEven](#isevenvalue)
98
+ - [isInteger](#isintegervalue)
99
+ - [isNegative](#isnegativevalue)
100
+ - [isOdd](#isoddvalue)
101
+ - [isPositive](#ispositivevalue)
102
+ - [negative](#negativevalue)
103
+ - [positive](#positivevalue)
104
+ - [sign](#signvalue)
46
105
  - [toFloat](#tofloatvalue-fallback)
47
106
  - [toInt](#tointvalue-fallback)
107
+ - [trunc](#truncvalue-fractiondigits)
48
108
  - [Object utilities](#object-utilities)
49
109
  - [entries](#entriesvalue)
110
+ - [extend](#extendvalue-other)
50
111
  - [isObject](#isobjectitem)
51
112
  - [keys](#keysvalue)
52
113
  - [omit](#omitobject-keys)
53
114
  - [pick](#pickobject-keys)
115
+ - [Randomization utilities](#randomization-utilities)
116
+ - [UUID utilities](#uuid-utilities)
117
+ - [uuidMax](#uuidmax)
118
+ - [uuidNil](#uuidnil)
119
+ - [uuidV1 / v1](#uuidv1options)
120
+ - [uuidV4 / v4 / uuid](#uuidv4options)
121
+ - [uuidV7 / v7](#uuidv7options)
122
+ - [chance](#chancepercentage)
123
+ - [draw](#drawlist)
124
+ - [maybe](#maybe)
125
+ - [random](#randommin-max)
126
+ - [scatter](#scatterlist-split-options)
127
+ - [shuffle](#shufflelist)
128
+ - [uid](#uidlength-charset)
54
129
  - [String utilities](#string-utilities)
55
130
  - [Casing utilities](#casing-utilities)
56
131
  - [camelCase](#camelcasestr-options)
@@ -80,6 +155,15 @@ cluster([1, 2, 3, 4, 5], 2);
80
155
  // [[1, 2], [3, 4], [5]]
81
156
  ```
82
157
 
158
+ #### `concat(...values)`
159
+ Concatenates values and arrays into a new array.
160
+
161
+ ```ts
162
+ concat(1, [2, 3], 4);
163
+ // Expected output:
164
+ // [1, 2, 3, 4]
165
+ ```
166
+
83
167
  #### `counting(list, identity)`
84
168
  Reduces a list down to an object of keys (as determined by the `identity` callback) mapped to how many times that key occurred.
85
169
 
@@ -93,6 +177,49 @@ counting(["a", "b", "a", "c", "a"], (item) => item);
93
177
  // }
94
178
  ```
95
179
 
180
+ #### `filter(list, predicate)`
181
+ Returns a new list containing the items of a given list that pass a predicate.
182
+
183
+ If the predicate returns a promise for any item, a promise is returned that resolves once all of them have.
184
+
185
+ ```ts
186
+ filter([1, 2, 3, 4], (n) => n % 2 === 0);
187
+ // Expected output:
188
+ // [2, 4]
189
+
190
+ await filter([1, 2, 3], async (n) => n > 1);
191
+ // Expected output:
192
+ // [2, 3]
193
+ ```
194
+
195
+ #### `filterMap(list, filter, mapper)`
196
+ Returns a new list of items based on filtered and mapped values of a given list.
197
+
198
+ ```ts
199
+ filterMap(
200
+ [1, 2, 3, 4],
201
+ (n) => n % 2 === 0,
202
+ (n) => n * 10,
203
+ );
204
+ // Expected output:
205
+ // [20, 40]
206
+ ```
207
+
208
+ This utility was formerly called `select`.
209
+
210
+ #### `first(list, fallback?)`
211
+ Returns the first item of a list, or a fallback if the list is empty.
212
+
213
+ ```ts
214
+ first([1, 2, 3]);
215
+ // Expected output:
216
+ // 1
217
+
218
+ first([], "none");
219
+ // Expected output:
220
+ // "none"
221
+ ```
222
+
96
223
  #### `fork(list, condition)`
97
224
  Splits a list into a tuple of two arrays based on a condition: items that pass, and items that don't.
98
225
 
@@ -102,6 +229,44 @@ fork([1, 2, 3, 4], (n) => n % 2 === 0);
102
229
  // [[2, 4], [1, 3]]
103
230
  ```
104
231
 
232
+ #### `group(list, identity)`
233
+ Groups the items of a list into an object of keys (as determined by the `identity` callback) mapped to the items with that key.
234
+
235
+ ```ts
236
+ group(["apple", "avocado", "banana"], (item) => item[0]);
237
+ // Expected output:
238
+ // {
239
+ // a: ["apple", "avocado"],
240
+ // b: ["banana"],
241
+ // }
242
+ ```
243
+
244
+ #### `hasItems(list)`
245
+ Checks if a list has at least one item, narrowing its type to a non-empty tuple.
246
+
247
+ ```ts
248
+ hasItems([1, 2, 3]);
249
+ // Expected output:
250
+ // true
251
+
252
+ hasItems([]);
253
+ // Expected output:
254
+ // false
255
+ ```
256
+
257
+ #### `last(list, fallback?)`
258
+ Returns the last item of a list, or a fallback if the list is empty.
259
+
260
+ ```ts
261
+ last([1, 2, 3]);
262
+ // Expected output:
263
+ // 3
264
+
265
+ last([], "none");
266
+ // Expected output:
267
+ // "none"
268
+ ```
269
+
105
270
  ### `list(startOrLength, end?, options?)`
106
271
  Returns an array with values to a specified size (inclusive), optionally stepped and/or mapped to another value.
107
272
 
@@ -127,9 +292,175 @@ list(0, 3, {
127
292
  // ["foo-0", "foo-1", "foo-2", "foo-3"]
128
293
  ```
129
294
 
130
- <!-- TODO -->
131
- #### `select(list, filter, mapper)`
132
- Returns a new list of items based on filtered and mapped values of a given list.
295
+ options:
296
+ - `step` - The steps used to generate the array.
297
+ - `valueMapper` - A mapper function to map a step to a value.
298
+
299
+ #### `map(list, callback)`
300
+ Returns a new list of items based on mapped values of a given list.
301
+
302
+ If the callback returns a promise for any item, a promise is returned that resolves once all of them have.
303
+
304
+ ```ts
305
+ map([1, 2, 3], (n) => n * 2);
306
+ // Expected output:
307
+ // [2, 4, 6]
308
+
309
+ await map([1, 2, 3], async (n) => n + 1);
310
+ // Expected output:
311
+ // [2, 3, 4]
312
+ ```
313
+
314
+ #### `max(list, mapper?, options?)`
315
+ Returns the largest item from a list.
316
+
317
+ ```ts
318
+ max([1, 2, 3]);
319
+ // Expected output:
320
+ // 3
321
+
322
+ max(
323
+ [
324
+ {
325
+ name: "Bob"
326
+ weight: 54
327
+ },
328
+ {
329
+ name: "Paul"
330
+ weight: 87
331
+ },
332
+ {
333
+ name: "Jane"
334
+ weight: 63
335
+ },
336
+ ],
337
+ (item) => item.weight,
338
+ );
339
+ // Expected output:
340
+ // {
341
+ // name: "Paul",
342
+ // weight: 87,
343
+ // }
344
+ ```
345
+
346
+ #### `min(list, mapper?, options?)`
347
+ Returns the smallest item from a list.
348
+
349
+ ```ts
350
+ min([1, 2, 3]);
351
+ // Expected output:
352
+ // 1
353
+
354
+ min(
355
+ [
356
+ {
357
+ name: "Bob"
358
+ weight: 54
359
+ },
360
+ {
361
+ name: "Paul"
362
+ weight: 87
363
+ },
364
+ {
365
+ name: "Jane"
366
+ weight: 63
367
+ },
368
+ ],
369
+ (item) => item.weight,
370
+ );
371
+ // Expected output:
372
+ // {
373
+ // name: "Bob",
374
+ // weight: 54,
375
+ // }
376
+ ```
377
+
378
+ #### `overflow(list, clampLength)`
379
+ Splits a list into a tuple of two arrays: the first `clampLength` items, and the rest of the items.
380
+
381
+ Throws an `OverflowUtilError` if the clamp length is negative or the given list is not an array.
382
+
383
+ ```ts
384
+ overflow([1, 2, 3, 4, 5], 3);
385
+ // Expected output:
386
+ // [[1, 2, 3], [4, 5]]
387
+ ```
388
+
389
+ #### `reduce(list, initial, callback, options?)`
390
+ Reduces all items of a list down to an accumulated result.
391
+
392
+ ```ts
393
+ reduce([1, 2, 3], 0, (acc, n) => acc + n);
394
+ // Expected output:
395
+ // 6
396
+
397
+ reduce(["a", "b", "c"], "", (acc, letter) => acc + letter, {
398
+ direction: "DESCENDING",
399
+ });
400
+ // Expected output:
401
+ // "cba"
402
+
403
+ reduce([1, 2, 3], 0, (acc, n) => acc + n, {
404
+ result: (total) => `Total: ${total}`,
405
+ });
406
+ // Expected output:
407
+ // "Total: 6"
408
+ ```
409
+
410
+ Options:
411
+ - `direction` - `"ASCENDING"` or `"DESCENDING"`, determines the order the list is reduced in (default `"ASCENDING"`)
412
+ - `result` - transforms the final accumulator into the returned result
413
+
414
+ #### `select(list, callback)`
415
+ Returns a new list built by deciding, per item, what should end up in the result. The callback receives a context object and must return one of its actions.
416
+
417
+ ```ts
418
+ select(
419
+ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
420
+ ({ item, keep, discard, filter }) => {
421
+ if (item < 3) {
422
+ return keep();
423
+ }
424
+
425
+ if (item > 8) {
426
+ return discard();
427
+ }
428
+
429
+ return filter(item % 2 === 0);
430
+ },
431
+ );
432
+ // Expected output:
433
+ // [1, 2, 4, 6, 8]
434
+
435
+ select<number | string[] | null, string>(
436
+ [1, ["2", "3", "4"], null, ["7", "8", "9"], 10],
437
+ ({ item, map, flat, spread }) => {
438
+ if (typeof item === "number") {
439
+ return map(item.toString());
440
+ }
441
+
442
+ if (Array.isArray(item)) {
443
+ return flat(item);
444
+ }
445
+
446
+ return spread("5", "6");
447
+ },
448
+ );
449
+ // Expected output:
450
+ // ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
451
+ ```
452
+
453
+ Available actions:
454
+ - `keep()` - keeps the current item
455
+ - `discard()` - removes the current item
456
+ - `filter(keep)` - keeps or removes the current item based on a boolean
457
+ - `map(value)` - replaces the current item with a value
458
+ - `flat(values)` - replaces the current item with every value of a list
459
+ - `spread(...values)` - replaces the current item with every given value
460
+
461
+ Throws a `SelectUtilError` if the callback returns an invalid action.
462
+
463
+ This utility was reworked, it's old behaviour has moved to the `filterMap` utility.
133
464
 
134
465
  #### `sift(list)`
135
466
  Filters all falsy values out of a list.
@@ -148,6 +479,27 @@ sift([1, 0, 2, null, 3, undefined, false]);
148
479
  // [1, 2, 3]
149
480
  ```
150
481
 
482
+ #### `sum(list, mapper?)`
483
+ Sums a list of items into a total number.
484
+
485
+ ```ts
486
+ sum([1, 2, 3]);
487
+ // Expected output:
488
+ // 6
489
+
490
+ sum([1, 2, 3], (n) => n * 2);
491
+ // Expected output:
492
+ // 12
493
+
494
+ sum([false, true, "", "Hello", null, {}, undefined, []]);
495
+ // Expected output:
496
+ // 4
497
+
498
+ sum(["3", "4", "5"], (item) => Number.parseInt(item, 10));
499
+ // Expected output:
500
+ // 12
501
+ ```
502
+
151
503
  #### `toggle(list, itemToToggle, options?)`
152
504
  Toggles a value in an array: removes it if present, adds it if not.
153
505
 
@@ -200,6 +552,24 @@ chain(() => true, (value: boolean) => value ? "true" : "false");
200
552
  // "true"
201
553
  ```
202
554
 
555
+ #### `compose(...callbacks)`
556
+ Turns many callbacks into a single re-usable callback.
557
+
558
+ ```ts
559
+ const fn = compose(
560
+ (n: number) => n + 1,
561
+ (n: number) => n * 2,
562
+ );
563
+
564
+ fn(2);
565
+ // Expected output:
566
+ // 6
567
+
568
+ fn(5);
569
+ // Expected output:
570
+ // 12
571
+ ```
572
+
203
573
  #### `defer(callback)`
204
574
  Defers a callback to the next execution cycle.
205
575
 
@@ -207,6 +577,50 @@ Defers a callback to the next execution cycle.
207
577
  defer(() => console.log("runs after the current call stack clears"));
208
578
  ```
209
579
 
580
+ #### `noop()`
581
+ No operation, this function does nothing. Useful for placeholder code.
582
+
583
+ ```ts
584
+ noop();
585
+ // Expected output:
586
+ // undefined
587
+ ```
588
+
589
+ #### `pipe(value, callback)`
590
+ Pipes a value into a callback and returns its result.
591
+
592
+ ```ts
593
+ pipe(5, (n) => n * 2);
594
+ // Expected output:
595
+ // 10
596
+
597
+ pipe("Foo", (value) => `${value} Bar`);
598
+ // Expected output:
599
+ // "Foo Bar"
600
+ ```
601
+
602
+ #### `preset(callback, parameters)`
603
+ Presets the parameters of a callback with a callback that computes its arguments.
604
+
605
+ ```ts
606
+ const fn = preset(
607
+ Number.parseInt,
608
+ (value: string): [string, number] => [value, 10],
609
+ );
610
+
611
+ fn("10");
612
+ // Expected output:
613
+ // 10
614
+
615
+ fn("3.2");
616
+ // Expected output:
617
+ // 3
618
+
619
+ preset(Number.parseInt, ["0", 10])();
620
+ // Expected output:
621
+ // 0
622
+ ```
623
+
210
624
  #### `retry(callback, options?)`
211
625
  Retries an async (or sync) callback until it succeeds or the maximum number of attempts is reached.
212
626
 
@@ -225,6 +639,19 @@ Options:
225
639
  - `backoff` - whether to double the delay after each retry (default `false`)
226
640
  - `onRetry` - callback invoked with the error and attempt number on each failed attempt
227
641
 
642
+ #### `task(callback?)`
643
+ Executes the given callback in asynchronous context.
644
+
645
+ ```ts
646
+ // This yields execution to the microtask queue.
647
+ await task();
648
+
649
+ // A task that has a seperate asynchronous flow
650
+ task(async () => {
651
+ await doSomething();
652
+ });
653
+ ```
654
+
228
655
  <!-- !SECTION -->
229
656
  <!-- SECTION: Misc utils -->
230
657
 
@@ -242,6 +669,23 @@ compute((a: number, b: number) => a + b, 2, 3);
242
669
  // 5
243
670
  ```
244
671
 
672
+ #### `identity(value)`
673
+ Returns the given value as is, with its type inferred as narrowly as possible (as a `const` generic).
674
+
675
+ ```ts
676
+ identity(5);
677
+ // Expected output:
678
+ // 5
679
+
680
+ identity({
681
+ a: 1,
682
+ });
683
+ // Expected output:
684
+ // {
685
+ // a: 1,
686
+ // }
687
+ ```
688
+
245
689
  #### `isEmpty(value)`
246
690
  Checks if a value is considered empty.
247
691
 
@@ -276,91 +720,693 @@ isEmpty({
276
720
  // false (the key exists)
277
721
  ```
278
722
 
279
- #### `isPrimitive(value)`
280
- Checks if a value is a primitive: `string`, `number`, `boolean`, `symbol`, `null`, or `undefined`.
723
+ #### `isNull(value)`
724
+ Checks if a value is `null`.
281
725
 
282
726
  ```ts
283
- isPrimitive("foo");
727
+ isNull(null);
284
728
  // Expected output:
285
729
  // true
286
730
 
287
- isPrimitive({});
731
+ isNull(undefined);
288
732
  // Expected output:
289
733
  // false
290
734
  ```
291
735
 
292
- #### `range(startOrLength, end?, options?)`
293
- Returns a generator that yields values over a specified range (inclusive), optionally stepped and/or mapped to another value.
736
+ #### `isNullish(value)`
737
+ Checks if a value is nullish: `null` or `undefined`.
294
738
 
295
739
  ```ts
296
- for (const value of range(3)) {
297
- console.log(value);
298
- }
740
+ isNullish(null);
299
741
  // Expected output:
300
- // logs 0, 1, 2, 3
742
+ // true
301
743
 
302
- for (const value of range(0, 3)) {
303
- console.log(value);
304
- }
744
+ isNullish(undefined);
305
745
  // Expected output:
306
- // logs 0, 1, 2, 3
746
+ // true
307
747
 
308
- for (const value of range(0, 6, {
309
- step: 2,
310
- })) {
311
- console.log(value);
312
- }
748
+ isNullish(0);
313
749
  // Expected output:
314
- // logs 0, 2, 4, 6
750
+ // false
751
+ ```
315
752
 
316
- for (const value of range(0, 3, {
317
- valueMapper: (step) => `foo-${step}`,
318
- })) {
319
- console.log(value);
320
- }
753
+ #### `isPrimitive(value)`
754
+ Checks if a value is a primitive: `string`, `number`, `boolean`, `symbol`, `null`, or `undefined`.
755
+
756
+ ```ts
757
+ isPrimitive("foo");
321
758
  // Expected output:
322
- // logs "foo-0", "foo-1", "foo-2", "foo-3"
759
+ // true
760
+
761
+ isPrimitive({});
762
+ // Expected output:
763
+ // false
323
764
  ```
324
765
 
325
- #### `sleep(delay)`
326
- Returns a promise that resolves after the specified delay (in milliseconds).
766
+ #### `isPromise(value)`
767
+ Checks if a value is a `Promise` (an instance of `Promise`).
327
768
 
328
769
  ```ts
329
- await sleep(1000);
770
+ isPromise(Promise.resolve(1));
330
771
  // Expected output:
331
- // waits 1 second
332
- ```
772
+ // true
333
773
 
334
- <!-- !SECTION -->
335
- <!-- SECTION: Number utils -->
774
+ isPromise({
775
+ then: () => {},
776
+ });
777
+ // Expected output:
778
+ // false
779
+ ```
336
780
 
337
- ### Number utilities
338
- #### `toFloat(value, fallback?)`
339
- Converts a value to a float, falling back to a default (`0` by default) if the conversion fails or the value isn't a supported type.
781
+ #### `isPromiseLike(value)`
782
+ Checks if a value is promise-like: an object with a `then` function.
340
783
 
341
784
  ```ts
342
- toFloat("3.14");
785
+ isPromiseLike(Promise.resolve(1));
343
786
  // Expected output:
344
- // 3.14
787
+ // true
345
788
 
346
- toFloat(true);
789
+ isPromiseLike({
790
+ then: () => {},
791
+ });
347
792
  // Expected output:
348
- // 1
793
+ // true
349
794
 
350
- toFloat("not a number", -1);
795
+ isPromiseLike({});
351
796
  // Expected output:
352
- // -1
797
+ // false
353
798
  ```
354
799
 
355
- #### `toInt(value, fallback?)`
356
- Converts a value to an integer, falling back to a default (`0` by default) if the conversion fails or the value isn't a supported type.
800
+ #### `isUndefined(value)`
801
+ Checks if a value is `undefined`.
357
802
 
358
803
  ```ts
359
- toInt("42");
804
+ isUndefined(undefined);
360
805
  // Expected output:
361
- // 42
806
+ // true
362
807
 
363
- toInt(true);
808
+ isUndefined(null);
809
+ // Expected output:
810
+ // false
811
+ ```
812
+
813
+ #### `match(value, clause, fallback?)`
814
+ Matches a value to a clause that return a value
815
+ and returns a fallback if none of the cases match.
816
+
817
+ ```ts
818
+ const fn = (value: string) => {
819
+ return match(
820
+ value,
821
+ {
822
+ A: 1,
823
+ B: 2,
824
+ },
825
+ -1,
826
+ );
827
+ };
828
+
829
+ fn("A");
830
+ // Expected output:
831
+ // 1
832
+
833
+ fn("B");
834
+ // Expected output:
835
+ // 2
836
+
837
+ fn("C");
838
+ // Expected output:
839
+ // -1
840
+ ```
841
+
842
+ #### `Range(rangeString?)`
843
+ > The constructor of this has an overload:
844
+ > `Range(details?)`
845
+ >
846
+ > Details:
847
+ > - `start` - The start value of the range (optional).
848
+ > - `inclusiveStart` - If the range should consider the `start` to be inclusive (optional).
849
+ > - `end` - The end value of the range (optional)
850
+ > - `inclusiveEnd` - If the range should consider the `end` to be inclusive (optional).
851
+ > - `step` - The step value of the range (optional).
852
+ > - `mapper` - The mapper of the range, this maps a step to a value (optional).
853
+
854
+ This is a class representing a range value, it is an iterable and generates values based on a start and end value (if specified).
855
+
856
+ If no start of end value is specified the range will work as expected with methods, but trying to iterate over it will throw an error.
857
+
858
+ It can also be given a `step` and a `mapper` to define how it should be generating a value.
859
+
860
+ If the argument given is a string, then it is expected to have that string match the following definition:
861
+ `S?>?..=?E?` where:
862
+ * `S` - The start of the range (optional)
863
+ * `E` - The end of the range (optional)
864
+ * `>` - If the start value is exclusive of this range (optional)
865
+ * `=` - If the end value is inclusive of this range (optional)
866
+
867
+ Here is a simple table explaining the different types of range strings:
868
+ | Syntax | Range | Is iterable |
869
+ | -------------------| --------------- | ----------- |
870
+ | `[start]..[end]` | start ≤ x < end | Yes |
871
+ | `[start]>..[end]` | start < x < end | Yes |
872
+ | `[start]..=[end]` | start ≤ x ≤ end | Yes |
873
+ | `[start]>..=[end]` | start < x ≤ end | Yes |
874
+ | `..` | - | No |
875
+ | `[start]..` | start ≤ x | No |
876
+ | `[start]>..` | start < x | No |
877
+ | `..[end]` | x < end | No |
878
+ | `..=[end]` | x ≤ end | No |
879
+
880
+ If a value is not iterable, that means it will throw an error on attempting to iterate the range.
881
+ A full range is a range without bounds, this mostly exists for completeness and would effect how certain methods of the range work, see the methods for more details on how they are effected.
882
+
883
+ > This class can also be gotten from the [range](#rangestartorlength-end-options) utility function.
884
+
885
+ ##### `static from(range)`
886
+ Creates a new range with the details from the specified range.
887
+
888
+ > This does the same as [Range.clone](#clone)
889
+
890
+ ##### `details (getter)`
891
+ Gets the internal details of the Range.
892
+
893
+ > This is a getter, no value can be set here.
894
+
895
+ ###### `start (getter)`
896
+ Gets the start value of range.
897
+
898
+ > This is a getter, no value can be set here.
899
+
900
+ ###### `end (getter)`
901
+ Gets the end value of range.
902
+
903
+ > This is a getter, no value can be set here.
904
+
905
+ ###### `step (getter)`
906
+ Gets the step value of range.
907
+
908
+ > This is a getter, no value can be set here.
909
+
910
+ ###### `mapper (getter)`
911
+ Gets the mapper value of range.
912
+
913
+ > This is a getter, no value can be set here.
914
+
915
+ ##### `start(start?)`
916
+ Creates a new Range with a given start value set.
917
+
918
+ ##### `inclusiveStart(inclusiveStart)`
919
+ Creates a new Range with a given inclusive start value set.
920
+
921
+ ##### `end(end?)`
922
+ Creates a new Range with a given end value set.
923
+
924
+ ##### `inclusiveEnd(inclusiveEnd)`
925
+ Creates a new Range with a given inclusive end value set.
926
+
927
+ ##### `step(step?)`
928
+ Creates a new Range with a given step value set.
929
+
930
+ ##### `map(mapper)`
931
+ Creates a new Range with a given mapper set.
932
+
933
+ ##### `includes(value)`
934
+ Returns a boolean to signal if the given value is included in the range.
935
+
936
+ > Notes:
937
+ > - If the range is a full range, then this will **always** return true.
938
+ > - `NaN` will **always** return false (unless the range is a full range).
939
+
940
+ ##### `excludes(value)`
941
+ Returns a boolean to signal if the given value is excluded from the range.
942
+
943
+ > Notes:
944
+ > - If the range is a full range, then this will **always** return false.
945
+ > - `NaN` will **always** return false.
946
+
947
+ ##### `toArray()`
948
+ Returns an array based on the values of the range.
949
+
950
+ ##### `clone()`
951
+ Returns a new Range with same details.
952
+
953
+ > This does the same as [static Range.from](#static-fromrange)
954
+
955
+ #### `range(startOrLength, end?, options?)`
956
+ Returns a [Range](#rangerangestring) that yields values over a specified range (inclusive), optionally stepped and/or mapped to another value.
957
+
958
+ ```ts
959
+ for (const value of range(3)) {
960
+ console.log(value);
961
+ }
962
+ // Expected output:
963
+ // logs 0, 1, 2, 3
964
+
965
+ for (const value of range(0, 3)) {
966
+ console.log(value);
967
+ }
968
+ // Expected output:
969
+ // logs 0, 1, 2, 3
970
+
971
+ for (const value of range(0, 6, {
972
+ step: 2,
973
+ })) {
974
+ console.log(value);
975
+ }
976
+ // Expected output:
977
+ // logs 0, 2, 4, 6
978
+
979
+ for (const value of range(0, 3, {
980
+ valueMapper: (step) => `foo-${step}`,
981
+ })) {
982
+ console.log(value);
983
+ }
984
+ // Expected output:
985
+ // logs "foo-0", "foo-1", "foo-2", "foo-3"
986
+
987
+ for (const value of range(0, 3, {
988
+ inclusiveStart: false,
989
+ })) {
990
+ console.log(value);
991
+ }
992
+ // Expected output:
993
+ // logs 1, 2, 3
994
+
995
+ for (const value of range(0, 3, {
996
+ inclusiveEnd: false,
997
+ })) {
998
+ console.log(value);
999
+ }
1000
+ // Expected output:
1001
+ // logs 0, 1, 2
1002
+ ```
1003
+
1004
+ options:
1005
+ - `step` - The steps used to generate the array.
1006
+ - `valueMapper` - A mapper function to map a step to a value.
1007
+ - `inclusiveStart` - Wether the start value is considered inclusive.
1008
+ - `inclusiveEnd` - Wether the end value is considered inclusive.
1009
+
1010
+ > NOTE: `inclusiveEnd` default value here differs from the `inclusiveEnd` value set by [`Range`](#rangerangestring), this is for backwards compatibility.
1011
+
1012
+ #### `raise(value)`
1013
+ Throws the given value, never returns.
1014
+
1015
+ - A string is wrapped in an `Error`.
1016
+ - A function is called without arguments and its result is thrown.
1017
+ - Any other value is thrown as is.
1018
+
1019
+ This is useful for throwing in expression positions, such as a fallback.
1020
+
1021
+ ```ts
1022
+ raise("Something went wrong");
1023
+ // Expected to throw:
1024
+ // Error("Something went wrong")
1025
+
1026
+ raise(() => new RangeError("Out of range"));
1027
+ // Expected to throw:
1028
+ // RangeError("Out of range")
1029
+ ```
1030
+
1031
+ #### `readOnly(value, deepFreeze?)` / `isReadOnly(value)`
1032
+ `readOnly` returns a read-only copy of an object, array, map, or set.
1033
+
1034
+ `isReadOnly` checks if a value is frozen.
1035
+
1036
+ ```ts
1037
+ const original = {
1038
+ a: 1,
1039
+ nested: {
1040
+ b: 2
1041
+ }
1042
+ };
1043
+ const shallow = readOnly(original);
1044
+ const deep = readOnly(original, true);
1045
+
1046
+ isReadOnly(shallow);
1047
+ // Expected output:
1048
+ // true
1049
+
1050
+ shallow.nested === original.nested;
1051
+ // Expected output:
1052
+ // true (nested values are shared and still mutable)
1053
+
1054
+ deep.nested === original.nested;
1055
+ // Expected output:
1056
+ // false (nested values are cloned and frozen)
1057
+
1058
+ isReadOnly(original);
1059
+ // Expected output:
1060
+ // false
1061
+ ```
1062
+
1063
+ #### `safe(callback)`
1064
+ Executes the given callback and returns an option of the result.
1065
+
1066
+ ```ts
1067
+ safe(() => {
1068
+ return "Hello world";
1069
+ });
1070
+ // Expected output:
1071
+ // {
1072
+ // success: true,
1073
+ // value: "Hello world",
1074
+ // }
1075
+
1076
+ safe(() => {
1077
+ throw new Error("Goodbye world");
1078
+ });
1079
+ // Expected output:
1080
+ // {
1081
+ // success: false,
1082
+ // error: Error("Goodbye world"),
1083
+ // }
1084
+ ```
1085
+
1086
+ #### `sleep(delay)`
1087
+ Returns a promise that resolves after the specified delay (in milliseconds).
1088
+
1089
+ ```ts
1090
+ await sleep(1000);
1091
+ // Expected output:
1092
+ // waits 1 second
1093
+ ```
1094
+
1095
+ #### `timeout(value, delayMs, options?)` / `isTimeoutError(value)`
1096
+ Wraps a promise (or a callback that returns one) into a promise that rejects with a `TimeoutError` if it hasn't settled after the given delay (in milliseconds). If the promise settles first, its result (or error) is passed through.
1097
+
1098
+ When given a callback, it receives an `AbortSignal` which is aborted when the delay elapses, so the underlying operation can be cancelled.
1099
+
1100
+ `isTimeoutError` checks if a value is a `TimeoutError`.
1101
+
1102
+ ```ts
1103
+ await timeout(sleep(100), 1000);
1104
+ // Expected output:
1105
+ // resolves after 100ms
1106
+
1107
+ await timeout(sleep(2000), 1000);
1108
+ // Expected to throw:
1109
+ // TimeoutError("The operation was timed out after 1000ms")
1110
+
1111
+ await timeout(
1112
+ (signal) => fetch("https://example.com", {
1113
+ signal,
1114
+ }),
1115
+ 1000,
1116
+ );
1117
+ // Expected output:
1118
+ // the response, or a rejection (and an aborted request) if it takes longer than 1 second
1119
+
1120
+ try {
1121
+ await timeout(sleep(2000), 1000);
1122
+ } catch (error) {
1123
+ isTimeoutError(error);
1124
+ // Expected output:
1125
+ // true
1126
+ }
1127
+ ```
1128
+
1129
+ Options:
1130
+ - `onTimeout` - a callback invoked with the delay when it elapses. Throwing inside it rejects the promise with the thrown value instead of a `TimeoutError`.
1131
+
1132
+ #### `unwrap(option, fallback?)`
1133
+ Directly returns the option's value, or throws the option's error.
1134
+ An option's error won't be thrown when a fallback is provided.
1135
+
1136
+ ```ts
1137
+ const option = safe(() => {
1138
+ throw new Error("Goodbye world");
1139
+ });
1140
+
1141
+ unwrap(option);
1142
+ // Expected to throw:
1143
+ // Error("Goodbye world")
1144
+
1145
+ unwrap(option, null);
1146
+ // Expected output:
1147
+ // null
1148
+ ```
1149
+
1150
+ #### `values(target)`
1151
+ Returns an array of values based on the given target.
1152
+
1153
+ ```ts
1154
+ values([1, 2, 3]);
1155
+ // Expected output:
1156
+ // [1, 2, 3]
1157
+
1158
+ values(new Set([4, 5, 6]));
1159
+ // Expected output:
1160
+ // [4, 5, 6]
1161
+
1162
+ values({
1163
+ A: "a",
1164
+ B: "b",
1165
+ C: "c",
1166
+ });
1167
+ // Expected output:
1168
+ // ["a", "b", "c"]
1169
+
1170
+ values(new Map([
1171
+ ["D", "d"],
1172
+ ["E", "e"],
1173
+ ["F", "f"],
1174
+ ]));
1175
+ // Expected output:
1176
+ // ["d", "e", "f"]
1177
+ ```
1178
+
1179
+ <!-- !SECTION -->
1180
+ <!-- SECTION: Number utils -->
1181
+
1182
+ ### Number utilities
1183
+ #### Math utilities
1184
+ ##### `isPrime(value)`
1185
+ Checks if the given value is a prime number.
1186
+
1187
+ ```ts
1188
+ isPrime(11);
1189
+ // Expected output:
1190
+ // true
1191
+
1192
+ isPrime(4);
1193
+ // Expected output:
1194
+ // false
1195
+
1196
+ isPrime(103);
1197
+ // Expected output:
1198
+ // true
1199
+
1200
+ isPrime(-9.2);
1201
+ // Expected output:
1202
+ // false
1203
+ ```
1204
+
1205
+ ##### `mod(dividend, divisor)`
1206
+ Returns the modulo of a dividend and a divisor.
1207
+
1208
+ ```ts
1209
+ mod(10, 5);
1210
+ // Expected output:
1211
+ // 0
1212
+
1213
+ mod(-2, 4);
1214
+ // Expected output:
1215
+ // 2
1216
+
1217
+ mod(6, 10);
1218
+ // Expected output:
1219
+ // 6
1220
+ ```
1221
+
1222
+ #### `clamp(min, value, max)`
1223
+ Clamps a number between a minimum and maximum value.
1224
+
1225
+ ```ts
1226
+ clamp(-5, 0, 5);
1227
+ // Expected output:
1228
+ // 0
1229
+
1230
+ clamp(-5, 20, 5);
1231
+ // Expected output:
1232
+ // 5
1233
+
1234
+ clamp(-5, -20, 5);
1235
+ // Expected output:
1236
+ // -5
1237
+ ```
1238
+
1239
+ #### `isDecimal(value)`
1240
+ Checks if the given value is a number with decimals.
1241
+
1242
+ ```ts
1243
+ isDecimal(1.1);
1244
+ // Expected output:
1245
+ // true
1246
+
1247
+ isDecimal(1);
1248
+ // Expected output:
1249
+ // false
1250
+
1251
+ isDecimal(NaN);
1252
+ // Expected output:
1253
+ // false
1254
+ ```
1255
+
1256
+ #### `isEven(value)`
1257
+ Checks if the given value is an even number.
1258
+
1259
+ ```ts
1260
+ isEven(4);
1261
+ // Expected output:
1262
+ // true
1263
+
1264
+ isEven(3);
1265
+ // Expected output:
1266
+ // false
1267
+
1268
+ isEven(0.5);
1269
+ // Expected output:
1270
+ // false
1271
+ ```
1272
+
1273
+ #### `isInteger(value)`
1274
+ Checks if the given value is an integer.
1275
+
1276
+ ```ts
1277
+ isInteger(4);
1278
+ // Expected output:
1279
+ // true
1280
+
1281
+ isInteger(4.5);
1282
+ // Expected output:
1283
+ // false
1284
+ ```
1285
+
1286
+ #### `isNegative(value)`
1287
+ Checks if the given value is a negative number.
1288
+
1289
+ ```ts
1290
+ isNegative(-5);
1291
+ // Expected output:
1292
+ // true
1293
+
1294
+ isNegative(5);
1295
+ // Expected output:
1296
+ // false
1297
+
1298
+ isNegative(-0);
1299
+ // Expected output:
1300
+ // true
1301
+ ```
1302
+
1303
+ #### `isOdd(value)`
1304
+ Checks if the given value is an odd number.
1305
+
1306
+ ```ts
1307
+ isOdd(3);
1308
+ // Expected output:
1309
+ // true
1310
+
1311
+ isOdd(4);
1312
+ // Expected output:
1313
+ // false
1314
+
1315
+ isOdd(0.5);
1316
+ // Expected output:
1317
+ // false
1318
+ ```
1319
+
1320
+ #### `isPositive(value)`
1321
+ Checks if the given value is a positive number.
1322
+
1323
+ ```ts
1324
+ isPositive(5);
1325
+ // Expected output:
1326
+ // true
1327
+
1328
+ isPositive(-5);
1329
+ // Expected output:
1330
+ // false
1331
+
1332
+ isPositive(0);
1333
+ // Expected output:
1334
+ // true
1335
+ ```
1336
+
1337
+ #### `negative(value)`
1338
+ Converts a number into a negative number.
1339
+
1340
+ ```ts
1341
+ negative(5);
1342
+ // Expected output:
1343
+ // -5
1344
+
1345
+ negative(-5);
1346
+ // Expected output:
1347
+ // -5
1348
+ ```
1349
+
1350
+ #### `positive(value)`
1351
+ Converts a number into a positive number.
1352
+
1353
+ ```ts
1354
+ positive(-5);
1355
+ // Expected output:
1356
+ // 5
1357
+
1358
+ positive(5);
1359
+ // Expected output:
1360
+ // 5
1361
+ ```
1362
+
1363
+ #### `sign(value)`
1364
+ Returns the sign of the given number: `1` if positive, `-1` if negative, `0` if zero (`NaN` is converted into zero).
1365
+
1366
+ ```ts
1367
+ sign(5);
1368
+ // Expected output:
1369
+ // 1
1370
+
1371
+ sign(-5);
1372
+ // Expected output:
1373
+ // -1
1374
+
1375
+ sign(0);
1376
+ // Expected output:
1377
+ // 0
1378
+
1379
+ sign(NaN);
1380
+ // Expected output:
1381
+ // 0
1382
+ ```
1383
+
1384
+ #### `toFloat(value, fallback?)`
1385
+ Converts a value to a float, falling back to a default (`0` by default) if the conversion fails or the value isn't a supported type.
1386
+
1387
+ ```ts
1388
+ toFloat("3.14");
1389
+ // Expected output:
1390
+ // 3.14
1391
+
1392
+ toFloat(true);
1393
+ // Expected output:
1394
+ // 1
1395
+
1396
+ toFloat("not a number", -1);
1397
+ // Expected output:
1398
+ // -1
1399
+ ```
1400
+
1401
+ #### `toInt(value, fallback?)`
1402
+ Converts a value to an integer, falling back to a default (`0` by default) if the conversion fails or the value isn't a supported type.
1403
+
1404
+ ```ts
1405
+ toInt("42");
1406
+ // Expected output:
1407
+ // 42
1408
+
1409
+ toInt(true);
364
1410
  // Expected output:
365
1411
  // 1
366
1412
 
@@ -369,6 +1415,23 @@ toInt("not a number", -1);
369
1415
  // -1
370
1416
  ```
371
1417
 
1418
+ #### `trunc(value, fractionDigits?)`
1419
+ Truncates a number to the specified number of fraction digits.
1420
+
1421
+ ```ts
1422
+ trunc(1.58);
1423
+ // Expected output:
1424
+ // 1
1425
+
1426
+ trunc(1.456, 2);
1427
+ // Expected output:
1428
+ // 1.45
1429
+
1430
+ trunc(1.789, 10)
1431
+ // Expected output:
1432
+ // 1.789
1433
+ ```
1434
+
372
1435
  <!-- !SECTION -->
373
1436
  <!-- SECTION: object -->
374
1437
 
@@ -385,6 +1448,25 @@ entries({
385
1448
  // [["a", 1], ["b", "two"]] (typed as [K, T[K]][])
386
1449
  ```
387
1450
 
1451
+ #### `extend(value, other)`
1452
+ Extends an object with another object.
1453
+
1454
+ ```ts
1455
+ extend(
1456
+ {
1457
+ key: "value",
1458
+ },
1459
+ {
1460
+ foo: "bar",
1461
+ },
1462
+ );
1463
+ // Expected output:
1464
+ // {
1465
+ // key: "value",
1466
+ // foo: "bar",
1467
+ // }
1468
+ ```
1469
+
388
1470
  #### `isObject(item)`
389
1471
  Checks if a value is an object, excluding arrays.
390
1472
 
@@ -474,6 +1556,235 @@ pick(
474
1556
  // }
475
1557
  ```
476
1558
 
1559
+ <!-- !SECTION -->
1560
+ <!-- SECTION: Random utils -->
1561
+ ### Randomization utilities
1562
+ Almost all utilites that generate someting at random are done with a cryptographically secure pseudorandom number generator (called from now own **CSPRNG**) and utilizes the [`crypto.getRandomValues`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) method. If a utility does not use this, it will be mentioned in the description of that utility.
1563
+
1564
+ #### UUID utilities
1565
+ ##### `uuidMax()`
1566
+ Returns the max UUID string possible.
1567
+
1568
+ ```ts
1569
+ uuidMax();
1570
+ // Expected output:
1571
+ // "ffffffff-ffff-ffff-ffff-ffffffffffff"
1572
+ ```
1573
+
1574
+ ##### `uuidNil()`
1575
+ Returns the nil UUID string.
1576
+
1577
+ ```ts
1578
+ uuidNil();
1579
+ // Expected output:
1580
+ // "00000000-0000-0000-0000-000000000000"
1581
+ ```
1582
+
1583
+ #### `uuidV1(options?)`
1584
+ > This is also aliased to `v1`
1585
+
1586
+ Returns a randomly generated UUID V1 string.
1587
+
1588
+ ```ts
1589
+ uuidV1();
1590
+ // Possible output:
1591
+ // c232ab00-9414-11ec-b3c8-9f68deced846
1592
+
1593
+ uuidV1({
1594
+ random: Uint8Array.of(0, 0, 0, 0, 0, 0, 0, 0, 0x33c8 >> 8, 0x33c8 & 0xff, 0x9f, 0x68, 0xde, 0xce, 0xd8, 0x46),
1595
+ milliseconds: 0x17f22e279b0,
1596
+ nanoseconds: 0,
1597
+ clockSequence: 0x33c8,
1598
+ node: Uint8Array.of(0x9f, 0x68, 0xde, 0xce, 0xd8, 0x46),
1599
+ })
1600
+ // Expected output:
1601
+ // c232ab00-9414-11ec-b3c8-9f68deced846
1602
+ ```
1603
+
1604
+ options:
1605
+ - `random` - The random bytes used to generate the UUID.
1606
+ - `rng` - A function to generate a list of random bytes for UUID generation.
1607
+ - `milliseconds` - A number that represents the amount of milliseconds from the EPOCH (number of milliseconds since 01-01-1970).
1608
+ - `nanoseconds` - A number that represents tha amount of nanoseconds have elapsed in the specified millisecond (This will always be 0 if not defined, javascript does not measure beyond the millisecond range).
1609
+ - `clockSequence` - The current clock sequence used for generation.
1610
+ - `node` - A list of random bytes used to complete the UUID V1.
1611
+
1612
+ #### `uuidV4(options?)`
1613
+ > This is also aliased to `v4` or `uuid`
1614
+
1615
+ Returns a randomly generated UUID V4 string.
1616
+
1617
+ ```ts
1618
+ uuidV4();
1619
+ // Possible output:
1620
+ // 919108f7-52d1-4320-9bac-f847db4148a8
1621
+
1622
+ uuidV4({
1623
+ random: Uint8Array.of(0x91, 0x91, 0x08, 0xf7, 0x52, 0xd1, 0x43, 0x20, 0x9b, 0xac, 0xf8, 0x47, 0xdb, 0x41, 0x48, 0xa8),
1624
+ })
1625
+ // Expected output:
1626
+ // 919108f7-52d1-4320-9bac-f847db4148a8
1627
+ ```
1628
+
1629
+ options:
1630
+ - `random` - The random bytes used to generate the UUID.
1631
+ - `rng` - A function to generate a list of random bytes for UUID generation.
1632
+
1633
+ #### `uuidV7(options?)`
1634
+ > This is also aliased to `v7`
1635
+
1636
+ Returns a randomly generated UUID V7 string.
1637
+
1638
+ ```ts
1639
+ uuidV7();
1640
+ // Possible output:
1641
+ // 017f22e2-79b0-7cc3-98c4-dc0c0c07398f
1642
+
1643
+ uuidV7({
1644
+ random: Uint8Array.of(0x10, 0x7f, 0x22, 0xe2, 0x79, 0xb0, 0x7c, 0xc3, 0x98, 0xc4, 0xdc, 0x0c, 0x0c, 0x07, 0x39, 0x8f),
1645
+ milliseconds: 0x017f22e279b0,
1646
+ sequence: 0xcc363137,
1647
+ })
1648
+ // Expected output:
1649
+ // 017f22e2-79b0-7cc3-98c4-dc0c0c07398f
1650
+ ```
1651
+
1652
+ options:
1653
+ - `random` - The random bytes used to generate the UUID.
1654
+ - `rng` - A function to generate a list of random bytes for UUID generation.
1655
+ - `milliseconds` - A number that represents the amount of milliseconds from the EPOCH (number of milliseconds since 01-01-1970).
1656
+ - `sequence` - The current clock sequence used for generation.
1657
+
1658
+ #### `chance(percentage)`
1659
+ Returns a random boolean based on the specified percentage.
1660
+ The percentage must be a number between 0 and 1. If it is not inside that range it will return a fixed value according to that percentage, so if percentage is more than or equal to 1 it will always return true and if percentage is less than or equal to 0 it will always return false.
1661
+
1662
+ ```ts
1663
+ chance(0.5);
1664
+ // Expected output:
1665
+ // true | false
1666
+
1667
+ chance(1);
1668
+ // Expected output:
1669
+ // true
1670
+
1671
+ chance(0);
1672
+ // Expected output:
1673
+ // false
1674
+ ```
1675
+
1676
+ #### `draw(list)`
1677
+ Returns a random item from a specified list (or `undefined` if the list is empty).
1678
+
1679
+ ```ts
1680
+ draw([0, 1, 2, 3]);
1681
+ // Expected output:
1682
+ // 0 | 1 | 2 | 3
1683
+
1684
+ draw([]);
1685
+ // Expected output:
1686
+ // undefined
1687
+ ```
1688
+
1689
+ #### `maybe()`
1690
+ Returns a random boolean.
1691
+
1692
+ ```ts
1693
+ maybe();
1694
+ // Expected output:
1695
+ // true | false
1696
+ ```
1697
+
1698
+ #### `random(min?, max?)`
1699
+ Returns a random value between a specified minimum and maximum value.
1700
+
1701
+ If the minimum and maximum values contradict each other, then this function will return `NaN`.
1702
+
1703
+ > NOTE: this utility does **NOT** use [CSPRNG](#randomization-utilities).
1704
+
1705
+ ```ts
1706
+ random();
1707
+ // Expected output:
1708
+ // n where n > 0 and n < 1
1709
+
1710
+ random(10, 20);
1711
+ // Expected output:
1712
+ // n where n > 10 and n < 20
1713
+
1714
+ random(1, 0);
1715
+ // Expected output:
1716
+ // NaN
1717
+ ```
1718
+
1719
+ #### `scatter(list, split?, options?)`
1720
+ Given an array, splits that array into 2 given a hard split and devides the items at random into the 2 given lists.
1721
+ The split must be a number between 0 and 1. If it is not inside that range it will return a fixed sized array according to that split, so if percentage is more than or equal to 1 it will always return `[list, []]` and if percentage is less than or equal to 0 it will always return `[[], list]` (Do note that these are handled as exception cases, meaning if this is the case then the first list will not be in a random order, but preserved order instead).
1722
+
1723
+ > NOTE: the first array will be in a random order, while the second array will have the order preserved.
1724
+
1725
+ ```ts
1726
+ scatter([0, 1, 2, 3, 4]);
1727
+ // Possible output:
1728
+ // [[3, 2, 4], [0, 1]]
1729
+
1730
+ scatter([0, 1, 2, 3, 4], 0.6);
1731
+ // Possible output:
1732
+ // [[3, 2, 4], [0, 1]]
1733
+
1734
+ scatter([0, 1, 2, 3, 4], 0.4);
1735
+ // Possible output:
1736
+ // [[2, 4], [0, 1, 3]]
1737
+
1738
+
1739
+ scatter([0, 1, 2, 3, 4], 0.5, {
1740
+ bias: "FLOOR",
1741
+ });
1742
+ // Possible output:
1743
+ // [[2, 4], [0, 1, 3]]
1744
+
1745
+ scatter([0, 1, 2, 3, 4], 0.5, {
1746
+ bias: "ROUND",
1747
+ });
1748
+ // Possible output:
1749
+ // [[3, 2, 4], [0, 1]]
1750
+
1751
+ scatter([0, 1, 2, 3, 4], 0.5, {
1752
+ bias: "CEILING",
1753
+ });
1754
+ // Possible output:
1755
+ // [[3, 2, 4], [0, 1]]
1756
+ ```
1757
+
1758
+ options:
1759
+ - `bias` - When the split does not work exactly for the given array length, this will decide how to split the final item (e.g. given an array of 5 items and a split of `0.5` (50%), the bias will decide if the split will be `3 - 2` or `2 - 3`) (default = `"ROUND"`)
1760
+
1761
+ #### `shuffle(list)`
1762
+ Shuffles the array into a new array will all the items in a random order.
1763
+
1764
+ ```ts
1765
+ shuffle([0, 1, 2, 3, 4]);
1766
+ // Possible output:
1767
+ // [2, 4, 0, 1, 3]
1768
+ ```
1769
+
1770
+ #### `uid(length?, charset?)`
1771
+ Returns a random string of characters gotten from a specified charset that can be used for ids.
1772
+ The default length is `8` and the default charset is `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`.
1773
+
1774
+ ```ts
1775
+ uid();
1776
+ // Possible output:
1777
+ // "Dae3pmZH"
1778
+
1779
+ uid(12);
1780
+ // Possible output:
1781
+ // "9lqD8Mp3CUrK"
1782
+
1783
+ uid(8, "Aa");
1784
+ // Possible output:
1785
+ // "AaAAAaAA"
1786
+ ```
1787
+
477
1788
  <!-- !SECTION -->
478
1789
  <!-- SECTION: String utils -->
479
1790
 
@@ -527,7 +1838,7 @@ capitalize("some value");
527
1838
  Converts a string into a custom cased version of the string, required a seperator and word transformer to work.
528
1839
 
529
1840
  > NOTE:
530
- This library also exports other casing utils that use this function under the hood and can (and most likely should) be used in most cases.
1841
+ > This library also exports other casing utils that use this function under the hood and can (and most likely should) be used in most cases.
531
1842
 
532
1843
  ```ts
533
1844
  customCase("someValue", {