@catstral/levy-utils 1.1.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 (92) hide show
  1. package/README.md +1188 -17
  2. package/dist/array/index.d.ts +20 -8
  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/toggle/index.d.ts +2 -2
  22. package/dist/callback/index.d.ts +8 -5
  23. package/dist/callback/utils/noop/index.d.ts +8 -0
  24. package/dist/callback/utils/pipe/index.d.ts +12 -0
  25. package/dist/callback/utils/preset/index.d.ts +6 -4
  26. package/dist/callback/utils/retry/index.d.ts +2 -2
  27. package/dist/callback/utils/task/index.d.ts +12 -0
  28. package/dist/index.d.ts +9 -8
  29. package/dist/index.js +5 -0
  30. package/dist/misc/index.d.ts +17 -8
  31. package/dist/misc/utils/identity/index.d.ts +10 -0
  32. package/dist/misc/utils/isNull/index.d.ts +9 -0
  33. package/dist/misc/utils/isNullish/index.d.ts +13 -0
  34. package/dist/misc/utils/isPrimitive/index.d.ts +2 -2
  35. package/dist/misc/utils/isPromise/index.d.ts +9 -0
  36. package/dist/misc/utils/isPromiseLike/index.d.ts +9 -0
  37. package/dist/misc/utils/isUndefined/index.d.ts +9 -0
  38. package/dist/misc/utils/match/index.d.ts +1 -1
  39. package/dist/misc/utils/option/index.d.ts +54 -0
  40. package/dist/misc/utils/raise/index.d.ts +19 -0
  41. package/dist/misc/utils/range/index.d.ts +218 -11
  42. package/dist/misc/utils/readOnly/index.d.ts +1 -1
  43. package/dist/misc/utils/sleep/index.d.ts +2 -2
  44. package/dist/misc/utils/timeout/index.d.ts +40 -0
  45. package/dist/misc/utils/values/index.d.ts +1 -1
  46. package/dist/number/index.d.ts +13 -2
  47. package/dist/number/math/index.d.ts +2 -0
  48. package/dist/number/math/utils/isPrime/index.d.ts +9 -0
  49. package/dist/number/math/utils/mod/index.d.ts +10 -0
  50. package/dist/number/types.d.ts +11 -0
  51. package/dist/number/utils/clamp/index.d.ts +13 -0
  52. package/dist/number/utils/isDecimal/index.d.ts +11 -0
  53. package/dist/number/utils/isEven/index.d.ts +9 -0
  54. package/dist/number/utils/isInteger/index.d.ts +11 -0
  55. package/dist/number/utils/isOdd/index.d.ts +9 -0
  56. package/dist/number/utils/negative/index.d.ts +21 -0
  57. package/dist/number/utils/positive/index.d.ts +21 -0
  58. package/dist/number/utils/sign/index.d.ts +14 -0
  59. package/dist/number/utils/toInt/index.d.ts +1 -1
  60. package/dist/number/utils/trunc/index.d.ts +16 -0
  61. package/dist/object/index.d.ts +6 -6
  62. package/dist/object/utils/extend/index.d.ts +11 -4
  63. package/dist/random/helper.d.ts +6 -0
  64. package/dist/random/index.d.ts +6 -0
  65. package/dist/random/utils/chance/index.d.ts +13 -0
  66. package/dist/random/utils/draw/index.d.ts +13 -0
  67. package/dist/random/utils/maybe/index.d.ts +8 -0
  68. package/dist/random/utils/random/index.d.ts +14 -0
  69. package/dist/random/utils/scatter/index.d.ts +30 -0
  70. package/dist/random/utils/shuffle/index.d.ts +11 -0
  71. package/dist/random/utils/uid/index.d.ts +12 -0
  72. package/dist/random/uuid/helpers.d.ts +4 -0
  73. package/dist/random/uuid/index.d.ts +5 -0
  74. package/dist/random/uuid/types.d.ts +16 -0
  75. package/dist/random/uuid/utils/max/index.d.ts +8 -0
  76. package/dist/random/uuid/utils/nil/index.d.ts +8 -0
  77. package/dist/random/uuid/utils/v1/index.d.ts +46 -0
  78. package/dist/random/uuid/utils/v4/index.d.ts +22 -0
  79. package/dist/random/uuid/utils/v7/index.d.ts +34 -0
  80. package/dist/string/casing/index.d.ts +11 -11
  81. package/dist/string/casing/utils/camel/index.d.ts +1 -1
  82. package/dist/string/casing/utils/custom/index.d.ts +1 -1
  83. package/dist/string/casing/utils/http/index.d.ts +1 -1
  84. package/dist/string/casing/utils/kebab/index.d.ts +1 -1
  85. package/dist/string/casing/utils/pascal/index.d.ts +1 -1
  86. package/dist/string/casing/utils/snake/index.d.ts +1 -1
  87. package/dist/string/casing/utils/title/index.d.ts +1 -1
  88. package/dist/string/index.d.ts +4 -4
  89. package/dist/types.d.ts +2 -0
  90. package/package.json +9 -14
  91. package/dist/levyUtils.cjs +0 -5
  92. package/dist/levyUtils.js +0 -1244
package/README.md CHANGED
@@ -26,10 +26,22 @@ import { range, sift, toggle } from "@catstral/levy-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)
34
46
  - [sum](#sumlist-mapper)
35
47
  - [toggle](#togglelist-itemtotoggle-options)
@@ -37,19 +49,62 @@ A list of all the utilities supported:
37
49
  - [chain](#chaincallbacks)
38
50
  - [compose](#composecallbacks)
39
51
  - [defer](#defercallback)
52
+ - [noop](#noop)
53
+ - [pipe](#pipevalue-callback)
40
54
  - [preset](#presetcallback-parameters)
41
55
  - [retry](#retrycallback-options)
56
+ - [task](#taskcallback)
42
57
  - [Miscellaneous utilities](#miscellaneous-utilities)
43
58
  - [compute / isComputation](#computevalue-args--iscomputationvalue)
59
+ - [identity](#identityvalue)
44
60
  - [isEmpty](#isemptyvalue)
61
+ - [isNull](#isnullvalue)
62
+ - [isNullish](#isnullishvalue)
45
63
  - [isPrimitive](#isprimitivevalue)
64
+ - [isPromise](#ispromisevalue)
65
+ - [isPromiseLike](#ispromiselikevalue)
66
+ - [isUndefined](#isundefinedvalue)
46
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)
47
83
  - [range](#rangestartorlength-end-options)
84
+ - [raise](#raisevalue)
85
+ - [readOnly / isReadOnly](#readonlyvalue-deepfreeze--isreadonlyvalue)
86
+ - [safe](#safecallback)
48
87
  - [sleep](#sleepdelay)
88
+ - [timeout / isTimeoutError](#timeoutvalue-delayms-options--istimeouterrorvalue)
89
+ - [unwrap](#unwrapoption-fallback)
49
90
  - [values](#valuestarget)
50
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)
51
105
  - [toFloat](#tofloatvalue-fallback)
52
106
  - [toInt](#tointvalue-fallback)
107
+ - [trunc](#truncvalue-fractiondigits)
53
108
  - [Object utilities](#object-utilities)
54
109
  - [entries](#entriesvalue)
55
110
  - [extend](#extendvalue-other)
@@ -57,6 +112,20 @@ A list of all the utilities supported:
57
112
  - [keys](#keysvalue)
58
113
  - [omit](#omitobject-keys)
59
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)
60
129
  - [String utilities](#string-utilities)
61
130
  - [Casing utilities](#casing-utilities)
62
131
  - [camelCase](#camelcasestr-options)
@@ -86,6 +155,15 @@ cluster([1, 2, 3, 4, 5], 2);
86
155
  // [[1, 2], [3, 4], [5]]
87
156
  ```
88
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
+
89
167
  #### `counting(list, identity)`
90
168
  Reduces a list down to an object of keys (as determined by the `identity` callback) mapped to how many times that key occurred.
91
169
 
@@ -99,6 +177,49 @@ counting(["a", "b", "a", "c", "a"], (item) => item);
99
177
  // }
100
178
  ```
101
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
+
102
223
  #### `fork(list, condition)`
103
224
  Splits a list into a tuple of two arrays based on a condition: items that pass, and items that don't.
104
225
 
@@ -108,6 +229,44 @@ fork([1, 2, 3, 4], (n) => n % 2 === 0);
108
229
  // [[2, 4], [1, 3]]
109
230
  ```
110
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
+
111
270
  ### `list(startOrLength, end?, options?)`
112
271
  Returns an array with values to a specified size (inclusive), optionally stepped and/or mapped to another value.
113
272
 
@@ -133,9 +292,175 @@ list(0, 3, {
133
292
  // ["foo-0", "foo-1", "foo-2", "foo-3"]
134
293
  ```
135
294
 
136
- <!-- TODO -->
137
- #### `select(list, filter, mapper)`
138
- 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.
139
464
 
140
465
  #### `sift(list)`
141
466
  Filters all falsy values out of a list.
@@ -252,6 +577,28 @@ Defers a callback to the next execution cycle.
252
577
  defer(() => console.log("runs after the current call stack clears"));
253
578
  ```
254
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
+
255
602
  #### `preset(callback, parameters)`
256
603
  Presets the parameters of a callback with a callback that computes its arguments.
257
604
 
@@ -268,6 +615,10 @@ fn("10");
268
615
  fn("3.2");
269
616
  // Expected output:
270
617
  // 3
618
+
619
+ preset(Number.parseInt, ["0", 10])();
620
+ // Expected output:
621
+ // 0
271
622
  ```
272
623
 
273
624
  #### `retry(callback, options?)`
@@ -288,6 +639,19 @@ Options:
288
639
  - `backoff` - whether to double the delay after each retry (default `false`)
289
640
  - `onRetry` - callback invoked with the error and attempt number on each failed attempt
290
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
+
291
655
  <!-- !SECTION -->
292
656
  <!-- SECTION: Misc utils -->
293
657
 
@@ -305,6 +669,23 @@ compute((a: number, b: number) => a + b, 2, 3);
305
669
  // 5
306
670
  ```
307
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
+
308
689
  #### `isEmpty(value)`
309
690
  Checks if a value is considered empty.
310
691
 
@@ -339,6 +720,36 @@ isEmpty({
339
720
  // false (the key exists)
340
721
  ```
341
722
 
723
+ #### `isNull(value)`
724
+ Checks if a value is `null`.
725
+
726
+ ```ts
727
+ isNull(null);
728
+ // Expected output:
729
+ // true
730
+
731
+ isNull(undefined);
732
+ // Expected output:
733
+ // false
734
+ ```
735
+
736
+ #### `isNullish(value)`
737
+ Checks if a value is nullish: `null` or `undefined`.
738
+
739
+ ```ts
740
+ isNullish(null);
741
+ // Expected output:
742
+ // true
743
+
744
+ isNullish(undefined);
745
+ // Expected output:
746
+ // true
747
+
748
+ isNullish(0);
749
+ // Expected output:
750
+ // false
751
+ ```
752
+
342
753
  #### `isPrimitive(value)`
343
754
  Checks if a value is a primitive: `string`, `number`, `boolean`, `symbol`, `null`, or `undefined`.
344
755
 
@@ -352,20 +763,67 @@ isPrimitive({});
352
763
  // false
353
764
  ```
354
765
 
766
+ #### `isPromise(value)`
767
+ Checks if a value is a `Promise` (an instance of `Promise`).
768
+
769
+ ```ts
770
+ isPromise(Promise.resolve(1));
771
+ // Expected output:
772
+ // true
773
+
774
+ isPromise({
775
+ then: () => {},
776
+ });
777
+ // Expected output:
778
+ // false
779
+ ```
780
+
781
+ #### `isPromiseLike(value)`
782
+ Checks if a value is promise-like: an object with a `then` function.
783
+
784
+ ```ts
785
+ isPromiseLike(Promise.resolve(1));
786
+ // Expected output:
787
+ // true
788
+
789
+ isPromiseLike({
790
+ then: () => {},
791
+ });
792
+ // Expected output:
793
+ // true
794
+
795
+ isPromiseLike({});
796
+ // Expected output:
797
+ // false
798
+ ```
799
+
800
+ #### `isUndefined(value)`
801
+ Checks if a value is `undefined`.
802
+
803
+ ```ts
804
+ isUndefined(undefined);
805
+ // Expected output:
806
+ // true
807
+
808
+ isUndefined(null);
809
+ // Expected output:
810
+ // false
811
+ ```
812
+
355
813
  #### `match(value, clause, fallback?)`
356
814
  Matches a value to a clause that return a value
357
815
  and returns a fallback if none of the cases match.
358
816
 
359
817
  ```ts
360
818
  const fn = (value: string) => {
361
- return match(
362
- value,
363
- {
364
- A: 1,
365
- B: 2,
366
- },
367
- -1
368
- );
819
+ return match(
820
+ value,
821
+ {
822
+ A: 1,
823
+ B: 2,
824
+ },
825
+ -1,
826
+ );
369
827
  };
370
828
 
371
829
  fn("A");
@@ -381,8 +839,121 @@ fn("C");
381
839
  // -1
382
840
  ```
383
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
+
384
955
  #### `range(startOrLength, end?, options?)`
385
- Returns a generator that yields values over a specified range (inclusive), optionally stepped and/or mapped to another value.
956
+ Returns a [Range](#rangerangestring) that yields values over a specified range (inclusive), optionally stepped and/or mapped to another value.
386
957
 
387
958
  ```ts
388
959
  for (const value of range(3)) {
@@ -412,10 +983,108 @@ for (const value of range(0, 3, {
412
983
  }
413
984
  // Expected output:
414
985
  // logs "foo-0", "foo-1", "foo-2", "foo-3"
415
- ```
416
986
 
417
- #### `sleep(delay)`
418
- Returns a promise that resolves after the specified delay (in milliseconds).
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).
419
1088
 
420
1089
  ```ts
421
1090
  await sleep(1000);
@@ -423,6 +1092,61 @@ await sleep(1000);
423
1092
  // waits 1 second
424
1093
  ```
425
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
+
426
1150
  #### `values(target)`
427
1151
  Returns an array of values based on the given target.
428
1152
 
@@ -456,6 +1180,207 @@ values(new Map([
456
1180
  <!-- SECTION: Number utils -->
457
1181
 
458
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
+
459
1384
  #### `toFloat(value, fallback?)`
460
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.
461
1386
 
@@ -490,6 +1415,23 @@ toInt("not a number", -1);
490
1415
  // -1
491
1416
  ```
492
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
+
493
1435
  <!-- !SECTION -->
494
1436
  <!-- SECTION: object -->
495
1437
 
@@ -614,6 +1556,235 @@ pick(
614
1556
  // }
615
1557
  ```
616
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
+
617
1788
  <!-- !SECTION -->
618
1789
  <!-- SECTION: String utils -->
619
1790
 
@@ -667,7 +1838,7 @@ capitalize("some value");
667
1838
  Converts a string into a custom cased version of the string, required a seperator and word transformer to work.
668
1839
 
669
1840
  > NOTE:
670
- 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.
671
1842
 
672
1843
  ```ts
673
1844
  customCase("someValue", {