@oscarpalmer/atoms 0.193.1 → 0.195.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 (121) hide show
  1. package/dist/array/difference.mjs +2 -2
  2. package/dist/array/index.d.mts +2 -2
  3. package/dist/array/index.mjs +2 -2
  4. package/dist/array/intersection.mjs +2 -2
  5. package/dist/array/move.mjs +1 -1
  6. package/dist/array/slice.mjs +5 -5
  7. package/dist/array/sort.d.mts +5 -1
  8. package/dist/array/sort.mjs +4 -2
  9. package/dist/array/swap.mjs +1 -1
  10. package/dist/array/union.mjs +2 -2
  11. package/dist/beacon.d.mts +8 -1
  12. package/dist/beacon.mjs +52 -60
  13. package/dist/color/constants.d.mts +1 -1
  14. package/dist/color/constants.mjs +3 -5
  15. package/dist/color/instance.mjs +34 -41
  16. package/dist/color/misc/format.d.mts +3 -2
  17. package/dist/color/misc/format.mjs +4 -1
  18. package/dist/color/misc/is.d.mts +9 -1
  19. package/dist/color/misc/is.mjs +11 -1
  20. package/dist/color/misc/state.d.mts +6 -6
  21. package/dist/color/misc/state.mjs +11 -14
  22. package/dist/color/models.d.mts +23 -68
  23. package/dist/color/space/hex.mjs +1 -1
  24. package/dist/color/space/rgb.mjs +1 -1
  25. package/dist/function/index.d.mts +1 -2
  26. package/dist/function/index.mjs +1 -2
  27. package/dist/function/limit.d.mts +0 -6
  28. package/dist/function/limit.mjs +2 -2
  29. package/dist/function/once.d.mts +0 -3
  30. package/dist/function/once.mjs +17 -14
  31. package/dist/function/retry.d.mts +1 -24
  32. package/dist/function/retry.mjs +1 -1
  33. package/dist/herald.d.mts +2 -72
  34. package/dist/herald.mjs +2 -92
  35. package/dist/index.d.mts +3332 -3418
  36. package/dist/index.mjs +1850 -1870
  37. package/dist/internal/abort.d.mts +10 -0
  38. package/dist/internal/abort.mjs +14 -0
  39. package/dist/internal/array/chunk.mjs +2 -2
  40. package/dist/internal/array/find.mjs +2 -2
  41. package/dist/{array → internal/array}/get.d.mts +2 -2
  42. package/dist/{array → internal/array}/get.mjs +2 -2
  43. package/dist/{array → internal/array}/match.d.mts +2 -2
  44. package/dist/{array → internal/array}/match.mjs +15 -15
  45. package/dist/internal/array/sets.d.mts +4 -4
  46. package/dist/internal/array/sets.mjs +7 -7
  47. package/dist/internal/defaults.d.mts +5 -0
  48. package/dist/internal/defaults.mjs +9 -0
  49. package/dist/{function → internal/function}/assert.d.mts +2 -2
  50. package/dist/{function → internal/function}/assert.mjs +4 -4
  51. package/dist/{function → internal/function}/memoize.d.mts +2 -2
  52. package/dist/{function → internal/function}/memoize.mjs +22 -35
  53. package/dist/internal/function/timer.mjs +19 -15
  54. package/dist/{function → internal/function}/work.d.mts +2 -2
  55. package/dist/{function → internal/function}/work.mjs +15 -13
  56. package/dist/internal/herald.d.mts +71 -0
  57. package/dist/internal/herald.mjs +110 -0
  58. package/dist/internal/number.d.mts +1 -2
  59. package/dist/internal/number.mjs +8 -11
  60. package/dist/internal/{result.d.mts → result/misc.d.mts} +42 -3
  61. package/dist/internal/result/misc.mjs +51 -0
  62. package/dist/{result → internal/result}/models.d.mts +2 -2
  63. package/dist/{sized → internal/sized}/map.d.mts +1 -1
  64. package/dist/{sized → internal/sized}/map.mjs +2 -2
  65. package/dist/internal/{sized.d.mts → sized/misc.d.mts} +1 -1
  66. package/dist/internal/sized/misc.mjs +12 -0
  67. package/dist/{string → internal/string}/case.d.mts +1 -1
  68. package/dist/{string → internal/string}/case.mjs +22 -22
  69. package/dist/internal/{string.d.mts → string/misc.d.mts} +1 -1
  70. package/dist/internal/{string.mjs → string/misc.mjs} +5 -5
  71. package/dist/internal/subscription.d.mts +24 -8
  72. package/dist/internal/subscription.mjs +49 -36
  73. package/dist/internal/value/compare.mjs +1 -1
  74. package/dist/internal/value/equal.mjs +6 -6
  75. package/dist/internal/value/has.d.mts +1 -1
  76. package/dist/internal/value/misc.d.mts +1 -1
  77. package/dist/internal/value/misc.mjs +16 -16
  78. package/dist/internal/value/set.mjs +2 -2
  79. package/dist/is.mjs +2 -2
  80. package/dist/logger.mjs +15 -39
  81. package/dist/promise/constants.d.mts +17 -0
  82. package/dist/promise/constants.mjs +14 -0
  83. package/dist/promise/delay.mjs +7 -10
  84. package/dist/promise/helpers.d.mts +1 -1
  85. package/dist/promise/helpers.mjs +3 -3
  86. package/dist/promise/index.d.mts +1 -1
  87. package/dist/promise/index.mjs +14 -17
  88. package/dist/promise/misc.d.mts +3 -2
  89. package/dist/promise/misc.mjs +10 -8
  90. package/dist/promise/models.d.mts +5 -17
  91. package/dist/promise/models.mjs +4 -13
  92. package/dist/promise/timed.mjs +9 -10
  93. package/dist/query.mjs +16 -16
  94. package/dist/queue.mjs +104 -120
  95. package/dist/random.mjs +8 -8
  96. package/dist/result/index.d.mts +1 -4
  97. package/dist/result/index.mjs +2 -2
  98. package/dist/result/match.d.mts +1 -4
  99. package/dist/result/match.mjs +5 -5
  100. package/dist/result/misc.d.mts +3 -42
  101. package/dist/result/misc.mjs +4 -30
  102. package/dist/result/work/flow.d.mts +1 -4
  103. package/dist/result/work/flow.mjs +6 -6
  104. package/dist/result/work/pipe.d.mts +1 -4
  105. package/dist/result/work/pipe.mjs +5 -5
  106. package/dist/sized/set.mjs +1 -1
  107. package/dist/string/fuzzy.mjs +25 -20
  108. package/dist/string/index.d.mts +1 -1
  109. package/dist/string/index.mjs +8 -8
  110. package/dist/string/match.mjs +1 -1
  111. package/dist/string/normalize.mjs +16 -16
  112. package/dist/string/template.mjs +3 -3
  113. package/dist/subscription.d.mts +2 -0
  114. package/dist/subscription.mjs +2 -0
  115. package/dist/value/clone.mjs +10 -10
  116. package/dist/value/diff.mjs +1 -1
  117. package/dist/value/smush.mjs +3 -3
  118. package/package.json +35 -14
  119. package/dist/internal/result.mjs +0 -25
  120. package/dist/internal/sized.mjs +0 -12
  121. /package/dist/{result → internal/result}/models.mjs +0 -0
package/dist/index.mjs CHANGED
@@ -55,7 +55,7 @@ function findValues(type, array, parameters, mapper) {
55
55
  const { length } = array;
56
56
  const { bool, key, value } = getFindParameters(parameters);
57
57
  const callbacks = getArrayCallbacks(bool, key);
58
- if (type === "unique" && callbacks?.keyed == null && length >= UNIQUE_THRESHOLD) {
58
+ if (type === "unique" && callbacks?.keyed == null && length >= FIND_UNIQUE_THRESHOLD) {
59
59
  result.matched = [...new Set(array)];
60
60
  return result;
61
61
  }
@@ -91,7 +91,7 @@ function getFindParameters(original) {
91
91
  const FIND_VALUE_INDEX = "index";
92
92
  const FIND_VALUE_ITEM = "item";
93
93
  const FIND_VALUES_UNIQUE = "unique";
94
- const UNIQUE_THRESHOLD = 100;
94
+ const FIND_UNIQUE_THRESHOLD = 100;
95
95
  //#endregion
96
96
  //#region src/array/filter.ts
97
97
  function exclude(array, ...parameters) {
@@ -156,7 +156,7 @@ function chunk(array, size) {
156
156
  if (!Array.isArray(array)) return [];
157
157
  if (array.length === 0) return [];
158
158
  const { length } = array;
159
- const actualSize = typeof size === "number" && size > 0 && size <= MAX_SIZE ? size : MAX_SIZE;
159
+ const actualSize = typeof size === "number" && size > 0 && size <= CHUNK_MAX_SIZE ? size : CHUNK_MAX_SIZE;
160
160
  if (length <= actualSize) return [array];
161
161
  const chunks = [];
162
162
  let index = 0;
@@ -166,7 +166,7 @@ function chunk(array, size) {
166
166
  }
167
167
  return chunks;
168
168
  }
169
- const MAX_SIZE = 5e3;
169
+ const CHUNK_MAX_SIZE = 5e3;
170
170
  //#endregion
171
171
  //#region src/internal/array/compact.ts
172
172
  function compact(array, strict) {
@@ -181,15 +181,6 @@ function compact(array, strict) {
181
181
  return compacted;
182
182
  }
183
183
  //#endregion
184
- //#region src/internal/array/index-of.ts
185
- function indexOf(array, ...parameters) {
186
- return findValue(FIND_VALUE_INDEX, array, parameters, false);
187
- }
188
- indexOf.last = lastIndexOf;
189
- function lastIndexOf(array, ...parameters) {
190
- return findValue(FIND_VALUE_INDEX, array, parameters, true);
191
- }
192
- //#endregion
193
184
  //#region src/internal/is.ts
194
185
  /**
195
186
  * Is the value an array or a plain object?
@@ -365,6 +356,89 @@ function isTypedArray(value) {
365
356
  return isTypedArray.types.has(value?.constructor);
366
357
  }
367
358
  //#endregion
359
+ //#region src/internal/array/get.ts
360
+ function getArray(value, indiced) {
361
+ if (Array.isArray(value)) return value;
362
+ if (value instanceof Map) return [...value.entries()];
363
+ if (value instanceof Set) return [...value.values()];
364
+ if (isNonPlainObject(value)) return [value];
365
+ if (indiced !== true) return Object.entries(value);
366
+ const keys = Object.keys(value);
367
+ const { length } = keys;
368
+ const array = [];
369
+ for (let index = 0; index < length; index += 1) {
370
+ const key = keys[index];
371
+ const asNumber = Number.parseInt(key, 10);
372
+ if (!Number.isNaN(asNumber)) array[asNumber] = value[key];
373
+ }
374
+ return array;
375
+ }
376
+ //#endregion
377
+ //#region src/internal/array/index-of.ts
378
+ function indexOf(array, ...parameters) {
379
+ return findValue(FIND_VALUE_INDEX, array, parameters, false);
380
+ }
381
+ indexOf.last = lastIndexOf;
382
+ function lastIndexOf(array, ...parameters) {
383
+ return findValue(FIND_VALUE_INDEX, array, parameters, true);
384
+ }
385
+ //#endregion
386
+ //#region src/internal/array/match.ts
387
+ function endsWithArray(haystack, needle, key) {
388
+ return endings.has(getPosition(haystack, needle, key)[1]);
389
+ }
390
+ function getArrayComparison(haystack, needle, key) {
391
+ return getPosition(haystack, needle, key)[1];
392
+ }
393
+ function getName(start, haystack, needle) {
394
+ if (start === 0) return haystack === needle ? MATCH_COMPARISON_SAME : MATCH_COMPARISON_START;
395
+ return start + needle === haystack ? MATCH_COMPARISON_END : MATCH_COMPARISON_INSIDE;
396
+ }
397
+ function getPosition(haystack, needle, key) {
398
+ if (!Array.isArray(haystack) || !Array.isArray(needle)) return invalid;
399
+ const haystackLength = haystack.length;
400
+ const needleLength = needle.length;
401
+ if (haystackLength === 0 || needleLength === 0) return outside;
402
+ if (needleLength > haystackLength) return outside;
403
+ const callback = getArrayCallback(key);
404
+ const limit = haystackLength - needleLength + 1;
405
+ let needleValues = callback == null ? needle : needle.slice();
406
+ if (callback != null) for (let needleIndex = 0; needleIndex < needleLength; needleIndex += 1) needleValues[needleIndex] = callback(needle[needleIndex], needleIndex, needle);
407
+ for (let haystackIndex = 0; haystackIndex < limit; haystackIndex += 1) {
408
+ let haystackItem = haystack[haystackIndex];
409
+ let haystackValue = callback?.(haystackItem, haystackIndex, haystack) ?? haystackItem;
410
+ if (!Object.is(haystackValue, needleValues[0])) continue;
411
+ if (needleLength === 1) return [haystackIndex, getName(haystackIndex, haystackLength, needleLength)];
412
+ for (let needleIndex = 1; needleIndex < needleLength; needleIndex += 1) {
413
+ haystackItem = haystack[haystackIndex + needleIndex];
414
+ haystackValue = callback?.(haystackItem, haystackIndex + needleIndex, haystack) ?? haystackItem;
415
+ if (!Object.is(haystackValue, needleValues[needleIndex])) break;
416
+ if (needleIndex === needleLength - 1) return [haystackIndex, getName(haystackIndex, haystackLength, needleLength)];
417
+ }
418
+ }
419
+ return outside;
420
+ }
421
+ function includesArray(haystack, needle, key) {
422
+ return !outsides.has(getPosition(haystack, needle, key)[1]);
423
+ }
424
+ function indexOfArray(haystack, needle, key) {
425
+ return getPosition(haystack, needle, key)[0];
426
+ }
427
+ function startsWithArray(haystack, needle, key) {
428
+ return starts.has(getPosition(haystack, needle, key)[1]);
429
+ }
430
+ const MATCH_COMPARISON_END = "end";
431
+ const MATCH_COMPARISON_INSIDE = "inside";
432
+ const MATCH_COMPARISON_INVALID = "invalid";
433
+ const MATCH_COMPARISON_OUTSIDE = "outside";
434
+ const MATCH_COMPARISON_SAME = "same";
435
+ const MATCH_COMPARISON_START = "start";
436
+ const endings = /* @__PURE__ */ new Set([MATCH_COMPARISON_END, MATCH_COMPARISON_SAME]);
437
+ const invalid = [-1, MATCH_COMPARISON_INVALID];
438
+ const outside = [-1, MATCH_COMPARISON_OUTSIDE];
439
+ const outsides = /* @__PURE__ */ new Set([MATCH_COMPARISON_INVALID, MATCH_COMPARISON_OUTSIDE]);
440
+ const starts = /* @__PURE__ */ new Set([MATCH_COMPARISON_START, MATCH_COMPARISON_SAME]);
441
+ //#endregion
368
442
  //#region src/internal/random.ts
369
443
  function getRandomFloatingNumberValue(inclusive, minimum, maximum) {
370
444
  let maxFloat = isNumber(maximum) && maximum <= Number.MAX_SAFE_INTEGER ? maximum : Number.MAX_SAFE_INTEGER;
@@ -416,9 +490,9 @@ function shuffle(array) {
416
490
  //#region src/internal/array/sets.ts
417
491
  function compareSets(type, first, second, key) {
418
492
  if (!Array.isArray(first)) return [];
419
- const isDifference = type === COMPARE_SETS_DIFFERENCE;
420
- const isIntersection = type === COMPARE_SETS_INTERSECTION;
421
- const isUnion = type === COMPARE_SETS_UNION;
493
+ const isDifference = type === SETS_COMPARE_DIFFERENCE;
494
+ const isIntersection = type === SETS_COMPARE_INTERSECTION;
495
+ const isUnion = type === SETS_COMPARE_UNION;
422
496
  if (first.length === 0) return isDifference ? first.slice() : isIntersection ? [] : second.slice();
423
497
  if (!Array.isArray(second) || second.length === 0) return isIntersection ? [] : first.slice();
424
498
  const callback = getArrayCallback(key);
@@ -439,13 +513,13 @@ function compareSets(type, first, second, key) {
439
513
  }
440
514
  return result;
441
515
  }
442
- const COMPARE_SETS_DIFFERENCE = "difference";
443
- const COMPARE_SETS_INTERSECTION = "intersection";
444
- const COMPARE_SETS_UNION = "union";
516
+ const SETS_COMPARE_DIFFERENCE = "difference";
517
+ const SETS_COMPARE_INTERSECTION = "intersection";
518
+ const SETS_COMPARE_UNION = "union";
445
519
  //#endregion
446
520
  //#region src/array/difference.ts
447
521
  function difference(first, second, key) {
448
- return compareSets(COMPARE_SETS_DIFFERENCE, first, second, key);
522
+ return compareSets(SETS_COMPARE_DIFFERENCE, first, second, key);
449
523
  }
450
524
  //#endregion
451
525
  //#region src/array/exists.ts
@@ -498,24 +572,6 @@ function times(length, value) {
498
572
  return values;
499
573
  }
500
574
  //#endregion
501
- //#region src/array/get.ts
502
- function getArray(value, indiced) {
503
- if (Array.isArray(value)) return value;
504
- if (value instanceof Map) return [...value.entries()];
505
- if (value instanceof Set) return [...value.values()];
506
- if (isNonPlainObject(value)) return [value];
507
- if (indiced !== true) return Object.entries(value);
508
- const keys = Object.keys(value);
509
- const { length } = keys;
510
- const array = [];
511
- for (let index = 0; index < length; index += 1) {
512
- const key = keys[index];
513
- const asNumber = Number.parseInt(key, 10);
514
- if (!Number.isNaN(asNumber)) array[asNumber] = value[key];
515
- }
516
- return array;
517
- }
518
- //#endregion
519
575
  //#region src/internal/array/insert.ts
520
576
  function insertChunkedValues(type, array, items, start, deleteCount) {
521
577
  const actualDeleteCount = deleteCount < 0 ? 0 : deleteCount;
@@ -549,7 +605,7 @@ function insert(array, indexOrItems, items) {
549
605
  //#endregion
550
606
  //#region src/array/intersection.ts
551
607
  function intersection(first, second, key) {
552
- return compareSets(COMPARE_SETS_INTERSECTION, first, second, key);
608
+ return compareSets(SETS_COMPARE_INTERSECTION, first, second, key);
553
609
  }
554
610
  //#endregion
555
611
  //#region src/array/partition.ts
@@ -558,62 +614,6 @@ function partition(array, ...parameters) {
558
614
  return [matched, notMatched];
559
615
  }
560
616
  //#endregion
561
- //#region src/array/match.ts
562
- function endsWithArray(haystack, needle, key) {
563
- return endings.has(getPosition(haystack, needle, key)[1]);
564
- }
565
- function getArrayComparison(haystack, needle, key) {
566
- return getPosition(haystack, needle, key)[1];
567
- }
568
- function getName(start, haystack, needle) {
569
- if (start === 0) return haystack === needle ? COMPARISON_SAME : COMPARISON_START;
570
- return start + needle === haystack ? COMPARISON_END : COMPARISON_INSIDE;
571
- }
572
- function getPosition(haystack, needle, key) {
573
- if (!Array.isArray(haystack) || !Array.isArray(needle)) return invalid;
574
- const haystackLength = haystack.length;
575
- const needleLength = needle.length;
576
- if (haystackLength === 0 || needleLength === 0) return outside;
577
- if (needleLength > haystackLength) return outside;
578
- const callback = getArrayCallback(key);
579
- const limit = haystackLength - needleLength + 1;
580
- let needleValues = callback == null ? needle : needle.slice();
581
- if (callback != null) for (let needleIndex = 0; needleIndex < needleLength; needleIndex += 1) needleValues[needleIndex] = callback(needle[needleIndex], needleIndex, needle);
582
- for (let haystackIndex = 0; haystackIndex < limit; haystackIndex += 1) {
583
- let haystackItem = haystack[haystackIndex];
584
- let haystackValue = callback?.(haystackItem, haystackIndex, haystack) ?? haystackItem;
585
- if (!Object.is(haystackValue, needleValues[0])) continue;
586
- if (needleLength === 1) return [haystackIndex, getName(haystackIndex, haystackLength, needleLength)];
587
- for (let needleIndex = 1; needleIndex < needleLength; needleIndex += 1) {
588
- haystackItem = haystack[haystackIndex + needleIndex];
589
- haystackValue = callback?.(haystackItem, haystackIndex + needleIndex, haystack) ?? haystackItem;
590
- if (!Object.is(haystackValue, needleValues[needleIndex])) break;
591
- if (needleIndex === needleLength - 1) return [haystackIndex, getName(haystackIndex, haystackLength, needleLength)];
592
- }
593
- }
594
- return outside;
595
- }
596
- function includesArray(haystack, needle, key) {
597
- return !outsides.has(getPosition(haystack, needle, key)[1]);
598
- }
599
- function indexOfArray(haystack, needle, key) {
600
- return getPosition(haystack, needle, key)[0];
601
- }
602
- function startsWithArray(haystack, needle, key) {
603
- return starts.has(getPosition(haystack, needle, key)[1]);
604
- }
605
- const COMPARISON_END = "end";
606
- const COMPARISON_INSIDE = "inside";
607
- const COMPARISON_INVALID = "invalid";
608
- const COMPARISON_OUTSIDE = "outside";
609
- const COMPARISON_SAME = "same";
610
- const COMPARISON_START = "start";
611
- const endings = /* @__PURE__ */ new Set([COMPARISON_END, COMPARISON_SAME]);
612
- const invalid = [-1, COMPARISON_INVALID];
613
- const outside = [-1, COMPARISON_OUTSIDE];
614
- const outsides = /* @__PURE__ */ new Set([COMPARISON_INVALID, COMPARISON_OUTSIDE]);
615
- const starts = /* @__PURE__ */ new Set([COMPARISON_START, COMPARISON_SAME]);
616
- //#endregion
617
617
  //#region src/array/push.ts
618
618
  /**
619
619
  * Push items into an array _(at the end)_
@@ -669,13 +669,13 @@ const SINGLE_MESSAGE = "Multiple items were found";
669
669
  //#endregion
670
670
  //#region src/array/slice.ts
671
671
  function drop(array, first, second) {
672
- return extract(EXTRACT_DROP, array, first, second);
672
+ return extract(SLICE_DROP, array, first, second);
673
673
  }
674
674
  function extract(type, array, first, second) {
675
675
  if (!Array.isArray(array)) return [];
676
676
  const { length } = array;
677
677
  if (length === 0) return [];
678
- const isTake = type === EXTRACT_TAKE;
678
+ const isTake = type === SLICE_TAKE;
679
679
  if (typeof first === "number") {
680
680
  if (Math.abs(first) >= length) return isTake ? array.slice() : [];
681
681
  if (first === 0) return isTake ? [] : array.slice();
@@ -713,10 +713,10 @@ function slice(array, first, second) {
713
713
  return first >= 0 ? array.slice(first, second) : array.slice(array.length + first, array.length + second);
714
714
  }
715
715
  function take(array, first, second) {
716
- return extract(EXTRACT_TAKE, array, first, second);
716
+ return extract(SLICE_TAKE, array, first, second);
717
717
  }
718
- const EXTRACT_DROP = "drop";
719
- const EXTRACT_TAKE = "take";
718
+ const SLICE_DROP = "drop";
719
+ const SLICE_TAKE = "take";
720
720
  //#endregion
721
721
  //#region src/array/splice.ts
722
722
  function splice(array, start, deleteCountOrItems, items) {
@@ -764,7 +764,7 @@ function toggle(array, values, key) {
764
764
  //#endregion
765
765
  //#region src/array/union.ts
766
766
  function union(first, second, key) {
767
- return compareSets(COMPARE_SETS_UNION, first, second, key);
767
+ return compareSets(SETS_COMPARE_UNION, first, second, key);
768
768
  }
769
769
  //#endregion
770
770
  //#region src/array/unique.ts
@@ -927,7 +927,7 @@ const aggregators = {
927
927
  sum: calculateSum
928
928
  };
929
929
  //#endregion
930
- //#region src/internal/string.ts
930
+ //#region src/internal/string/misc.ts
931
931
  /**
932
932
  * Get the string value from any value
933
933
  *
@@ -954,7 +954,7 @@ function getString(value) {
954
954
  return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
955
955
  }
956
956
  function ignoreKey(key) {
957
- return EXPRESSION_IGNORED.test(key);
957
+ return STRING_EXPRESSION_IGNORED.test(key);
958
958
  }
959
959
  function interpolate(strings, values) {
960
960
  const { length } = strings;
@@ -1005,10 +1005,10 @@ function tryEncode(value) {
1005
1005
  * @returns Array of words found in the string
1006
1006
  */
1007
1007
  function words(value) {
1008
- return typeof value === "string" ? value.match(EXPRESSION_WORDS) ?? [] : [];
1008
+ return typeof value === "string" ? value.match(STRING_EXPRESSION_WORDS) ?? [] : [];
1009
1009
  }
1010
- const EXPRESSION_IGNORED = /(^|\.)(__proto__|constructor|prototype)(\.|$)/i;
1011
- const EXPRESSION_WORDS = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
1010
+ const STRING_EXPRESSION_IGNORED = /(^|\.)(__proto__|constructor|prototype)(\.|$)/i;
1011
+ const STRING_EXPRESSION_WORDS = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
1012
1012
  //#endregion
1013
1013
  //#region src/internal/value/handlers.ts
1014
1014
  function getCompareHandlers(owner, options) {
@@ -1236,8 +1236,10 @@ function getValueSorter(value, modifier) {
1236
1236
  function initializeSorter(first, second) {
1237
1237
  const sorters = getSorters(first, getModifier(first, second));
1238
1238
  const sorter = (array) => sortArray(array, sorters);
1239
- sorter.index = (array, item) => getIndex(array, item, sorters);
1240
- sorter.is = (array) => isSortedArray(array, sorters);
1239
+ Object.defineProperties(sorter, {
1240
+ index: { value: (array, item) => getIndex(array, item, sorters) },
1241
+ is: { value: (array) => isSortedArray(array, sorters) }
1242
+ });
1241
1243
  return sorter;
1242
1244
  }
1243
1245
  function isSorted(array, first, second) {
@@ -1379,70 +1381,204 @@ function toRecordArrays(array, first, second) {
1379
1381
  return groupValues(array, first, second, true);
1380
1382
  }
1381
1383
  //#endregion
1382
- //#region src/internal/result.ts
1383
- function isError(value, extended) {
1384
- return isResultValue(value, false) && (extended === true ? value.original instanceof Error : true);
1385
- }
1386
- function isOk(value) {
1387
- return isResultValue(value, true);
1388
- }
1384
+ //#region src/internal/function/misc.ts
1389
1385
  /**
1390
- * Is the value a _Result_?
1391
- *
1392
- * @param value Value to check
1393
- * @returns `true` if the value is a _Result_, otherwise `false`
1386
+ * A function that does nothing, which can be useful, I guess…
1394
1387
  */
1395
- function isResult(value) {
1396
- return isResultValue(value, true) || isResultValue(value, false);
1397
- }
1398
- function isResultValue(value, okValue) {
1399
- if (isNonPlainObject(value)) return false;
1400
- return value.ok === okValue && (okValue ? PROPERTY_VALUE : PROPERTY_ERROR) in value;
1401
- }
1402
- const PROPERTY_ERROR = "error";
1403
- const PROPERTY_VALUE = "value";
1388
+ function noop() {}
1404
1389
  //#endregion
1405
- //#region src/result/misc.ts
1406
- function error(value, original) {
1407
- return getError(value, original);
1390
+ //#region src/internal/function/timer.ts
1391
+ function getAsyncTimer(type, callback, time) {
1392
+ function cancel() {
1393
+ clearTimer(id);
1394
+ if (last != null && !last.running) {
1395
+ last.reject();
1396
+ last = void 0;
1397
+ }
1398
+ }
1399
+ async function run(item) {
1400
+ const now = performance.now();
1401
+ start ??= now;
1402
+ if (interval === 0 || now - start >= interval - TIMER_OFFSET) {
1403
+ start = throttle ? now : void 0;
1404
+ item.running = true;
1405
+ try {
1406
+ let result = callback(...item.parameters);
1407
+ if (result instanceof Promise) result = await result;
1408
+ item.resolve(result);
1409
+ } catch (error) {
1410
+ item.reject(error);
1411
+ } finally {
1412
+ item.running = false;
1413
+ }
1414
+ } else id = startTimer(() => run(item));
1415
+ }
1416
+ const interval = getInterval(time);
1417
+ const throttle = type === TIMER_THROTTLE;
1418
+ let id;
1419
+ let last;
1420
+ let start;
1421
+ const timer = (...parameters) => {
1422
+ cancel();
1423
+ const next = {
1424
+ parameters,
1425
+ running: false
1426
+ };
1427
+ next.promise = new Promise((resolve, reject) => {
1428
+ next.reject = reject;
1429
+ next.resolve = resolve;
1430
+ });
1431
+ last = next;
1432
+ if (throttle) run(next);
1433
+ else id = startTimer(() => run(next));
1434
+ return next.promise;
1435
+ };
1436
+ Object.defineProperty(timer, TIMER_CANCEL, { value: () => cancel() });
1437
+ return timer;
1408
1438
  }
1409
- function getError(value, original) {
1410
- const errorResult = {
1411
- error: value,
1412
- ok: false
1439
+ function getInterval(value) {
1440
+ return typeof value === "number" && value > 0 ? value : 0;
1441
+ }
1442
+ function getTimer(type, callback, time) {
1443
+ function cancel() {
1444
+ clearTimer(id);
1445
+ }
1446
+ function run() {
1447
+ const now = performance.now();
1448
+ start ??= now;
1449
+ if (interval === 0 || now - start >= interval - TIMER_OFFSET) {
1450
+ start = throttle ? now : void 0;
1451
+ callback(...args);
1452
+ } else id = startTimer(run);
1453
+ }
1454
+ const interval = getInterval(time);
1455
+ const throttle = type === TIMER_THROTTLE;
1456
+ let args;
1457
+ let id;
1458
+ let start;
1459
+ const timer = (...parameters) => {
1460
+ cancel();
1461
+ args = parameters;
1462
+ if (throttle) run();
1463
+ else id = startTimer(run);
1413
1464
  };
1414
- if (original instanceof Error) errorResult.original = original;
1415
- return errorResult;
1465
+ Object.defineProperty(timer, TIMER_CANCEL, { value: () => cancel() });
1466
+ return timer;
1416
1467
  }
1468
+ const TIMER_CANCEL = "cancel";
1469
+ const TIMER_DEBOUNCE = "debounce";
1470
+ const TIMER_OFFSET = 5;
1471
+ const TIMER_THROTTLE = "throttle";
1472
+ const TIMER_WAIT = "wait";
1473
+ // istanbul ignore next
1474
+ const clearTimer = typeof cancelAnimationFrame === "function" ? cancelAnimationFrame : clearTimeout;
1475
+ // istanbul ignore next
1476
+ const startTimer = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout;
1477
+ //#endregion
1478
+ //#region src/function/limit.ts
1417
1479
  /**
1418
- * Creates an ok result
1480
+ * Debounce a function, ensuring it is only called after `time` milliseconds have passed
1419
1481
  *
1420
- * @param value Value
1421
- * @returns Ok result
1482
+ * - When called, successful _(finished)_ results will resolve and errors will reject
1483
+ * - On subsequent calls, existing calls will be canceled _(rejected)_, the timer reset, and will wait another `time` milliseconds before the new call is made _(and so on...)_
1484
+ *
1485
+ * _Available as `asyncDebounce` and `debounce.async`_
1486
+ *
1487
+ * @param callback Callback to debounce
1488
+ * @param time Time in milliseconds to wait before calling the callback _(defaults to `0`; e.g., as soon as possible)_
1489
+ * @returns Debounced callback handler with a `cancel` method
1422
1490
  */
1423
- function ok(value) {
1424
- return {
1425
- ok: true,
1426
- value
1427
- };
1491
+ function asyncDebounce(callback, time) {
1492
+ return getAsyncTimer(TIMER_DEBOUNCE, callback, time);
1428
1493
  }
1429
1494
  /**
1430
- * Converts a _Result_ to a _Promise_
1495
+ * Throttle a function, ensuring it is only called once every `time` milliseconds
1431
1496
  *
1432
- * Resolves if ok, rejects for error
1497
+ * - When called, successful _(finished)_ results will resolve and errors will reject
1498
+ * - On subsequent calls, existing calls will be canceled _(rejected)_ and will wait until the next valid time to call the callback again _(and so on...)_
1433
1499
  *
1434
- * @param result _Result_ to convert
1435
- * @returns Promised result
1500
+ * _Available as `asyncThrottle` and `throttle.async`_
1501
+ *
1502
+ * @param callback Callback to throttle
1503
+ * @param time Time in milliseconds to wait before calling the callback again _(defaults to `0`; e.g., as soon as possible)_
1504
+ * @returns Throttled callback handler with a `cancel` method
1436
1505
  */
1437
- async function toPromise(result) {
1438
- const actual = typeof result === "function" ? result() : result;
1439
- if (!isResult(actual)) return Promise.reject(new Error(MESSAGE_PROMISE_RESULT));
1440
- return isOk(actual) ? Promise.resolve(actual.value) : Promise.reject(actual.error);
1506
+ function asyncThrottle(callback, time) {
1507
+ return getAsyncTimer(TIMER_THROTTLE, callback, time);
1508
+ }
1509
+ /**
1510
+ * Debounce a function, ensuring it is only called after `time` milliseconds have passed
1511
+ *
1512
+ * On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
1513
+ *
1514
+ * @param callback Callback to debounce
1515
+ * @param time Time in milliseconds to wait before calling the callback _(defaults to `0`; e.g., as soon as possible)_
1516
+ * @returns Debounced callback handler with a `cancel` method
1517
+ */
1518
+ function debounce(callback, time) {
1519
+ return getTimer(TIMER_DEBOUNCE, callback, time);
1520
+ }
1521
+ /**
1522
+ * Throttle a function, ensuring it is only called once every `time` milliseconds
1523
+ *
1524
+ * @param callback Callback to throttle
1525
+ * @param time Time in milliseconds to wait before calling the callback again _(defaults to `0`; e.g., as soon as possible)_
1526
+ * @returns Throttled callback handler with a `cancel` method
1527
+ */
1528
+ function throttle(callback, time) {
1529
+ return getTimer(TIMER_THROTTLE, callback, time);
1530
+ }
1531
+ Object.defineProperty(debounce, "async", { value: asyncDebounce });
1532
+ Object.defineProperty(throttle, "async", { value: asyncThrottle });
1533
+ //#endregion
1534
+ //#region src/internal/result/misc.ts
1535
+ function error(value, original) {
1536
+ return getError(value, original);
1537
+ }
1538
+ function getError(value, original) {
1539
+ const errorResult = {
1540
+ error: value,
1541
+ ok: false
1542
+ };
1543
+ if (original instanceof Error) errorResult.original = original;
1544
+ return errorResult;
1545
+ }
1546
+ function isError(value, extended) {
1547
+ return isResultValue(value, false) && (extended === true ? value.original instanceof Error : true);
1548
+ }
1549
+ function isOk(value) {
1550
+ return isResultValue(value, true);
1551
+ }
1552
+ /**
1553
+ * Is the value a _Result_?
1554
+ *
1555
+ * @param value Value to check
1556
+ * @returns `true` if the value is a _Result_, otherwise `false`
1557
+ */
1558
+ function isResult(value) {
1559
+ return isResultValue(value, true) || isResultValue(value, false);
1560
+ }
1561
+ function isResultValue(value, okValue) {
1562
+ if (isNonPlainObject(value)) return false;
1563
+ return value.ok === okValue && (okValue ? RESULT_PROPERTY_VALUE : RESULT_PROPERTY_ERROR) in value;
1564
+ }
1565
+ /**
1566
+ * Creates an ok result
1567
+ *
1568
+ * @param value Value
1569
+ * @returns Ok result
1570
+ */
1571
+ function ok(value) {
1572
+ return {
1573
+ ok: true,
1574
+ value
1575
+ };
1441
1576
  }
1442
1577
  function unwrap(value, defaultValue) {
1443
1578
  return isOk(value) ? value.value : defaultValue;
1444
1579
  }
1445
- const MESSAGE_PROMISE_RESULT = "toPromise expected to receive a Result";
1580
+ const RESULT_PROPERTY_ERROR = "error";
1581
+ const RESULT_PROPERTY_VALUE = "value";
1446
1582
  //#endregion
1447
1583
  //#region src/internal/value/misc.ts
1448
1584
  function findKey(needle, haystack) {
@@ -1451,8 +1587,8 @@ function findKey(needle, haystack) {
1451
1587
  return index > -1 ? keys[index] : needle;
1452
1588
  }
1453
1589
  function getNestedValue(data, path, ignoreCase) {
1454
- if (typeof data !== "object" || data === null) return error(NESTED_MESSAGE_INPUT);
1455
- if (typeof path !== "string" || path.trim().length === 0) return error(NESTED_MESSAGE_PATH);
1590
+ if (typeof data !== "object" || data === null) return error(MISC_NESTED_MESSAGE_INPUT);
1591
+ if (typeof path !== "string" || path.trim().length === 0) return error(MISC_NESTED_MESSAGE_PATH);
1456
1592
  const shouldIgnoreCase = ignoreCase === true;
1457
1593
  const paths = getPaths(path, shouldIgnoreCase);
1458
1594
  if (typeof paths === "string") return handleValue(data, paths, null, true, shouldIgnoreCase);
@@ -1468,25 +1604,25 @@ function getNestedValue(data, path, ignoreCase) {
1468
1604
  }
1469
1605
  function getPaths(path, lowercase) {
1470
1606
  const normalized = lowercase ? path.toLowerCase() : path;
1471
- if (!EXPRESSION_NESTED.test(normalized)) return normalized;
1472
- return normalized.replace(EXPRESSION_BRACKET, ".$1").replace(EXPRESSION_DOTS, "").split(".");
1607
+ if (!MISC_EXPRESSION_NESTED.test(normalized)) return normalized;
1608
+ return normalized.replace(MISC_EXPRESSION_BRACKET, ".$1").replace(MISC_EXPRESSION_DOTS, "").split(".");
1473
1609
  }
1474
1610
  function handleValue(data, path, value, get, ignoreCase) {
1475
1611
  if (typeof data === "object" && data !== null) {
1476
- if (ignoreKey(path)) return error(NESTED_MESSAGE_UNSAFE);
1612
+ if (ignoreKey(path)) return error(MISC_NESTED_MESSAGE_UNSAFE);
1477
1613
  const key = ignoreCase ? findKey(path, data) : path;
1478
- if (get) return key in data ? ok(data[key]) : error(NESTED_MESSAGE_MISSING);
1614
+ if (get) return key in data ? ok(data[key]) : error(MISC_NESTED_MESSAGE_MISSING);
1479
1615
  data[key] = typeof value === "function" ? value(data[key]) : value;
1480
1616
  }
1481
- if (get) return error(NESTED_MESSAGE_MISSING);
1617
+ if (get) return error(MISC_NESTED_MESSAGE_MISSING);
1482
1618
  }
1483
- const EXPRESSION_BRACKET = /\[(\w+)\]/g;
1484
- const EXPRESSION_DOTS = /^\.|\.$/g;
1485
- const EXPRESSION_NESTED = /\.|\[\w+\]/;
1486
- const NESTED_MESSAGE_INPUT = "Expected data to be an object";
1487
- const NESTED_MESSAGE_MISSING = "Expected property to exist in object";
1488
- const NESTED_MESSAGE_PATH = "Expected path to be a string";
1489
- const NESTED_MESSAGE_UNSAFE = "Access to this property is not allowed";
1619
+ const MISC_EXPRESSION_BRACKET = /\[(\w+)\]/g;
1620
+ const MISC_EXPRESSION_DOTS = /^\.|\.$/g;
1621
+ const MISC_EXPRESSION_NESTED = /\.|\[\w+\]/;
1622
+ const MISC_NESTED_MESSAGE_INPUT = "Expected data to be an object";
1623
+ const MISC_NESTED_MESSAGE_MISSING = "Expected property to exist in object";
1624
+ const MISC_NESTED_MESSAGE_PATH = "Expected path to be a string";
1625
+ const MISC_NESTED_MESSAGE_UNSAFE = "Access to this property is not allowed";
1490
1626
  //#endregion
1491
1627
  //#region src/internal/value/has.ts
1492
1628
  function hasValue(data, path, ignoreCase) {
@@ -1497,7 +1633,7 @@ function hasValueResult(data, path, ignoreCase) {
1497
1633
  return getNestedValue(data, path, ignoreCase === true);
1498
1634
  }
1499
1635
  //#endregion
1500
- //#region src/function/assert.ts
1636
+ //#region src/internal/function/assert.ts
1501
1637
  /**
1502
1638
  * Asserts that a condition is true, throwing an error if it is not
1503
1639
  *
@@ -1538,7 +1674,7 @@ function assertCondition(condition, message, error) {
1538
1674
  * @param error Error constructor _(defaults to `Error`)_
1539
1675
  */
1540
1676
  function assertDefined(value, message, error) {
1541
- assert(() => value != null, message ?? MESSAGE_VALUE_DEFINED, error);
1677
+ assert(() => value != null, message ?? ASSERT_MESSAGE_VALUE_DEFINED, error);
1542
1678
  }
1543
1679
  /**
1544
1680
  * Creates an _Asserter_ that asserts a value is an instance of a constructor, throwing an error if it is not
@@ -1589,108 +1725,363 @@ function assertProperty(path, condition, message, error) {
1589
1725
  }, message, error);
1590
1726
  };
1591
1727
  }
1592
- const MESSAGE_VALUE_DEFINED = "Expected value to be defined";
1593
- //#endregion
1594
- //#region src/internal/function/misc.ts
1595
- /**
1596
- * A function that does nothing, which can be useful, I guess…
1597
- */
1598
- function noop() {}
1728
+ const ASSERT_MESSAGE_VALUE_DEFINED = "Expected value to be defined";
1599
1729
  //#endregion
1600
- //#region src/internal/number.ts
1601
- /**
1602
- * Is the number between a minimum and maximum value?
1603
- *
1604
- * @param value Value to check
1605
- * @param minimum Minimum value
1606
- * @param maximum Maximum value
1607
- * @returns `true` if the value is between the minimum and maximum, otherwise `false`
1608
- */
1609
- function between(value, minimum, maximum) {
1610
- if (![
1611
- value,
1612
- minimum,
1613
- maximum
1614
- ].every(isNumber)) return false;
1615
- if (Object.is(minimum, maximum)) return Object.is(value, minimum);
1616
- return value >= (maximum > minimum ? minimum : maximum) && value <= (maximum > minimum ? maximum : minimum);
1617
- }
1730
+ //#region src/function/once.ts
1618
1731
  /**
1619
- * Clamp a number between a minimum and maximum value
1732
+ * Create an asynchronous function that can only be called once, rejecting or resolving the same result on subsequent calls
1620
1733
  *
1621
- * @param value Value to clamp
1622
- * @param minimum Minimum value
1623
- * @param maximum Maximum value
1624
- * @param loop If `true`, the value will loop around when smaller than the minimum or larger than the maximum _(defaults to `false`)_
1625
- * @returns Clamped value
1734
+ * _Available as `asyncOnce` and `once.async`_
1626
1735
  *
1627
- * @example
1628
- * ```typescript
1629
- * clamp(10, 0, 5); // => 5
1630
- * clamp(10, 0, 5, true); // => 0
1631
- * ```
1736
+ * @param callback Callback to use once
1737
+ * @returns _Once_ callback
1632
1738
  */
1633
- function clamp(value, minimum, maximum, loop) {
1634
- if (![
1635
- value,
1636
- minimum,
1637
- maximum
1638
- ].every(isNumber)) return NaN;
1639
- if (value < minimum) return loop === true ? maximum : minimum;
1640
- return value > maximum ? loop === true ? minimum : maximum : value;
1739
+ function asyncOnce(callback) {
1740
+ assert(() => typeof callback === "function", ONCE_MESSAGE_EXPECTATION);
1741
+ const state = {
1742
+ called: false,
1743
+ cleared: false,
1744
+ error: false,
1745
+ finished: false,
1746
+ items: [],
1747
+ value: void 0
1748
+ };
1749
+ const fn = (...parameters) => {
1750
+ if (state.cleared) return Promise.reject(new Error(ONCE_MESSAGE_CLEARED));
1751
+ if (state.finished) return state.error ? Promise.reject(state.value) : Promise.resolve(state.value);
1752
+ if (state.called) return new Promise((resolve, reject) => {
1753
+ state.items.push({
1754
+ reject,
1755
+ resolve
1756
+ });
1757
+ });
1758
+ state.called = true;
1759
+ return new Promise((resolve, reject) => {
1760
+ state.items.push({
1761
+ reject,
1762
+ resolve
1763
+ });
1764
+ callback(...parameters).then((value) => {
1765
+ handleOnceResult(state, value, false);
1766
+ }).catch((error) => {
1767
+ handleOnceResult(state, error, true);
1768
+ });
1769
+ });
1770
+ };
1771
+ Object.defineProperties(fn, {
1772
+ called: {
1773
+ enumerable: true,
1774
+ get: () => state.called
1775
+ },
1776
+ clear: { value: () => clearState(state) },
1777
+ cleared: {
1778
+ enumerable: true,
1779
+ get: () => state.cleared
1780
+ },
1781
+ error: {
1782
+ enumerable: true,
1783
+ get: () => state.error
1784
+ },
1785
+ finished: {
1786
+ enumerable: true,
1787
+ get: () => state.finished
1788
+ }
1789
+ });
1790
+ return fn;
1791
+ }
1792
+ function clearState(state) {
1793
+ if (!state.called || state.cleared) return;
1794
+ state.cleared = true;
1795
+ state.value = void 0;
1796
+ }
1797
+ function handleOnceResult(state, value, error) {
1798
+ state.error = error;
1799
+ state.finished = true;
1800
+ state.value = value;
1801
+ const items = state.items.splice(0);
1802
+ const { length } = items;
1803
+ for (let index = 0; index < length; index += 1) {
1804
+ const { reject, resolve } = items[index];
1805
+ if (error) reject(value);
1806
+ else resolve(value);
1807
+ }
1641
1808
  }
1642
1809
  /**
1643
- * Get the number value from an unknown value
1644
- *
1645
- * _(Based on Lodash)_
1810
+ * Create a function that can only be called once, returning the same value on subsequent calls
1646
1811
  *
1647
- * @param value Original value
1648
- * @returns Original value as a number, or `Number.NaN` if the value is unable to be parsed
1812
+ * @param callback Callback to use once
1813
+ * @returns _Once_ callback
1649
1814
  */
1650
- function getNumber(value) {
1651
- if (typeof value === "number") return value;
1652
- if (typeof value === "bigint" || typeof value === "boolean") return Number(value);
1653
- if (value == null || typeof value === "symbol") return NaN;
1654
- if (typeof value === "function") return getNumber(value());
1655
- let parsed = value.valueOf();
1656
- if (typeof parsed === "object") parsed = parsed.toString();
1657
- if (typeof parsed !== "string") return getNumber(parsed);
1658
- const trimmed = parsed.trim();
1659
- if (trimmed.length === 0) return NaN;
1660
- if (EXPRESSION_ZEROISH.test(parsed)) return 0;
1661
- const isBinary = EXPRESSION_BINARY.test(trimmed);
1662
- if (isBinary || EXPRESSION_OCTAL.test(trimmed)) return Number.parseInt(trimmed.slice(2), isBinary ? 2 : OCTAL_VALUE);
1663
- return Number(trimmed);
1664
- }
1665
- function getNumberOrDefault(value, defaultValue, minimum) {
1666
- return typeof value === "number" && !Number.isNaN(value) && value >= (minimum ?? 0) ? Math.floor(value) : defaultValue;
1667
- }
1668
- const EXPRESSION_BINARY = /^0b[01]+$/i;
1669
- const EXPRESSION_OCTAL = /^0o[0-7]+$/i;
1670
- const EXPRESSION_ZEROISH = /^\s*0+\s*$/;
1671
- const OCTAL_VALUE = 8;
1672
- //#endregion
1673
- //#region src/internal/sized.ts
1674
- function getSizedMaximum(first, second) {
1675
- let actual;
1676
- if (typeof first === "number") actual = first;
1677
- else actual = typeof second === "number" ? second : MAXIMUM_DEFAULT;
1678
- return clamp(actual, 1, MAXIMUM_ABSOLUTE);
1815
+ function once(callback) {
1816
+ assert(() => typeof callback === "function", ONCE_MESSAGE_EXPECTATION);
1817
+ const state = {
1818
+ called: false,
1819
+ cleared: false,
1820
+ value: void 0
1821
+ };
1822
+ const fn = (...parameters) => {
1823
+ if (state.cleared) throw new Error(ONCE_MESSAGE_CLEARED);
1824
+ if (state.called) return state.value;
1825
+ state.called = true;
1826
+ state.value = callback(...parameters);
1827
+ return state.value;
1828
+ };
1829
+ Object.defineProperties(fn, {
1830
+ called: {
1831
+ enumerable: true,
1832
+ get: () => state.called
1833
+ },
1834
+ clear: { value: () => clearState(state) },
1835
+ cleared: {
1836
+ enumerable: true,
1837
+ get: () => state.cleared
1838
+ }
1839
+ });
1840
+ return fn;
1679
1841
  }
1680
- const MAXIMUM_ABSOLUTE = 16777216;
1681
- const MAXIMUM_DEFAULT = 1048576;
1842
+ const ONCE_MESSAGE_CLEARED = "Once has been cleared";
1843
+ const ONCE_MESSAGE_EXPECTATION = "Once expected a function";
1844
+ Object.defineProperty(once, "async", { value: asyncOnce });
1682
1845
  //#endregion
1683
- //#region src/sized/map.ts
1846
+ //#region src/function/retry.ts
1684
1847
  /**
1685
- * A _Map_ with a maximum size
1686
- *
1687
- * Behavior is similar to a _LRU_ cache, where the least recently used entries are removed
1848
+ * An error thrown when a retry fails
1688
1849
  */
1689
- var SizedMap = class extends Map {
1690
- /**
1691
- * The maximum size of the _Map_
1692
- */
1693
- #maximumSize;
1850
+ var RetryError = class extends Error {
1851
+ original;
1852
+ constructor(message, original) {
1853
+ super(message);
1854
+ this.original = original;
1855
+ this.name = RETRY_ERROR_NAME;
1856
+ }
1857
+ };
1858
+ /**
1859
+ * Retry a callback a specified number of times, with a delay between attempts
1860
+ *
1861
+ * _Available as `asyncRetry` and `retry.async`_
1862
+ *
1863
+ * @param callback Callback to retry
1864
+ * @param options Retry options
1865
+ * @returns Callback result
1866
+ */
1867
+ async function asyncRetry(callback, options) {
1868
+ if (typeof callback !== "function") throw new TypeError(RETRY_MESSAGE_EXPECTATION);
1869
+ async function handle() {
1870
+ try {
1871
+ const result = await callback();
1872
+ resolver(result);
1873
+ } catch (error) {
1874
+ if (attempts >= times || !when(error)) rejector(new RetryError(RETRY_MESSAGE_FAILED, error));
1875
+ else {
1876
+ attempts += 1;
1877
+ timer();
1878
+ }
1879
+ }
1880
+ }
1881
+ const { delay, times, when } = getRetryOptions(options);
1882
+ const timer = getTimer(TIMER_WAIT, handle, delay);
1883
+ let attempts = 0;
1884
+ let rejector;
1885
+ let resolver;
1886
+ return new Promise((resolve, reject) => {
1887
+ rejector = reject;
1888
+ resolver = resolve;
1889
+ handle();
1890
+ });
1891
+ }
1892
+ function getRetryNumber(value) {
1893
+ return typeof value === "number" && value > 0 ? value : 0;
1894
+ }
1895
+ function getRetryOptions(input) {
1896
+ const options = isPlainObject(input) ? input : {};
1897
+ return {
1898
+ delay: getRetryNumber(options.delay),
1899
+ times: getRetryNumber(options.times),
1900
+ when: typeof options.when === "function" ? options.when : shouldRetry
1901
+ };
1902
+ }
1903
+ /**
1904
+ * Retry a callback a specified number of times
1905
+ *
1906
+ * @param callback Callback to retry
1907
+ * @param options Retry options
1908
+ * @returns Callback result
1909
+ */
1910
+ function retry(callback, options) {
1911
+ if (typeof callback !== "function") throw new TypeError(RETRY_MESSAGE_EXPECTATION);
1912
+ const { times, when } = getRetryOptions(options);
1913
+ let last;
1914
+ for (let index = 0; index <= times; index += 1) try {
1915
+ return callback();
1916
+ } catch (error) {
1917
+ if (index >= times || !when(error)) {
1918
+ last = error;
1919
+ break;
1920
+ }
1921
+ }
1922
+ throw new RetryError(RETRY_MESSAGE_FAILED, last);
1923
+ }
1924
+ function shouldRetry() {
1925
+ return true;
1926
+ }
1927
+ const RETRY_ERROR_NAME = "RetryError";
1928
+ const RETRY_MESSAGE_EXPECTATION = "Retry expected a function";
1929
+ const RETRY_MESSAGE_FAILED = "Retry failed";
1930
+ Object.defineProperty(retry, "async", { value: asyncRetry });
1931
+ //#endregion
1932
+ //#region src/internal/function/work.ts
1933
+ function asyncFlow(...fns) {
1934
+ assertFlowFunctions(fns);
1935
+ return (...args) => asyncWork(args.map((value) => {
1936
+ if (isError(value)) throw value.error;
1937
+ return isOk(value) ? value.value : value;
1938
+ }), fns, true);
1939
+ }
1940
+ function flow(...fns) {
1941
+ assertFlowFunctions(fns);
1942
+ return (...args) => work(args.map((value) => {
1943
+ if (isError(value)) throw value.error;
1944
+ return isOk(value) ? value.value : value;
1945
+ }), fns, true);
1946
+ }
1947
+ async function asyncPipe(value, ...pipes) {
1948
+ assertPipeFunctions(pipes);
1949
+ return asyncWork(value, pipes, false);
1950
+ }
1951
+ function pipe(value, ...pipes) {
1952
+ assertPipeFunctions(pipes);
1953
+ return work(value, pipes, false);
1954
+ }
1955
+ async function asyncWork(initial, functions, flow) {
1956
+ const { length } = functions;
1957
+ let transformed = unwrapValue(initial);
1958
+ for (let index = 0; index < length; index += 1) {
1959
+ const fn = functions[index];
1960
+ transformed = unwrapValue(flow && index === 0 && Array.isArray(initial) ? await fn(...initial) : await fn(transformed));
1961
+ }
1962
+ return transformed;
1963
+ }
1964
+ function unwrapValue(value, flow, nested) {
1965
+ if (typeof value === "function") {
1966
+ if (nested != null) throw new TypeError(WORK_MESSAGE_NESTING);
1967
+ return unwrapValue(value(), flow, true);
1968
+ }
1969
+ if (flow != null && value instanceof Promise) throw new TypeError(flow ? WORK_MESSAGE_FLOW_PROMISE : WORK_MESSAGE_PIPE_PROMISE);
1970
+ if (isError(value)) throw value.error;
1971
+ return isOk(value) ? value.value : value;
1972
+ }
1973
+ function work(initial, functions, flow) {
1974
+ const { length } = functions;
1975
+ let transformed = unwrapValue(initial, flow);
1976
+ for (let index = 0; index < length; index += 1) {
1977
+ const fn = functions[index];
1978
+ transformed = unwrapValue(flow && index === 0 && Array.isArray(initial) ? fn(...initial) : fn(transformed), flow);
1979
+ }
1980
+ return transformed;
1981
+ }
1982
+ const WORK_MESSAGE_FLOW_ARRAY = "Flow expected to receive an array of functions";
1983
+ const WORK_MESSAGE_FLOW_PROMISE = "Synchronous Flow received a promise. Use `flow.async` instead.";
1984
+ const WORK_MESSAGE_NESTING = "Return values are too deeply nested.";
1985
+ const WORK_MESSAGE_PIPE_ARRAY = "Pipe expected to receive an array of functions";
1986
+ const WORK_MESSAGE_PIPE_PROMISE = "Synchronous Pipe received a promise. Use `pipe.async` instead.";
1987
+ const assertFlowFunctions = assert.condition((value) => Array.isArray(value) && value.every((item) => typeof item === "function"), WORK_MESSAGE_FLOW_ARRAY, TypeError);
1988
+ const assertPipeFunctions = assert.condition((value) => Array.isArray(value) && value.every((item) => typeof item === "function"), WORK_MESSAGE_PIPE_ARRAY, TypeError);
1989
+ flow.async = asyncFlow;
1990
+ pipe.async = asyncPipe;
1991
+ Object.defineProperty(flow, "async", { value: asyncFlow });
1992
+ Object.defineProperty(pipe, "async", { value: asyncPipe });
1993
+ //#endregion
1994
+ //#region src/internal/number.ts
1995
+ /**
1996
+ * Is the number between a minimum and maximum value?
1997
+ *
1998
+ * @param value Value to check
1999
+ * @param minimum Minimum value
2000
+ * @param maximum Maximum value
2001
+ * @returns `true` if the value is between the minimum and maximum, otherwise `false`
2002
+ */
2003
+ function between(value, minimum, maximum) {
2004
+ if (![
2005
+ value,
2006
+ minimum,
2007
+ maximum
2008
+ ].every(isNumber)) return false;
2009
+ if (Object.is(minimum, maximum)) return Object.is(value, minimum);
2010
+ return value >= (maximum > minimum ? minimum : maximum) && value <= (maximum > minimum ? maximum : minimum);
2011
+ }
2012
+ /**
2013
+ * Clamp a number between a minimum and maximum value
2014
+ *
2015
+ * @param value Value to clamp
2016
+ * @param minimum Minimum value
2017
+ * @param maximum Maximum value
2018
+ * @param loop If `true`, the value will loop around when smaller than the minimum or larger than the maximum _(defaults to `false`)_
2019
+ * @returns Clamped value
2020
+ *
2021
+ * @example
2022
+ * ```typescript
2023
+ * clamp(10, 0, 5); // => 5
2024
+ * clamp(10, 0, 5, true); // => 0
2025
+ * ```
2026
+ */
2027
+ function clamp(value, minimum, maximum, loop) {
2028
+ if (![
2029
+ value,
2030
+ minimum,
2031
+ maximum
2032
+ ].every(isNumber)) return NaN;
2033
+ if (value < minimum) return loop === true ? maximum : minimum;
2034
+ return value > maximum ? loop === true ? minimum : maximum : value;
2035
+ }
2036
+ /**
2037
+ * Get the number value from an unknown value
2038
+ *
2039
+ * _(Based on Lodash)_
2040
+ *
2041
+ * @param value Original value
2042
+ * @returns Original value as a number, or `Number.NaN` if the value is unable to be parsed
2043
+ */
2044
+ function getNumber(value) {
2045
+ if (typeof value === "number") return value;
2046
+ if (typeof value === "bigint" || typeof value === "boolean") return Number(value);
2047
+ if (value == null || typeof value === "symbol") return NaN;
2048
+ if (typeof value === "function") return getNumber(value());
2049
+ let parsed = value.valueOf();
2050
+ if (typeof parsed === "object") parsed = parsed.toString();
2051
+ if (typeof parsed !== "string") return getNumber(parsed);
2052
+ const trimmed = parsed.trim();
2053
+ if (trimmed.length === 0) return NaN;
2054
+ if (NUMBER_EXPRESSION_ZEROISH.test(parsed)) return 0;
2055
+ const isBinary = NUMBER_EXPRESSION_BINARY.test(trimmed);
2056
+ if (isBinary || NUMBER_EXPRESSION_OCTAL.test(trimmed)) return Number.parseInt(trimmed.slice(2), isBinary ? 2 : NUMBER_OCTAL_VALUE);
2057
+ return Number(trimmed);
2058
+ }
2059
+ const NUMBER_EXPRESSION_BINARY = /^0b[01]+$/i;
2060
+ const NUMBER_EXPRESSION_OCTAL = /^0o[0-7]+$/i;
2061
+ const NUMBER_EXPRESSION_ZEROISH = /^\s*0+\s*$/;
2062
+ const NUMBER_OCTAL_VALUE = 8;
2063
+ //#endregion
2064
+ //#region src/internal/sized/misc.ts
2065
+ function getSizedMaximum(first, second) {
2066
+ let actual;
2067
+ if (typeof first === "number") actual = first;
2068
+ else actual = typeof second === "number" ? second : SIZED_MAXIMUM_DEFAULT;
2069
+ return clamp(actual, 1, SIZED_MAXIMUM_ABSOLUTE);
2070
+ }
2071
+ const SIZED_MAXIMUM_ABSOLUTE = 16777216;
2072
+ const SIZED_MAXIMUM_DEFAULT = 1048576;
2073
+ //#endregion
2074
+ //#region src/internal/sized/map.ts
2075
+ /**
2076
+ * A _Map_ with a maximum size
2077
+ *
2078
+ * Behavior is similar to a _LRU_ cache, where the least recently used entries are removed
2079
+ */
2080
+ var SizedMap = class extends Map {
2081
+ /**
2082
+ * The maximum size of the _Map_
2083
+ */
2084
+ #maximumSize;
1694
2085
  /**
1695
2086
  * Is the _Map_ full?
1696
2087
  */
@@ -1734,12 +2125,12 @@ var SizedMap = class extends Map {
1734
2125
  }
1735
2126
  };
1736
2127
  //#endregion
1737
- //#region src/function/memoize.ts
2128
+ //#region src/internal/function/memoize.ts
1738
2129
  function getMemoizationOptions(input) {
1739
2130
  const { cacheKey, cacheSize } = isPlainObject(input) ? input : {};
1740
2131
  return {
1741
2132
  cacheKey: typeof cacheKey === "function" ? cacheKey : void 0,
1742
- cacheSize: typeof cacheSize === "number" && cacheSize > 0 ? cacheSize : DEFAULT_CACHE_SIZE
2133
+ cacheSize: typeof cacheSize === "number" && cacheSize > 0 ? cacheSize : MEMOIZED_CACHE_SIZE_DEFAULT
1743
2134
  };
1744
2135
  }
1745
2136
  /**
@@ -1750,818 +2141,326 @@ function getMemoizationOptions(input) {
1750
2141
  * @returns _Memoized_ instance
1751
2142
  */
1752
2143
  function memoize(callback, options) {
1753
- if (typeof callback !== "function") throw new TypeError(MEMOIZED_ERROR_CALLBACK);
1754
- const state = { options: getMemoizationOptions(options) };
2144
+ if (typeof callback !== "function") throw new TypeError(MEMOIZED_CALLBACK);
2145
+ const state = {
2146
+ cache: void 0,
2147
+ getter: void 0,
2148
+ options: getMemoizationOptions(options)
2149
+ };
1755
2150
  state.cache = new SizedMap(state.options.cacheSize);
1756
2151
  state.getter = (...parameters) => {
1757
- const key = state.options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join(parameters.map(getString), SEPARATOR));
2152
+ const key = state.options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join(parameters.map(getString), MEMOIZED_KEY_SEPARATOR));
1758
2153
  if (state.cache.has(key)) return state.cache.get(key);
1759
2154
  const value = callback(...parameters);
1760
- state.cache?.set(key, value);
2155
+ state.cache.set(key, value);
1761
2156
  return value;
1762
2157
  };
1763
2158
  const instance = {
1764
- clear: () => {
1765
- state.cache?.clear();
1766
- },
1767
- delete: (key) => {
1768
- return state.cache?.delete(key) ?? false;
1769
- },
1770
- destroy: () => {
1771
- state.cache?.clear();
1772
- state.cache = void 0;
1773
- state.getter = void 0;
1774
- },
1775
- get: (key) => {
1776
- return state.cache?.get(key);
1777
- },
1778
- has: (key) => {
1779
- return state.cache?.has(key) ?? false;
1780
- },
1781
- run: (...parameters) => {
1782
- if (state.cache == null || state.getter == null) throw new Error(MEMOIZED_ERROR_DESTROYED);
1783
- return state.getter(...parameters);
1784
- }
2159
+ clear: () => state.cache.clear(),
2160
+ delete: (key) => state.cache.delete(key),
2161
+ get: (key) => state.cache.get(key),
2162
+ has: (key) => state.cache.has(key),
2163
+ run: (...parameters) => state.getter(...parameters)
1785
2164
  };
1786
2165
  Object.defineProperties(instance, {
1787
2166
  maximum: {
1788
2167
  enumerable: true,
1789
- get: () => state.cache?.maximum ?? NaN
2168
+ get: () => state.cache.maximum
1790
2169
  },
1791
2170
  size: {
1792
2171
  enumerable: true,
1793
- get: () => state.cache?.size ?? NaN
2172
+ get: () => state.cache.size
1794
2173
  }
1795
2174
  });
1796
2175
  return Object.freeze(instance);
1797
2176
  }
1798
- const DEFAULT_CACHE_SIZE = 1024;
1799
- const MEMOIZED_ERROR_CALLBACK = "Memoized requires a callback function";
1800
- const MEMOIZED_ERROR_DESTROYED = "The Memoized instance has been destroyed";
1801
- const SEPARATOR = "_";
2177
+ const MEMOIZED_CACHE_SIZE_DEFAULT = 1024;
2178
+ const MEMOIZED_CALLBACK = "Memoized requires a callback function";
2179
+ const MEMOIZED_KEY_SEPARATOR = "_";
1802
2180
  //#endregion
1803
- //#region src/internal/function/timer.ts
1804
- function getAsyncTimer(type, callback, time) {
1805
- async function run(item) {
1806
- const now = performance.now();
1807
- start ??= now;
1808
- if (interval === 0 || now - start >= interval - OFFSET) {
1809
- start = throttle ? now : void 0;
1810
- item.running = true;
1811
- try {
1812
- let result = callback(...item.parameters);
1813
- if (result instanceof Promise) result = await result;
1814
- item.resolve(result);
1815
- } catch (error) {
1816
- item.reject(error);
1817
- } finally {
1818
- item.running = false;
1819
- }
1820
- } else id = startTimer(() => run(item));
1821
- }
1822
- const interval = getInterval(time);
1823
- const throttle = type === TIMER_THROTTLE;
1824
- let id;
1825
- let last;
1826
- let start;
1827
- const timer = (...parameters) => {
1828
- timer.cancel();
1829
- const next = {
1830
- parameters,
1831
- running: false
1832
- };
1833
- next.promise = new Promise((resolve, reject) => {
1834
- next.reject = reject;
1835
- next.resolve = resolve;
1836
- });
1837
- last = next;
1838
- if (throttle) run(next);
1839
- else id = startTimer(() => {
1840
- run(next);
1841
- });
1842
- return next.promise;
1843
- };
1844
- timer.cancel = () => {
1845
- clearTimer(id);
1846
- if (last != null && !last.running) last.reject();
1847
- };
1848
- return timer;
1849
- }
1850
- function getInterval(value) {
1851
- return typeof value === "number" && value > 0 ? value : 0;
1852
- }
1853
- function getTimer(type, callback, time) {
1854
- function run() {
1855
- const now = performance.now();
1856
- start ??= now;
1857
- if (interval === 0 || now - start >= interval - OFFSET) {
1858
- start = throttle ? now : void 0;
1859
- callback(...args);
1860
- } else id = startTimer(run);
1861
- }
1862
- const interval = getInterval(time);
1863
- const throttle = type === TIMER_THROTTLE;
1864
- let args;
1865
- let id;
1866
- let start;
1867
- const timer = (...parameters) => {
1868
- timer.cancel();
1869
- args = parameters;
1870
- if (throttle) run();
1871
- else id = startTimer(run);
1872
- };
1873
- timer.cancel = () => {
1874
- clearTimer(id);
1875
- };
1876
- return timer;
1877
- }
1878
- const OFFSET = 5;
1879
- const TIMER_DEBOUNCE = "debounce";
1880
- const TIMER_THROTTLE = "throttle";
1881
- const TIMER_WAIT = "wait";
1882
- // istanbul ignore next
1883
- const clearTimer = typeof cancelAnimationFrame === "function" ? cancelAnimationFrame : clearTimeout;
1884
- // istanbul ignore next
1885
- const startTimer = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout;
1886
- //#endregion
1887
- //#region src/function/limit.ts
2181
+ //#region src/internal/string/case.ts
1888
2182
  /**
1889
- * Debounce a function, ensuring it is only called after `time` milliseconds have passed
1890
- *
1891
- * - When called, successful _(finished)_ results will resolve and errors will reject
1892
- * - On subsequent calls, existing calls will be canceled _(rejected)_, the timer reset, and will wait another `time` milliseconds before the new call is made _(and so on...)_
1893
- *
1894
- * _Available as `asyncDebounce` and `debounce.async`_
2183
+ * Convert a string to camel case _(thisIsCamelCase)_
1895
2184
  *
1896
- * @param callback Callback to debounce
1897
- * @param time Time in milliseconds to wait before calling the callback _(defaults to `0`; e.g., as soon as possible)_
1898
- * @returns Debounced callback handler with a `cancel` method
2185
+ * @param value String to convert
2186
+ * @returns Camel-cased string
1899
2187
  */
1900
- function asyncDebounce(callback, time) {
1901
- return getAsyncTimer(TIMER_DEBOUNCE, callback, time);
2188
+ function camelCase(value) {
2189
+ return toCase(STRING_CASE_CAMEL, value, true, false);
1902
2190
  }
1903
2191
  /**
1904
- * Throttle a function, ensuring it is only called once every `time` milliseconds
1905
- *
1906
- * - When called, successful _(finished)_ results will resolve and errors will reject
1907
- * - On subsequent calls, existing calls will be canceled _(rejected)_ and will wait until the next valid time to call the callback again _(and so on...)_
1908
- *
1909
- * _Available as `asyncThrottle` and `throttle.async`_
2192
+ * Capitalize the first letter of a string _(and lowercase the rest)_
1910
2193
  *
1911
- * @param callback Callback to throttle
1912
- * @param time Time in milliseconds to wait before calling the callback again _(defaults to `0`; e.g., as soon as possible)_
1913
- * @returns Throttled callback handler with a `cancel` method
2194
+ * @param value String to capitalize
2195
+ * @returns Capitalized string
1914
2196
  */
1915
- function asyncThrottle(callback, time) {
1916
- return getAsyncTimer(TIMER_THROTTLE, callback, time);
2197
+ function capitalize(value) {
2198
+ if (typeof value !== "string" || value.length === 0) return "";
2199
+ memoizedCapitalize ??= memoize((v) => v.length === 1 ? v.toLocaleUpperCase() : `${v.charAt(0).toLocaleUpperCase()}${v.slice(1).toLocaleLowerCase()}`);
2200
+ return memoizedCapitalize.run(value);
1917
2201
  }
1918
2202
  /**
1919
- * Debounce a function, ensuring it is only called after `time` milliseconds have passed
1920
- *
1921
- * On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
2203
+ * Convert a string to kebab case _(this-is-kebab-case)_
1922
2204
  *
1923
- * @param callback Callback to debounce
1924
- * @param time Time in milliseconds to wait before calling the callback _(defaults to `0`; e.g., as soon as possible)_
1925
- * @returns Debounced callback handler with a `cancel` method
2205
+ * @param value String to convert
2206
+ * @returns Kebab-cased string
1926
2207
  */
1927
- function debounce(callback, time) {
1928
- return getTimer(TIMER_DEBOUNCE, callback, time);
2208
+ function kebabCase(value) {
2209
+ return toCase(STRING_CASE_KEBAB, value, false, false);
1929
2210
  }
1930
- debounce.async = asyncDebounce;
1931
2211
  /**
1932
- * Throttle a function, ensuring it is only called once every `time` milliseconds
2212
+ * Convert a string to lower case
1933
2213
  *
1934
- * @param callback Callback to throttle
1935
- * @param time Time in milliseconds to wait before calling the callback again _(defaults to `0`; e.g., as soon as possible)_
1936
- * @returns Throttled callback handler with a `cancel` method
2214
+ * @param value String to convert
2215
+ * @returns Lower-cased string
1937
2216
  */
1938
- function throttle(callback, time) {
1939
- return getTimer(TIMER_THROTTLE, callback, time);
2217
+ function lowerCase(value) {
2218
+ if (typeof value !== "string") return "";
2219
+ memoizedLowerCase ??= memoize((v) => v.toLocaleLowerCase());
2220
+ return memoizedLowerCase.run(value);
1940
2221
  }
1941
- throttle.async = asyncThrottle;
1942
- //#endregion
1943
- //#region src/function/once.ts
1944
2222
  /**
1945
- * Create an asynchronous function that can only be called once, rejecting or resolving the same result on subsequent calls
1946
- *
1947
- * _Available as `asyncOnce` and `once.async`_
2223
+ * Convert a string to pascal case _(ThisIsPascalCase)_
1948
2224
  *
1949
- * @param callback Callback to use once
1950
- * @returns _Once_ callback
2225
+ * @param value String to convert
2226
+ * @returns Pascal-cased string
1951
2227
  */
1952
- function asyncOnce(callback) {
1953
- assert(() => typeof callback === "function", ONCE_MESSAGE_EXPECTATION);
1954
- const state = {
1955
- called: false,
1956
- cleared: false,
1957
- error: false,
1958
- finished: false,
1959
- items: [],
1960
- value: void 0
1961
- };
1962
- const fn = (...parameters) => {
1963
- if (state.cleared) return Promise.reject(new Error(ONCE_MESSAGE_CLEARED));
1964
- if (state.finished) return state.error ? Promise.reject(state.value) : Promise.resolve(state.value);
1965
- if (state.called) return new Promise((resolve, reject) => {
1966
- state.items.push({
1967
- reject,
1968
- resolve
1969
- });
1970
- });
1971
- state.called = true;
1972
- return new Promise((resolve, reject) => {
1973
- state.items.push({
1974
- reject,
1975
- resolve
1976
- });
1977
- callback(...parameters).then((value) => {
1978
- handleOnceResult(state, value, false);
1979
- }).catch((error) => {
1980
- handleOnceResult(state, error, true);
1981
- });
1982
- });
1983
- };
1984
- Object.defineProperties(fn, {
1985
- called: {
1986
- enumerable: true,
1987
- get: () => state.called
1988
- },
1989
- cleared: {
1990
- enumerable: true,
1991
- get: () => state.cleared
1992
- },
1993
- error: {
1994
- enumerable: true,
1995
- get: () => state.error
1996
- },
1997
- finished: {
1998
- enumerable: true,
1999
- get: () => state.finished
2000
- }
2001
- });
2002
- fn.clear = () => {
2003
- if (!state.called || !state.finished || state.cleared) return;
2004
- state.cleared = true;
2005
- state.value = void 0;
2006
- };
2007
- return fn;
2008
- }
2009
- function handleOnceResult(state, value, error) {
2010
- state.error = error;
2011
- state.finished = true;
2012
- state.value = value;
2013
- const items = state.items.splice(0);
2014
- const { length } = items;
2015
- for (let index = 0; index < length; index += 1) {
2016
- const { reject, resolve } = items[index];
2017
- if (error) reject(value);
2018
- else resolve(value);
2019
- }
2228
+ function pascalCase(value) {
2229
+ return toCase(STRING_CASE_PASCAL, value, true, true);
2020
2230
  }
2021
2231
  /**
2022
- * Create a function that can only be called once, returning the same value on subsequent calls
2232
+ * Convert a string to snake case _(this_is_snake_case)_
2023
2233
  *
2024
- * @param callback Callback to use once
2025
- * @returns _Once_ callback
2234
+ * @param value String to convert
2235
+ * @returns Snake-cased string
2026
2236
  */
2027
- function once(callback) {
2028
- assert(() => typeof callback === "function", ONCE_MESSAGE_EXPECTATION);
2029
- const state = {
2030
- called: false,
2031
- cleared: false,
2032
- value: void 0
2033
- };
2034
- const fn = (...parameters) => {
2035
- if (state.cleared) throw new Error(ONCE_MESSAGE_CLEARED);
2036
- if (state.called) return state.value;
2037
- state.called = true;
2038
- state.value = callback(...parameters);
2039
- return state.value;
2040
- };
2041
- Object.defineProperties(fn, {
2042
- called: { get: () => state.called },
2043
- cleared: { get: () => state.cleared }
2044
- });
2045
- fn.clear = () => {
2046
- if (!state.called || state.cleared) return;
2047
- state.cleared = true;
2048
- state.value = void 0;
2049
- };
2050
- return fn;
2237
+ function snakeCase(value) {
2238
+ return toCase(STRING_CASE_SNAKE, value, false, false);
2051
2239
  }
2052
- once.async = asyncOnce;
2053
- const ONCE_MESSAGE_CLEARED = "Once has been cleared";
2054
- const ONCE_MESSAGE_EXPECTATION = "Once expected a function";
2055
- //#endregion
2056
- //#region src/function/retry.ts
2057
2240
  /**
2058
- * An error thrown when a retry fails
2241
+ * Convert a string to title case _(Capitalizing Every Word)_
2242
+ *
2243
+ * @param value String to convert
2244
+ * @returns Title-cased string
2059
2245
  */
2060
- var RetryError = class extends Error {
2061
- original;
2062
- constructor(message, original) {
2063
- super(message);
2064
- this.original = original;
2065
- this.name = RETRY_ERROR_NAME;
2246
+ function titleCase(value) {
2247
+ if (typeof value !== "string" || value.length === 0) return "";
2248
+ memoizedTitleCase ??= memoize((v) => v.length < 2 ? capitalize(v) : join(words(v).map(capitalize), " "));
2249
+ return memoizedTitleCase.run(value);
2250
+ }
2251
+ function toCase(type, value, capitalizeAny, capitalizeFirst) {
2252
+ caseMemoizers[type] ??= memoize(toCaseCallback.bind({
2253
+ type,
2254
+ capitalizeAny,
2255
+ capitalizeFirst
2256
+ }));
2257
+ return caseMemoizers[type].run(value);
2258
+ }
2259
+ function toCaseCallback(value) {
2260
+ if (typeof value !== "string") return "";
2261
+ if (value.length < 1) return value;
2262
+ const { capitalizeAny, capitalizeFirst, type } = this;
2263
+ const parts = words(value);
2264
+ const partsLength = parts.length;
2265
+ const cased = [];
2266
+ for (let partIndex = 0; partIndex < partsLength; partIndex += 1) {
2267
+ const items = parts[partIndex].replace(STRING_EXPRESSION_ACRONYM, (full, one, two, three) => three === STRING_S ? full : `${one}-${two}${three}`).replace(STRING_EXPRESSION_CAMEL_CASE, STRING_REPLACEMENT_CAMEL_CASE).split("-");
2268
+ const itemsLength = items.length;
2269
+ const partResult = [];
2270
+ let itemCount = 0;
2271
+ for (let itemIndex = 0; itemIndex < itemsLength; itemIndex += 1) {
2272
+ const item = items[itemIndex];
2273
+ if (item.length === 0) continue;
2274
+ if (!capitalizeAny || itemCount === 0 && partIndex === 0 && !capitalizeFirst) partResult.push(item.toLocaleLowerCase());
2275
+ else partResult.push(capitalize(item));
2276
+ itemCount += 1;
2277
+ }
2278
+ cased.push(join(partResult, delimiters[type]));
2066
2279
  }
2067
- };
2280
+ return join(cased, delimiters[type]);
2281
+ }
2068
2282
  /**
2069
- * Retry a callback a specified number of times, with a delay between attempts
2070
- *
2071
- * _Available as `asyncRetry` and `retry.async`_
2283
+ * Convert a string to upper case
2072
2284
  *
2073
- * @param callback Callback to retry
2074
- * @param options Retry options
2075
- * @returns Callback result
2285
+ * @param value String to convert
2286
+ * @returns Upper-cased string
2076
2287
  */
2077
- async function asyncRetry(callback, options) {
2078
- if (typeof callback !== "function") throw new TypeError(RETRY_MESSAGE_EXPECTATION);
2079
- async function handle() {
2080
- try {
2081
- const result = await callback();
2082
- resolver(result);
2083
- } catch (error) {
2084
- if (attempts >= times || !when(error)) rejector(new RetryError(RETRY_MESSAGE_FAILED, error));
2085
- else {
2086
- attempts += 1;
2087
- timer();
2088
- }
2089
- }
2090
- }
2091
- const { delay, times, when } = getRetryOptions(options);
2092
- const timer = getTimer(TIMER_WAIT, handle, delay);
2093
- let attempts = 0;
2094
- let rejector;
2095
- let resolver;
2096
- return new Promise((resolve, reject) => {
2097
- rejector = reject;
2098
- resolver = resolve;
2099
- handle();
2100
- });
2101
- }
2102
- function getRetryNumber(value) {
2103
- return typeof value === "number" && value > 0 ? value : 0;
2104
- }
2105
- function getRetryOptions(input) {
2106
- const options = isPlainObject(input) ? input : {};
2107
- return {
2108
- delay: getRetryNumber(options.delay),
2109
- times: getRetryNumber(options.times),
2110
- when: typeof options.when === "function" ? options.when : shouldRetry
2111
- };
2288
+ function upperCase(value) {
2289
+ if (typeof value !== "string" || value.length === 0) return "";
2290
+ memoizedUpperCase ??= memoize((v) => v.toLocaleUpperCase());
2291
+ return memoizedUpperCase.run(value);
2112
2292
  }
2293
+ const STRING_CASE_CAMEL = "camel";
2294
+ const STRING_CASE_KEBAB = "kebab";
2295
+ const STRING_CASE_PASCAL = "pascal";
2296
+ const STRING_CASE_SNAKE = "snake";
2297
+ const STRING_DELIMTER_EMPTY = "";
2298
+ const STRING_DELIMITER_HYPHEN = "-";
2299
+ const STRING_DELIMITER_UNDERSCORE = "_";
2300
+ const STRING_EXPRESSION_CAMEL_CASE = /(\p{Ll})(\p{Lu})/gu;
2301
+ const STRING_EXPRESSION_ACRONYM = /(\p{Lu}*)(\p{Lu})(\p{Ll}+)/gu;
2302
+ const STRING_REPLACEMENT_CAMEL_CASE = "$1-$2";
2303
+ const STRING_S = "s";
2304
+ const caseMemoizers = {};
2305
+ const delimiters = {
2306
+ [STRING_CASE_CAMEL]: STRING_DELIMTER_EMPTY,
2307
+ [STRING_CASE_KEBAB]: STRING_DELIMITER_HYPHEN,
2308
+ [STRING_CASE_PASCAL]: STRING_DELIMTER_EMPTY,
2309
+ [STRING_CASE_SNAKE]: STRING_DELIMITER_UNDERSCORE
2310
+ };
2311
+ let memoizedCapitalize;
2312
+ let memoizedLowerCase;
2313
+ let memoizedTitleCase;
2314
+ let memoizedUpperCase;
2315
+ //#endregion
2316
+ //#region src/internal/value/equal.ts
2113
2317
  /**
2114
- * Retry a callback a specified number of times
2318
+ * Deregister a equality comparison handler for a specific class
2115
2319
  *
2116
- * @param callback Callback to retry
2117
- * @param options Retry options
2118
- * @returns Callback result
2320
+ * _Available as `deregisterEqualizer` and `equal.deregister`_
2321
+ *
2322
+ * @param constructor Class constructor
2119
2323
  */
2120
- function retry(callback, options) {
2121
- if (typeof callback !== "function") throw new TypeError(RETRY_MESSAGE_EXPECTATION);
2122
- const { times, when } = getRetryOptions(options);
2123
- let last;
2124
- for (let index = 0; index <= times; index += 1) try {
2125
- return callback();
2126
- } catch (error) {
2127
- if (index >= times || !when(error)) {
2128
- last = error;
2129
- break;
2130
- }
2131
- }
2132
- throw new RetryError(RETRY_MESSAGE_FAILED, last);
2324
+ function deregisterEqualizer(constructor) {
2325
+ equal.handlers.deregister(constructor);
2133
2326
  }
2134
- retry.async = asyncRetry;
2135
- function shouldRetry() {
2327
+ function filterKey(key, options) {
2328
+ if (typeof key !== "string") return true;
2329
+ if (options.ignoreExpressions.enabled && options.ignoreExpressions.values.some((expression) => expression.test(key))) return false;
2330
+ if (options.ignoreKeys.enabled && options.ignoreKeys.values.has(key)) return false;
2136
2331
  return true;
2137
2332
  }
2138
- const RETRY_ERROR_NAME = "RetryError";
2139
- const RETRY_MESSAGE_EXPECTATION = "Retry expected a function";
2140
- const RETRY_MESSAGE_FAILED = "Retry failed";
2141
- //#endregion
2142
- //#region src/function/work.ts
2143
- function asyncFlow(...fns) {
2144
- assertFlowFunctions(fns);
2145
- return (...args) => asyncWork(args.map((value) => {
2146
- if (isError(value)) throw value.error;
2147
- return isOk(value) ? value.value : value;
2148
- }), fns, true);
2333
+ function equal(first, second, options) {
2334
+ return equalValue(first, second, getEqualOptions(options));
2149
2335
  }
2150
- function flow(...fns) {
2151
- assertFlowFunctions(fns);
2152
- return (...args) => work(args.map((value) => {
2153
- if (isError(value)) throw value.error;
2154
- return isOk(value) ? value.value : value;
2155
- }), fns, true);
2336
+ equal.handlers = getCompareHandlers(equal, { callback: Object.is });
2337
+ equal.deregister = deregisterEqualizer;
2338
+ equal.initialize = initializeEqualizer;
2339
+ equal.register = registerEqualizer;
2340
+ function equalArray(first, second, options) {
2341
+ const { length } = first;
2342
+ if (length !== second.length) return false;
2343
+ let offset = 0;
2344
+ if (length >= EQUAL_ARRAY_THRESHOLD) {
2345
+ offset = Math.round(length / EQUAL_ARRAY_PEEK_PERCENTAGE);
2346
+ offset = offset > EQUAL_ARRAY_THRESHOLD ? EQUAL_ARRAY_THRESHOLD : offset;
2347
+ for (let index = 0; index < offset; index += 1) if (!(equalValue(first[index], second[index], options) && equalValue(first[length - index - 1], second[length - index - 1], options))) return false;
2348
+ }
2349
+ const end = length - offset;
2350
+ for (let index = offset; index < end; index += 1) if (!equalValue(first[index], second[index], options)) return false;
2351
+ return true;
2156
2352
  }
2157
- flow.async = asyncFlow;
2158
- async function asyncPipe(value, ...pipes) {
2159
- assertPipeFunctions(pipes);
2160
- return asyncWork(value, pipes, false);
2353
+ function equalArrayBuffer(first, second, options) {
2354
+ return first.byteLength === second.byteLength ? equalArray(new Uint8Array(first), new Uint8Array(second), options) : false;
2161
2355
  }
2162
- function pipe(value, ...pipes) {
2163
- assertPipeFunctions(pipes);
2164
- return work(value, pipes, false);
2356
+ function equalDataView(first, second, options) {
2357
+ return first.byteOffset === second.byteOffset ? equalArrayBuffer(first.buffer, second.buffer, options) : false;
2165
2358
  }
2166
- pipe.async = asyncPipe;
2167
- async function asyncWork(initial, functions, flow) {
2168
- const { length } = functions;
2169
- let transformed = unwrapValue(initial);
2170
- for (let index = 0; index < length; index += 1) {
2171
- const fn = functions[index];
2172
- transformed = unwrapValue(flow && index === 0 && Array.isArray(initial) ? await fn(...initial) : await fn(transformed));
2359
+ function equalMap(first, second, options) {
2360
+ const { size } = first;
2361
+ if (size !== second.size) return false;
2362
+ const firstKeys = [...first.keys()];
2363
+ for (let index = 0; index < size; index += 1) {
2364
+ const key = firstKeys[index];
2365
+ if (!second.has(key) || !equalValue(first.get(key), second.get(key), options)) return false;
2173
2366
  }
2174
- return transformed;
2367
+ return true;
2175
2368
  }
2176
- function unwrapValue(value, flow, nested) {
2177
- if (typeof value === "function") {
2178
- if (nested != null) throw new TypeError(MESSAGE_NESTING);
2179
- return unwrapValue(value(), flow, true);
2369
+ function equalPlainObject(first, second, options) {
2370
+ let firstKeys = [...Object.keys(first), ...Object.getOwnPropertySymbols(first)];
2371
+ let secondKeys = [...Object.keys(second), ...Object.getOwnPropertySymbols(second)];
2372
+ if (options.ignoreKeys.enabled || options.ignoreExpressions.enabled) {
2373
+ firstKeys = firstKeys.filter((key) => filterKey(key, options));
2374
+ secondKeys = secondKeys.filter((key) => filterKey(key, options));
2180
2375
  }
2181
- if (flow != null && value instanceof Promise) throw new TypeError(flow ? MESSAGE_FLOW_PROMISE : MESSAGE_PIPE_PROMISE);
2182
- if (isError(value)) throw value.error;
2183
- return isOk(value) ? value.value : value;
2376
+ const secondSet = secondKeys.length >= EQUAL_MINIMUM_LENGTH_FOR_SET ? new Set(secondKeys) : void 0;
2377
+ const { length } = firstKeys;
2378
+ if (length !== secondKeys.length) return false;
2379
+ for (let index = 0; index < length; index += 1) {
2380
+ const key = firstKeys[index];
2381
+ if (!(secondSet?.has(key) ?? secondKeys.includes(key)) || !equalValue(first[key], second[key], options)) return false;
2382
+ }
2383
+ return true;
2184
2384
  }
2185
- function work(initial, functions, flow) {
2186
- const { length } = functions;
2187
- let transformed = unwrapValue(initial, flow);
2385
+ function equalProperties(first, second, properties, options) {
2386
+ const { length } = properties;
2188
2387
  for (let index = 0; index < length; index += 1) {
2189
- const fn = functions[index];
2190
- transformed = unwrapValue(flow && index === 0 && Array.isArray(initial) ? fn(...initial) : fn(transformed), flow);
2388
+ const property = properties[index];
2389
+ if (!equalValue(first[property], second[property], options)) return false;
2191
2390
  }
2192
- return transformed;
2391
+ return true;
2193
2392
  }
2194
- const MESSAGE_FLOW_ARRAY = "Flow expected to receive an array of functions";
2195
- const MESSAGE_FLOW_PROMISE = "Synchronous Flow received a promise. Use `flow.async` instead.";
2196
- const MESSAGE_NESTING = "Return values are too deeply nested.";
2197
- const MESSAGE_PIPE_ARRAY = "Pipe expected to receive an array of functions";
2198
- const MESSAGE_PIPE_PROMISE = "Synchronous Pipe received a promise. Use `pipe.async` instead.";
2199
- const assertFlowFunctions = assert.condition((value) => Array.isArray(value) && value.every((item) => typeof item === "function"), MESSAGE_FLOW_ARRAY, TypeError);
2200
- const assertPipeFunctions = assert.condition((value) => Array.isArray(value) && value.every((item) => typeof item === "function"), MESSAGE_PIPE_ARRAY, TypeError);
2201
- //#endregion
2202
- //#region src/herald.ts
2203
- function getEvents(herald) {
2204
- const events = {
2205
- subscribe: (event, callback) => herald.subscribe(event, callback),
2206
- unsubscribe: (event, callback) => herald.unsubscribe(event, callback)
2207
- };
2208
- Object.defineProperty(events, KEY_HERALD, {
2209
- enumerable: false,
2210
- value: NAME_EVENTS
2211
- });
2212
- return Object.freeze(events);
2393
+ function equalSet(first, second, options) {
2394
+ const { size } = first;
2395
+ if (size !== second.size) return false;
2396
+ const firstValues = [...first];
2397
+ const secondValues = [...second];
2398
+ for (let index = 0; index < size; index += 1) {
2399
+ const firstValue = firstValues[index];
2400
+ if (isPrimitive(firstValue) ? !second.has(firstValue) : !secondValues.some((secondValue) => equalValue(firstValue, secondValue, options))) return false;
2401
+ }
2402
+ return true;
2213
2403
  }
2214
- /**
2215
- * Create a _Herald_ for announcing named events
2216
- *
2217
- * @param names Event names
2218
- * @returns _Herald_ instance
2219
- */
2220
- function herald(names) {
2221
- if (!Array.isArray(names) || names.length === 0 || !names.every((name) => typeof name === "string")) throw new Error(MESSAGE);
2222
- const set = new Set(names);
2223
- const subscribers = /* @__PURE__ */ new Map();
2224
- const instance = {
2225
- clear() {
2226
- subscribers.clear();
2227
- },
2228
- emit(event, ...parameters) {
2229
- const callbacks = subscribers.get(event);
2230
- if (callbacks == null) return;
2231
- for (const callback of callbacks) callback(...parameters);
2404
+ function equalTypedArray(first, second) {
2405
+ if (first.constructor !== second.constructor) return false;
2406
+ if (first.byteLength !== second.byteLength) return false;
2407
+ const { length } = first;
2408
+ for (let index = 0; index < length; index += 1) if (first[index] !== second[index]) return false;
2409
+ return true;
2410
+ }
2411
+ function equalValue(first, second, options) {
2412
+ if (options.relaxedNullish && first == null && second == null) return true;
2413
+ switch (true) {
2414
+ case Object.is(first, second): return true;
2415
+ case first == null || second == null: return first === second;
2416
+ case typeof first !== typeof second: return false;
2417
+ case typeof first === "string" && options.ignoreCase === true: return Object.is(first.toLocaleLowerCase(), second.toLocaleLowerCase());
2418
+ case first instanceof ArrayBuffer && second instanceof ArrayBuffer: return equalArrayBuffer(first, second, options);
2419
+ case first instanceof Date && second instanceof Date: return Object.is(first.getTime(), second.getTime());
2420
+ case first instanceof DataView && second instanceof DataView: return equalDataView(first, second, options);
2421
+ case first instanceof Error && second instanceof Error: return equalProperties(first, second, EQUAL_ERROR_PROPERTIES, options);
2422
+ case first instanceof Map && second instanceof Map: return equalMap(first, second, options);
2423
+ case first instanceof RegExp && second instanceof RegExp: return equalProperties(first, second, EQUAL_EXPRESSION_PROPERTIES, options);
2424
+ case first instanceof Set && second instanceof Set: return equalSet(first, second, options);
2425
+ case Array.isArray(first) && Array.isArray(second): return equalArray(first, second, options);
2426
+ case isPlainObject(first) && isPlainObject(second): return equalPlainObject(first, second, options);
2427
+ case isTypedArray(first) && isTypedArray(second): return equalTypedArray(first, second);
2428
+ default: return equal.handlers.handle(first, second, options);
2429
+ }
2430
+ }
2431
+ function getEqualOptions(input) {
2432
+ const options = {
2433
+ ignoreCase: false,
2434
+ ignoreExpressions: {
2435
+ enabled: false,
2436
+ values: []
2232
2437
  },
2233
- subscribe(event, callback) {
2234
- if (!set.has(event) || typeof callback !== "function") return noop;
2235
- let eventSubscribers = subscribers.get(event);
2236
- if (eventSubscribers == null) {
2237
- eventSubscribers = /* @__PURE__ */ new Set();
2238
- subscribers.set(event, eventSubscribers);
2239
- }
2240
- eventSubscribers.add(callback);
2241
- return () => {
2242
- eventSubscribers?.delete(callback);
2243
- };
2438
+ ignoreKeys: {
2439
+ enabled: false,
2440
+ values: /* @__PURE__ */ new Set()
2244
2441
  },
2245
- unsubscribe(event, callback) {
2246
- if (!set.has(event) || (callback != null ? typeof callback !== "function" : false)) return;
2247
- const eventSubscribers = subscribers.get(event);
2248
- if (eventSubscribers == null) return;
2249
- if (callback == null) eventSubscribers.clear();
2250
- else eventSubscribers.delete(callback);
2251
- if (callback == null || eventSubscribers.size === 0) subscribers.delete(event);
2252
- }
2442
+ relaxedNullish: false
2253
2443
  };
2254
- Object.defineProperties(instance, {
2255
- [KEY_HERALD]: {
2256
- enumerable: false,
2257
- value: NAME_HERALD
2258
- },
2259
- events: {
2260
- enumerable: true,
2261
- value: getEvents(instance)
2262
- }
2263
- });
2264
- return Object.freeze(instance);
2444
+ if (typeof input === "boolean") {
2445
+ options.ignoreCase = input;
2446
+ return options;
2447
+ }
2448
+ if (isNonPlainObject(input)) return options;
2449
+ options.ignoreCase = typeof input.ignoreCase === "boolean" ? input.ignoreCase : false;
2450
+ options.ignoreExpressions.values = (Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => key instanceof RegExp);
2451
+ options.ignoreKeys.values = new Set((Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => typeof key === "string"));
2452
+ options.ignoreExpressions.enabled = options.ignoreExpressions.values.length > 0;
2453
+ options.ignoreKeys.enabled = options.ignoreKeys.values.size > 0;
2454
+ options.relaxedNullish = input.relaxedNullish === true;
2455
+ return options;
2265
2456
  }
2266
2457
  /**
2267
- * Is the value events for a herald?
2458
+ * Create an equalizer with predefined options
2268
2459
  *
2269
- * @param value Value to check
2270
- * @returns `true` if the value is events for a herald, otherwise `false`
2271
- */
2272
- function isEvents(value) {
2273
- return isHeraldInstance(NAME_EVENTS, value);
2274
- }
2275
- /**
2276
- * Is the value a herald?
2460
+ * _Available as `initializeEqualizer` and `equal.initialize`_
2277
2461
  *
2278
- * @param value Value to check
2279
- * @returns `true` if the value is a herald, otherwise `false`
2280
- */
2281
- function isHerald(value) {
2282
- return isHeraldInstance(NAME_HERALD, value);
2283
- }
2284
- function isHeraldInstance(name, value) {
2285
- return typeof value === "object" && value != null && KEY_HERALD in value && value[KEY_HERALD] === name;
2286
- }
2287
- const KEY_HERALD = "$herald";
2288
- const MESSAGE = "Herald requires an array of event names.";
2289
- const NAME_EVENTS = "events";
2290
- const NAME_HERALD = "herald";
2291
- //#endregion
2292
- //#region src/internal/subscription.ts
2293
- function addSubscription(subscription, state) {
2294
- const { key, subscriptions, value } = state.parameters;
2295
- const { items, values } = subscriptions;
2296
- if (key == null) {
2297
- items.any.add(subscription);
2298
- values.from.any.set(value, subscription);
2299
- values.to.any.set(subscription, value);
2300
- return;
2301
- }
2302
- if (items.keyed == null || values.from.keyed == null || values.to.keyed == null)
2303
- // istanbul ignore next
2304
- return;
2305
- let keyedItems = items.keyed.get(key);
2306
- if (keyedItems == null) {
2307
- keyedItems = /* @__PURE__ */ new Set();
2308
- items.keyed.set(key, keyedItems);
2309
- }
2310
- keyedItems.add(subscription);
2311
- let keyedFrom = values.from.keyed.get(key);
2312
- if (keyedFrom == null) {
2313
- keyedFrom = /* @__PURE__ */ new Map();
2314
- values.from.keyed.set(key, keyedFrom);
2315
- }
2316
- keyedFrom.set(value, subscription);
2317
- let keyedTo = values.to.keyed.get(key);
2318
- if (keyedTo == null) {
2319
- keyedTo = /* @__PURE__ */ new Map();
2320
- values.to.keyed.set(key, keyedTo);
2321
- }
2322
- keyedTo.set(subscription, value);
2323
- }
2324
- function clearSubscriptions(store) {
2325
- for (const susbcription of store.values.to.any.keys()) susbcription.unsubscribe();
2326
- if (store.values.to.keyed != null) for (const values of store.values.to.keyed.values()) for (const susbcription of values.keys()) susbcription.unsubscribe();
2327
- }
2328
- function getExistingSubscription(state) {
2329
- const { parameters } = state;
2330
- const { values } = parameters.subscriptions;
2331
- return parameters.key == null ? values.from.any.get(parameters.value) : values.from.keyed?.get(parameters.key)?.get(parameters.value);
2332
- }
2333
- function getSubscription(parameters) {
2334
- const state = {
2335
- parameters,
2336
- active: true
2337
- };
2338
- const existing = getExistingSubscription(state);
2339
- if (existing != null) return existing;
2340
- if (parameters.subscriptions.keys != null && parameters.key != null && !parameters.subscriptions.keys.has(parameters.key)) throw new Error();
2341
- const instance = { unsubscribe: () => {
2342
- removeSubscription(instance, state);
2343
- } };
2344
- Object.defineProperties(instance, {
2345
- [PROPERTY]: {
2346
- enumerable: false,
2347
- value: true
2348
- },
2349
- [parameters.property.key]: {
2350
- enumerable: false,
2351
- value: parameters.property.value
2352
- },
2353
- active: {
2354
- enumerable: true,
2355
- get: () => (parameters.isActive?.() ?? true) && state.active
2356
- }
2357
- });
2358
- addSubscription(instance, state);
2359
- return Object.freeze(instance);
2360
- }
2361
- function getSubscriptions(keys) {
2362
- return {
2363
- keys,
2364
- items: {
2365
- any: /* @__PURE__ */ new Set(),
2366
- keyed: keys == null ? void 0 : /* @__PURE__ */ new Map()
2367
- },
2368
- values: {
2369
- from: {
2370
- any: /* @__PURE__ */ new Map(),
2371
- keyed: keys == null ? void 0 : /* @__PURE__ */ new Map()
2372
- },
2373
- to: {
2374
- any: /* @__PURE__ */ new Map(),
2375
- keyed: keys == null ? void 0 : /* @__PURE__ */ new Map()
2376
- }
2377
- }
2378
- };
2379
- }
2380
- /**
2381
- * Is the value a subscription?
2382
- *
2383
- * @param value Value to check
2384
- * @returns `true` if the value is a subscription, otherwise `false`
2385
- */
2386
- function isSubscription(value) {
2387
- return isPlainObject(value) && PROPERTY in value && value[PROPERTY] === true;
2388
- }
2389
- function removeFromStore(items, values, subscription, value, key) {
2390
- items.delete(subscription);
2391
- if (key == null) {
2392
- values.from.any.delete(value);
2393
- values.to.any.delete(subscription);
2394
- } else {
2395
- values.from.keyed?.get(key)?.delete(value);
2396
- values.to.keyed?.get(key)?.delete(subscription);
2397
- }
2398
- }
2399
- function removeSubscription(subscription, state) {
2400
- if (!state.active) return;
2401
- state.active = false;
2402
- const { key, subscriptions, value } = state.parameters;
2403
- const { items, values } = subscriptions;
2404
- if (key == null) {
2405
- removeFromStore(items.any, values, subscription, value);
2406
- return;
2407
- }
2408
- const keyed = items.keyed?.get(key);
2409
- if (items.keyed == null || keyed == null)
2410
- // istanbul ignore next
2411
- return;
2412
- removeFromStore(keyed, values, subscription, value, key);
2413
- if (keyed.size === 0) items.keyed.delete(key);
2414
- }
2415
- const PROPERTY = "$subscription";
2416
- //#endregion
2417
- //#region src/internal/value/equal.ts
2418
- /**
2419
- * Deregister a equality comparison handler for a specific class
2420
- *
2421
- * _Available as `deregisterEqualizer` and `equal.deregister`_
2422
- *
2423
- * @param constructor Class constructor
2424
- */
2425
- function deregisterEqualizer(constructor) {
2426
- equal.handlers.deregister(constructor);
2427
- }
2428
- function filterKey(key, options) {
2429
- if (typeof key !== "string") return true;
2430
- if (options.ignoreExpressions.enabled && options.ignoreExpressions.values.some((expression) => expression.test(key))) return false;
2431
- if (options.ignoreKeys.enabled && options.ignoreKeys.values.has(key)) return false;
2432
- return true;
2433
- }
2434
- function equal(first, second, options) {
2435
- return equalValue(first, second, getEqualOptions(options));
2436
- }
2437
- equal.handlers = getCompareHandlers(equal, { callback: Object.is });
2438
- equal.deregister = deregisterEqualizer;
2439
- equal.initialize = initializeEqualizer;
2440
- equal.register = registerEqualizer;
2441
- function equalArray(first, second, options) {
2442
- const { length } = first;
2443
- if (length !== second.length) return false;
2444
- let offset = 0;
2445
- if (length >= EQUAL_ARRAY_THRESHOLD) {
2446
- offset = Math.round(length / EQUAL_ARRAY_PEEK_PERCENTAGE);
2447
- offset = offset > EQUAL_ARRAY_THRESHOLD ? EQUAL_ARRAY_THRESHOLD : offset;
2448
- for (let index = 0; index < offset; index += 1) if (!(equalValue(first[index], second[index], options) && equalValue(first[length - index - 1], second[length - index - 1], options))) return false;
2449
- }
2450
- const end = length - offset;
2451
- for (let index = offset; index < end; index += 1) if (!equalValue(first[index], second[index], options)) return false;
2452
- return true;
2453
- }
2454
- function equalArrayBuffer(first, second, options) {
2455
- return first.byteLength === second.byteLength ? equalArray(new Uint8Array(first), new Uint8Array(second), options) : false;
2456
- }
2457
- function equalDataView(first, second, options) {
2458
- return first.byteOffset === second.byteOffset ? equalArrayBuffer(first.buffer, second.buffer, options) : false;
2459
- }
2460
- function equalMap(first, second, options) {
2461
- const { size } = first;
2462
- if (size !== second.size) return false;
2463
- const firstKeys = [...first.keys()];
2464
- for (let index = 0; index < size; index += 1) {
2465
- const key = firstKeys[index];
2466
- if (!second.has(key) || !equalValue(first.get(key), second.get(key), options)) return false;
2467
- }
2468
- return true;
2469
- }
2470
- function equalPlainObject(first, second, options) {
2471
- let firstKeys = [...Object.keys(first), ...Object.getOwnPropertySymbols(first)];
2472
- let secondKeys = [...Object.keys(second), ...Object.getOwnPropertySymbols(second)];
2473
- if (options.ignoreKeys.enabled || options.ignoreExpressions.enabled) {
2474
- firstKeys = firstKeys.filter((key) => filterKey(key, options));
2475
- secondKeys = secondKeys.filter((key) => filterKey(key, options));
2476
- }
2477
- const secondSet = secondKeys.length >= MINIMUM_LENGTH_FOR_SET ? new Set(secondKeys) : void 0;
2478
- const { length } = firstKeys;
2479
- if (length !== secondKeys.length) return false;
2480
- for (let index = 0; index < length; index += 1) {
2481
- const key = firstKeys[index];
2482
- if (!(secondSet?.has(key) ?? secondKeys.includes(key)) || !equalValue(first[key], second[key], options)) return false;
2483
- }
2484
- return true;
2485
- }
2486
- function equalProperties(first, second, properties, options) {
2487
- const { length } = properties;
2488
- for (let index = 0; index < length; index += 1) {
2489
- const property = properties[index];
2490
- if (!equalValue(first[property], second[property], options)) return false;
2491
- }
2492
- return true;
2493
- }
2494
- function equalSet(first, second, options) {
2495
- const { size } = first;
2496
- if (size !== second.size) return false;
2497
- const firstValues = [...first];
2498
- const secondValues = [...second];
2499
- for (let index = 0; index < size; index += 1) {
2500
- const firstValue = firstValues[index];
2501
- if (isPrimitive(firstValue) ? !second.has(firstValue) : !secondValues.some((secondValue) => equalValue(firstValue, secondValue, options))) return false;
2502
- }
2503
- return true;
2504
- }
2505
- function equalTypedArray(first, second) {
2506
- if (first.constructor !== second.constructor) return false;
2507
- if (first.byteLength !== second.byteLength) return false;
2508
- const { length } = first;
2509
- for (let index = 0; index < length; index += 1) if (first[index] !== second[index]) return false;
2510
- return true;
2511
- }
2512
- function equalValue(first, second, options) {
2513
- if (options.relaxedNullish && first == null && second == null) return true;
2514
- switch (true) {
2515
- case Object.is(first, second): return true;
2516
- case first == null || second == null: return first === second;
2517
- case typeof first !== typeof second: return false;
2518
- case typeof first === "string" && options.ignoreCase === true: return Object.is(first.toLocaleLowerCase(), second.toLocaleLowerCase());
2519
- case first instanceof ArrayBuffer && second instanceof ArrayBuffer: return equalArrayBuffer(first, second, options);
2520
- case first instanceof Date && second instanceof Date: return Object.is(first.getTime(), second.getTime());
2521
- case first instanceof DataView && second instanceof DataView: return equalDataView(first, second, options);
2522
- case first instanceof Error && second instanceof Error: return equalProperties(first, second, ERROR_PROPERTIES, options);
2523
- case first instanceof Map && second instanceof Map: return equalMap(first, second, options);
2524
- case first instanceof RegExp && second instanceof RegExp: return equalProperties(first, second, EXPRESSION_PROPERTIES, options);
2525
- case first instanceof Set && second instanceof Set: return equalSet(first, second, options);
2526
- case Array.isArray(first) && Array.isArray(second): return equalArray(first, second, options);
2527
- case isPlainObject(first) && isPlainObject(second): return equalPlainObject(first, second, options);
2528
- case isTypedArray(first) && isTypedArray(second): return equalTypedArray(first, second);
2529
- default: return equal.handlers.handle(first, second, options);
2530
- }
2531
- }
2532
- function getEqualOptions(input) {
2533
- const options = {
2534
- ignoreCase: false,
2535
- ignoreExpressions: {
2536
- enabled: false,
2537
- values: []
2538
- },
2539
- ignoreKeys: {
2540
- enabled: false,
2541
- values: /* @__PURE__ */ new Set()
2542
- },
2543
- relaxedNullish: false
2544
- };
2545
- if (typeof input === "boolean") {
2546
- options.ignoreCase = input;
2547
- return options;
2548
- }
2549
- if (isNonPlainObject(input)) return options;
2550
- options.ignoreCase = typeof input.ignoreCase === "boolean" ? input.ignoreCase : false;
2551
- options.ignoreExpressions.values = (Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => key instanceof RegExp);
2552
- options.ignoreKeys.values = new Set((Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => typeof key === "string"));
2553
- options.ignoreExpressions.enabled = options.ignoreExpressions.values.length > 0;
2554
- options.ignoreKeys.enabled = options.ignoreKeys.values.size > 0;
2555
- options.relaxedNullish = input.relaxedNullish === true;
2556
- return options;
2557
- }
2558
- /**
2559
- * Create an equalizer with predefined options
2560
- *
2561
- * _Available as `initializeEqualizer` and `equal.initialize`_
2562
- *
2563
- * @param options Comparison options
2564
- * @returns Equalizer function
2462
+ * @param options Comparison options
2463
+ * @returns Equalizer function
2565
2464
  */
2566
2465
  function initializeEqualizer(options) {
2567
2466
  const actual = getEqualOptions(options);
@@ -2583,9 +2482,9 @@ function registerEqualizer(constructor, handler) {
2583
2482
  }
2584
2483
  const EQUAL_ARRAY_PEEK_PERCENTAGE = 10;
2585
2484
  const EQUAL_ARRAY_THRESHOLD = 100;
2586
- const ERROR_PROPERTIES = ["name", "message"];
2587
- const EXPRESSION_PROPERTIES = ["source", "flags"];
2588
- const MINIMUM_LENGTH_FOR_SET = 16;
2485
+ const EQUAL_ERROR_PROPERTIES = ["name", "message"];
2486
+ const EQUAL_EXPRESSION_PROPERTIES = ["source", "flags"];
2487
+ const EQUAL_MINIMUM_LENGTH_FOR_SET = 16;
2589
2488
  //#endregion
2590
2489
  //#region src/internal/value/get.ts
2591
2490
  function getValue(data, path, ignoreCase) {
@@ -2613,7 +2512,7 @@ function setValue(data, path, value, ignoreCase) {
2613
2512
  let next = handleValue(target, currentPath, null, true, shouldIgnoreCase).value;
2614
2513
  if (typeof next !== "object" || next === null) {
2615
2514
  const nextPath = paths[index + 1];
2616
- if (EXPRESSION_INDEX.test(nextPath)) next = Array.from({ length: Number(nextPath) + 1 }, () => void 0);
2515
+ if (SET_EXPRESSION_INDEX.test(nextPath)) next = Array.from({ length: Number(nextPath) + 1 }, () => void 0);
2617
2516
  else next = {};
2618
2517
  target[currentPath] = next;
2619
2518
  }
@@ -2621,142 +2520,376 @@ function setValue(data, path, value, ignoreCase) {
2621
2520
  }
2622
2521
  return data;
2623
2522
  }
2624
- const EXPRESSION_INDEX = /^\d+$/;
2523
+ const SET_EXPRESSION_INDEX = /^\d+$/;
2625
2524
  //#endregion
2626
- //#region src/string/case.ts
2627
- /**
2628
- * Convert a string to camel case _(thisIsCamelCase)_
2629
- *
2630
- * @param value String to convert
2631
- * @returns Camel-cased string
2632
- */
2633
- function camelCase(value) {
2634
- return toCase(CASE_CAMEL, value, true, false);
2525
+ //#region src/internal/abort.ts
2526
+ function createAborter(value, onAbort) {
2527
+ if (!(value instanceof AbortSignal)) return;
2528
+ value.addEventListener(ABORT_EVENT, onAbort, ABORT_OPTIONS);
2529
+ return {
2530
+ callback: onAbort,
2531
+ signal: value,
2532
+ cancel: () => value.removeEventListener(ABORT_EVENT, onAbort)
2533
+ };
2534
+ }
2535
+ const ABORT_EVENT = "abort";
2536
+ const ABORT_OPTIONS = { once: true };
2537
+ //#endregion
2538
+ //#region src/internal/defaults.ts
2539
+ function getBooleanOrDefault(value, defaultValue) {
2540
+ return typeof value === "boolean" ? value : defaultValue;
2541
+ }
2542
+ function getNumberOrDefault(value, defaultValue, minimum) {
2543
+ return typeof value === "number" && !Number.isNaN(value) && value >= (minimum ?? 0) ? value : defaultValue;
2635
2544
  }
2545
+ //#endregion
2546
+ //#region src/promise/constants.ts
2547
+ const PROMISE_ERROR_NAME = "PromiseTimeoutError";
2548
+ const PROMISE_MESSAGE_EXPECTATION_ATTEMPT = "Attempt expected a function or a promise";
2549
+ const PROMISE_MESSAGE_EXPECTATION_RESULT = "toResult expected a Promise";
2550
+ const PROMISE_MESSAGE_EXPECTATION_TIMED = "Timed function expected a Promise";
2551
+ const PROMISE_MESSAGE_TIMEOUT = "Promise timed out";
2552
+ const PROMISE_STRATEGY_ALL = /* @__PURE__ */ new Set(["complete", "first"]);
2553
+ const PROMISE_STRATEGY_DEFAULT = "complete";
2554
+ const PROMISE_TYPE_FULFILLED = "fulfilled";
2555
+ const PROMISE_TYPE_REJECTED = "rejected";
2556
+ //#endregion
2557
+ //#region src/promise/models.ts
2636
2558
  /**
2637
- * Capitalize the first letter of a string _(and lowercase the rest)_
2638
- *
2639
- * @param value String to capitalize
2640
- * @returns Capitalized string
2559
+ * A _Promise_ that can be canceled
2641
2560
  */
2642
- function capitalize(value) {
2643
- if (typeof value !== "string" || value.length === 0) return "";
2644
- memoizedCapitalize ??= memoize((v) => v.length === 1 ? v.toLocaleUpperCase() : `${v.charAt(0).toLocaleUpperCase()}${v.slice(1).toLocaleLowerCase()}`);
2645
- return memoizedCapitalize.run(value);
2561
+ var CancelablePromise = class extends Promise {
2562
+ #rejector;
2563
+ constructor(executor) {
2564
+ let rejector;
2565
+ super((resolve, reject) => {
2566
+ rejector = reject;
2567
+ executor(resolve, reject);
2568
+ });
2569
+ this.#rejector = rejector;
2570
+ }
2571
+ /**
2572
+ * Cancel the _Promise_, rejecting it with an optional reason
2573
+ *
2574
+ * @param reason Optional reason for canceling the _Promise_
2575
+ */
2576
+ cancel(reason) {
2577
+ this.#rejector?.(reason);
2578
+ this.#rejector = void 0;
2579
+ }
2580
+ };
2581
+ /**
2582
+ * An error thrown when a promise times out
2583
+ */
2584
+ var PromiseTimeoutError = class extends Error {
2585
+ constructor() {
2586
+ super(PROMISE_MESSAGE_TIMEOUT);
2587
+ this.name = PROMISE_ERROR_NAME;
2588
+ }
2589
+ };
2590
+ //#endregion
2591
+ //#region src/promise/helpers.ts
2592
+ function getPromiseOptions(input) {
2593
+ if (typeof input === "number") return { time: getNumberOrDefault(input, 0) };
2594
+ if (input instanceof AbortSignal) return {
2595
+ signal: input,
2596
+ time: 0
2597
+ };
2598
+ const options = typeof input === "object" && input !== null ? input : {};
2599
+ return {
2600
+ signal: options.signal instanceof AbortSignal ? options.signal : void 0,
2601
+ time: getNumberOrDefault(options.time, 0)
2602
+ };
2603
+ }
2604
+ function getPromisesOptions(input) {
2605
+ if (typeof input === "string") return { strategy: getStrategyOrDefault(input) };
2606
+ if (input instanceof AbortSignal) return {
2607
+ signal: input,
2608
+ strategy: PROMISE_STRATEGY_DEFAULT
2609
+ };
2610
+ const options = typeof input === "object" && input !== null ? input : {};
2611
+ return {
2612
+ signal: options.signal instanceof AbortSignal ? options.signal : void 0,
2613
+ strategy: getStrategyOrDefault(options.strategy)
2614
+ };
2615
+ }
2616
+ function getResultsFromPromises(promised) {
2617
+ return promised.map((result) => isFulfilled(result) ? ok(result.value) : error(result.reason));
2618
+ }
2619
+ function getStrategyOrDefault(value) {
2620
+ return PROMISE_STRATEGY_ALL.has(value) ? value : PROMISE_STRATEGY_DEFAULT;
2646
2621
  }
2647
2622
  /**
2648
- * Convert a string to kebab case _(this-is-kebab-case)_
2623
+ * Is the value a fulfilled _Promise_ result?
2649
2624
  *
2650
- * @param value String to convert
2651
- * @returns Kebab-cased string
2625
+ * @param value Value to check
2626
+ * @returns `true` if the value is a fulfilled _Promise_ result, otherwise `false`
2652
2627
  */
2653
- function kebabCase(value) {
2654
- return toCase(CASE_KEBAB, value, false, false);
2628
+ function isFulfilled(value) {
2629
+ return isType(value, PROMISE_TYPE_FULFILLED);
2655
2630
  }
2656
2631
  /**
2657
- * Convert a string to lower case
2632
+ * Is the value a rejected _Promise_ result?
2658
2633
  *
2659
- * @param value String to convert
2660
- * @returns Lower-cased string
2634
+ * @param value Value to check
2635
+ * @returns `true` if the value is a rejected _Promise_ result, otherwise `false`
2661
2636
  */
2662
- function lowerCase(value) {
2663
- if (typeof value !== "string") return "";
2664
- memoizedLowerCase ??= memoize((v) => v.toLocaleLowerCase());
2665
- return memoizedLowerCase.run(value);
2637
+ function isRejected(value) {
2638
+ return isType(value, PROMISE_TYPE_REJECTED);
2666
2639
  }
2640
+ function isType(value, type) {
2641
+ return typeof value === "object" && value !== null && value.status === type;
2642
+ }
2643
+ //#endregion
2644
+ //#region src/result/misc.ts
2667
2645
  /**
2668
- * Convert a string to pascal case _(ThisIsPascalCase)_
2646
+ * Converts a _Result_ to a _Promise_
2669
2647
  *
2670
- * @param value String to convert
2671
- * @returns Pascal-cased string
2648
+ * Resolves if ok, rejects for error
2649
+ *
2650
+ * @param result _Result_ to convert
2651
+ * @returns Promised result
2672
2652
  */
2673
- function pascalCase(value) {
2674
- return toCase(CASE_PASCAL, value, true, true);
2653
+ async function toPromise(result) {
2654
+ const actual = typeof result === "function" ? result() : result;
2655
+ if (!isResult(actual)) return Promise.reject(new Error(RESULT_MESSAGE_PROMISE));
2656
+ return isOk(actual) ? Promise.resolve(actual.value) : Promise.reject(actual.error);
2675
2657
  }
2658
+ const RESULT_MESSAGE_PROMISE = "toPromise expected to receive a Result";
2659
+ //#endregion
2660
+ //#region src/promise/misc.ts
2676
2661
  /**
2677
- * Convert a string to snake case _(this_is_snake_case)_
2662
+ * Create a cancelable _Promise_
2678
2663
  *
2679
- * @param value String to convert
2680
- * @returns Snake-cased string
2664
+ * @param executor Executor function for the _Promise_
2665
+ * @returns Cancelable _Promise_
2681
2666
  */
2682
- function snakeCase(value) {
2683
- return toCase(CASE_SNAKE, value, false, false);
2667
+ function cancelable(executor) {
2668
+ return new CancelablePromise(executor);
2669
+ }
2670
+ function handleResult(status, parameters) {
2671
+ const { aborter, complete, data, handlers, index, value } = parameters;
2672
+ if (aborter?.signal.aborted ?? false) return;
2673
+ if (!complete && status === "rejected") {
2674
+ settlePromise(handlers.reject, value, aborter);
2675
+ return;
2676
+ }
2677
+ data.result[index] = !complete ? value : status === "fulfilled" ? {
2678
+ status,
2679
+ value
2680
+ } : {
2681
+ status,
2682
+ reason: value
2683
+ };
2684
+ if (index === data.last) settlePromise(handlers.resolve, data.result, aborter);
2685
+ }
2686
+ function settlePromise(settler, value, aborter) {
2687
+ aborter?.cancel();
2688
+ settler(value);
2689
+ }
2690
+ async function toResult(value) {
2691
+ const actual = typeof value === "function" ? value() : value;
2692
+ if (!(actual instanceof Promise)) return Promise.reject(/* @__PURE__ */ new TypeError(PROMISE_MESSAGE_EXPECTATION_RESULT));
2693
+ return actual.then((result) => ok(result)).catch((reason) => error(reason));
2694
+ }
2695
+ //#endregion
2696
+ //#region src/promise/delay.ts
2697
+ function delay(options) {
2698
+ const { signal, time } = getPromiseOptions(options);
2699
+ if (signal?.aborted ?? false) return Promise.reject(signal?.reason);
2700
+ const aborter = createAborter(signal, () => {
2701
+ timer.cancel();
2702
+ rejector(signal?.reason);
2703
+ });
2704
+ const timer = getTimer(TIMER_WAIT, () => settlePromise(resolver, void 0, aborter), time);
2705
+ let rejector;
2706
+ let resolver;
2707
+ return new Promise((resolve, reject) => {
2708
+ rejector = reject;
2709
+ resolver = resolve;
2710
+ if (time === 0) settlePromise(resolver, void 0, aborter);
2711
+ else timer();
2712
+ });
2713
+ }
2714
+ //#endregion
2715
+ //#region src/promise/timed.ts
2716
+ async function getTimedPromise(promise, time, signal) {
2717
+ const aborter = createAborter(signal, () => {
2718
+ timer.cancel();
2719
+ rejector(signal?.reason);
2720
+ });
2721
+ const timer = getTimer(TIMER_WAIT, () => settlePromise(rejector, new PromiseTimeoutError(), aborter), time);
2722
+ let rejector;
2723
+ return Promise.race([promise, new Promise((_, reject) => {
2724
+ rejector = reject;
2725
+ timer();
2726
+ })]).then((value) => {
2727
+ aborter?.cancel();
2728
+ timer.cancel();
2729
+ rejector(void 0);
2730
+ return value;
2731
+ });
2732
+ }
2733
+ async function timed(promise, options) {
2734
+ if (!(promise instanceof Promise)) return Promise.reject(/* @__PURE__ */ new TypeError(PROMISE_MESSAGE_EXPECTATION_TIMED));
2735
+ const { signal, time } = getPromiseOptions(options);
2736
+ if (signal?.aborted ?? false) return Promise.reject(signal?.reason);
2737
+ return time > 0 ? getTimedPromise(promise, time, signal) : promise;
2738
+ }
2739
+ //#endregion
2740
+ //#region src/promise/index.ts
2741
+ async function attemptPromise(value, options) {
2742
+ const isFunction = typeof value === "function";
2743
+ if (!isFunction && !(value instanceof Promise)) return Promise.reject(/* @__PURE__ */ new TypeError(PROMISE_MESSAGE_EXPECTATION_ATTEMPT));
2744
+ const { signal, time } = getPromiseOptions(options);
2745
+ if (signal?.aborted ?? false) return Promise.reject(signal?.reason);
2746
+ const aborter = createAborter(signal, () => {
2747
+ rejector(signal?.reason);
2748
+ });
2749
+ async function handler(resolve, reject) {
2750
+ try {
2751
+ let result = isFunction ? value() : await value;
2752
+ if (result instanceof Promise) result = await result;
2753
+ settlePromise(resolve, result, aborter);
2754
+ } catch (error) {
2755
+ settlePromise(reject, error, aborter);
2756
+ }
2757
+ }
2758
+ let rejector;
2759
+ const promise = new Promise((resolve, reject) => {
2760
+ rejector = reject;
2761
+ handler(resolve, reject);
2762
+ });
2763
+ return time > 0 ? getTimedPromise(promise, time, signal) : promise;
2764
+ }
2765
+ async function promises(items, options) {
2766
+ const { signal, strategy } = getPromisesOptions(options);
2767
+ if (signal?.aborted ?? false) return Promise.reject(signal?.reason);
2768
+ if (!Array.isArray(items)) return Promise.resolve([]);
2769
+ const actual = items.map((item) => typeof item === "function" ? item() : item).filter((item) => item instanceof Promise);
2770
+ const { length } = actual;
2771
+ if (length === 0) return Promise.resolve([]);
2772
+ const complete = strategy === PROMISE_STRATEGY_DEFAULT;
2773
+ const aborter = createAborter(signal, () => {
2774
+ handlers.reject(signal?.reason);
2775
+ });
2776
+ const data = {
2777
+ last: length - 1,
2778
+ result: []
2779
+ };
2780
+ let handlers;
2781
+ return new Promise((resolve, reject) => {
2782
+ handlers = {
2783
+ reject,
2784
+ resolve
2785
+ };
2786
+ for (let index = 0; index < length; index += 1) actual[index].then((value) => handleResult(PROMISE_TYPE_FULFILLED, {
2787
+ aborter,
2788
+ complete,
2789
+ data,
2790
+ handlers,
2791
+ index,
2792
+ value
2793
+ })).catch((reason) => handleResult(PROMISE_TYPE_REJECTED, {
2794
+ aborter,
2795
+ complete,
2796
+ data,
2797
+ handlers,
2798
+ index,
2799
+ value: reason
2800
+ }));
2801
+ });
2802
+ }
2803
+ promises.result = resultPromises;
2804
+ async function resultPromises(items, signal) {
2805
+ return promises(items, signal).then(getResultsFromPromises);
2806
+ }
2807
+ //#endregion
2808
+ //#region src/result/index.ts
2809
+ async function asyncAttempt(value, err) {
2810
+ try {
2811
+ let result = typeof value === "function" ? value() : await value;
2812
+ if (result instanceof Promise) result = await result;
2813
+ return ok(result);
2814
+ } catch (thrown) {
2815
+ return getError(err ?? thrown, err == null ? void 0 : thrown);
2816
+ }
2817
+ }
2818
+ function attempt(callback, err) {
2819
+ try {
2820
+ return ok(callback());
2821
+ } catch (thrown) {
2822
+ return getError(err ?? thrown, err == null ? void 0 : thrown);
2823
+ }
2824
+ }
2825
+ Object.defineProperty(attempt, "async", { value: asyncAttempt });
2826
+ //#endregion
2827
+ //#region src/result/match.ts
2828
+ async function asyncMatchResult(result, first, error) {
2829
+ let value;
2830
+ if (typeof result === "function") value = await result();
2831
+ else if (result instanceof Promise) value = await result;
2832
+ else value = result;
2833
+ if (!isResult(value)) throw new Error(MATCH_MESSAGE);
2834
+ const hasObj = typeof first === "object" && first !== null;
2835
+ const okHandler = hasObj ? first.ok : first;
2836
+ const errorHandler = hasObj ? first.error : error;
2837
+ if (isOk(value)) return okHandler(value.value);
2838
+ return errorHandler(value.error, value.original);
2684
2839
  }
2685
- /**
2686
- * Convert a string to title case _(Capitalizing Every Word)_
2687
- *
2688
- * @param value String to convert
2689
- * @returns Title-cased string
2690
- */
2691
- function titleCase(value) {
2692
- if (typeof value !== "string" || value.length === 0) return "";
2693
- memoizedTitleCase ??= memoize((v) => v.length < 2 ? capitalize(v) : join(words(v).map(capitalize), " "));
2694
- return memoizedTitleCase.run(value);
2840
+ function matchResult(result, first, error) {
2841
+ const value = typeof result === "function" ? result() : result;
2842
+ if (!isResult(value)) throw new Error(MATCH_MESSAGE);
2843
+ const hasObj = typeof first === "object" && first !== null;
2844
+ const okHandler = hasObj ? first.ok : first;
2845
+ const errorHandler = hasObj ? first.error : error;
2846
+ if (isOk(value)) return okHandler(value.value);
2847
+ return errorHandler(value.error, value.original);
2695
2848
  }
2696
- function toCase(type, value, capitalizeAny, capitalizeFirst) {
2697
- caseMemoizers[type] ??= memoize(toCaseCallback.bind({
2698
- type,
2699
- capitalizeAny,
2700
- capitalizeFirst
2701
- }));
2702
- return caseMemoizers[type].run(value);
2849
+ const MATCH_MESSAGE = "`result.match` expected a Result or a function that returns a Result";
2850
+ Object.defineProperty(matchResult, "async", { value: asyncMatchResult });
2851
+ //#endregion
2852
+ //#region src/result/work/flow.ts
2853
+ function attemptAsyncFlow(...fns) {
2854
+ let Flow;
2855
+ return (...args) => asyncAttempt(() => {
2856
+ Flow ??= asyncFlow(...fns);
2857
+ return Flow(...args.map((value) => {
2858
+ if (isError(value)) throw value.error;
2859
+ return isOk(value) ? value.value : value;
2860
+ }));
2861
+ });
2703
2862
  }
2704
- function toCaseCallback(value) {
2705
- if (typeof value !== "string") return "";
2706
- if (value.length < 1) return value;
2707
- const { capitalizeAny, capitalizeFirst, type } = this;
2708
- const parts = words(value);
2709
- const partsLength = parts.length;
2710
- const cased = [];
2711
- for (let partIndex = 0; partIndex < partsLength; partIndex += 1) {
2712
- const items = parts[partIndex].replace(EXPRESSION_ACRONYM, (full, one, two, three) => three === S ? full : `${one}-${two}${three}`).replace(EXPRESSION_CAMEL_CASE, REPLACEMENT_CAMEL_CASE).split("-");
2713
- const itemsLength = items.length;
2714
- const partResult = [];
2715
- let itemCount = 0;
2716
- for (let itemIndex = 0; itemIndex < itemsLength; itemIndex += 1) {
2717
- const item = items[itemIndex];
2718
- if (item.length === 0) continue;
2719
- if (!capitalizeAny || itemCount === 0 && partIndex === 0 && !capitalizeFirst) partResult.push(item.toLocaleLowerCase());
2720
- else partResult.push(capitalize(item));
2721
- itemCount += 1;
2722
- }
2723
- cased.push(join(partResult, delimiters[type]));
2724
- }
2725
- return join(cased, delimiters[type]);
2863
+ function attemptFlow(...fns) {
2864
+ let Flow;
2865
+ return (...args) => attempt(() => {
2866
+ Flow ??= flow(...fns);
2867
+ return Flow(...args.map((value) => {
2868
+ if (isError(value)) throw value.error;
2869
+ return isOk(value) ? value.value : value;
2870
+ }));
2871
+ });
2726
2872
  }
2727
- /**
2728
- * Convert a string to upper case
2729
- *
2730
- * @param value String to convert
2731
- * @returns Upper-cased string
2732
- */
2733
- function upperCase(value) {
2734
- if (typeof value !== "string" || value.length === 0) return "";
2735
- memoizedUpperCase ??= memoize((v) => v.toLocaleUpperCase());
2736
- return memoizedUpperCase.run(value);
2873
+ Object.defineProperty(attemptFlow, "async", { value: attemptAsyncFlow });
2874
+ //#endregion
2875
+ //#region src/result/work/pipe.ts
2876
+ async function attemptAsyncPipe(initial, first, ...seconds) {
2877
+ return asyncAttempt(() => {
2878
+ if (isError(initial)) throw initial.error;
2879
+ const value = typeof initial === "function" ? initial() : isOk(initial) ? initial.value : initial;
2880
+ if (first == null) return value;
2881
+ return asyncPipe(value, ...[first, ...seconds]);
2882
+ });
2737
2883
  }
2738
- const CASE_CAMEL = "camel";
2739
- const CASE_KEBAB = "kebab";
2740
- const CASE_PASCAL = "pascal";
2741
- const CASE_SNAKE = "snake";
2742
- const DELIMTER_EMPTY = "";
2743
- const DELIMITER_HYPHEN = "-";
2744
- const DELIMITER_UNDERSCORE = "_";
2745
- const EXPRESSION_CAMEL_CASE = /(\p{Ll})(\p{Lu})/gu;
2746
- const EXPRESSION_ACRONYM = /(\p{Lu}*)(\p{Lu})(\p{Ll}+)/gu;
2747
- const REPLACEMENT_CAMEL_CASE = "$1-$2";
2748
- const S = "s";
2749
- const caseMemoizers = {};
2750
- const delimiters = {
2751
- [CASE_CAMEL]: DELIMTER_EMPTY,
2752
- [CASE_KEBAB]: DELIMITER_HYPHEN,
2753
- [CASE_PASCAL]: DELIMTER_EMPTY,
2754
- [CASE_SNAKE]: DELIMITER_UNDERSCORE
2755
- };
2756
- let memoizedCapitalize;
2757
- let memoizedLowerCase;
2758
- let memoizedTitleCase;
2759
- let memoizedUpperCase;
2884
+ function attemptPipe(initial, first, ...seconds) {
2885
+ return attempt(() => {
2886
+ if (isError(initial)) throw initial.error;
2887
+ const value = typeof initial === "function" ? initial() : isOk(initial) ? initial.value : initial;
2888
+ if (first == null) return value;
2889
+ return pipe(value, ...[first, ...seconds]);
2890
+ });
2891
+ }
2892
+ Object.defineProperty(attemptPipe, "async", { value: attemptAsyncPipe });
2760
2893
  //#endregion
2761
2894
  //#region src/string/match.ts
2762
2895
  /**
@@ -2813,10 +2946,10 @@ function getHandler(input) {
2813
2946
  case "string": return (item) => item[input];
2814
2947
  default:
2815
2948
  if (isPlainObject(input)) return getHandler(input.key ?? input.handler);
2816
- throw new TypeError(MESSAGE_HANDLER);
2949
+ throw new TypeError(FUZZY_MESSAGE_HANDLER);
2817
2950
  }
2818
2951
  }
2819
- function getItems$1(items) {
2952
+ function getFuzzyItems(items) {
2820
2953
  return items.sort((first, second) => first.haystack.localeCompare(second.haystack)).map(({ item }) => item);
2821
2954
  }
2822
2955
  function getFuzzyOptions(input, state) {
@@ -2840,22 +2973,22 @@ function getFuzzyState(items, input) {
2840
2973
  }
2841
2974
  function getTolerance(input, state) {
2842
2975
  if (typeof input === "number" && !Number.isNaN(input)) return input < 0 ? 0 : Math.floor(input);
2843
- return state?.tolerance ?? PROXIMITY_THRESHOLD;
2976
+ return state?.tolerance ?? FUZZY_PROXIMITY_THRESHOLD;
2844
2977
  }
2845
2978
  function fuzzy(items, configuration) {
2846
- if (!Array.isArray(items)) throw new TypeError(MESSAGE_ARRAY);
2979
+ if (!Array.isArray(items)) throw new TypeError(FUZZY_MESSAGE_ARRAY);
2847
2980
  const state = getFuzzyState(items, configuration);
2848
2981
  const instance = { search: (value, options) => search(state.items, state.strings, value, options == null ? state : getFuzzyOptions(options, state)) };
2849
2982
  Object.defineProperties(instance, {
2850
2983
  items: {
2984
+ enumerable: true,
2851
2985
  get: () => state.items.slice(),
2852
- set: (items) => {
2853
- if (!Array.isArray(items)) throw new TypeError(MESSAGE_ARRAY);
2854
- state.items = items.slice();
2855
- state.strings = items.map(state.handler);
2856
- }
2986
+ set: (value) => setItems(state, value)
2857
2987
  },
2858
- strings: { get: () => state.strings.slice() }
2988
+ strings: {
2989
+ enumerable: true,
2990
+ get: () => state.strings.slice()
2991
+ }
2859
2992
  });
2860
2993
  return Object.freeze(instance);
2861
2994
  }
@@ -2899,14 +3032,14 @@ function getScore(haystack, needle) {
2899
3032
  if (haystackIndex === 0) score += 1;
2900
3033
  if (previousMatchIndex !== -1) {
2901
3034
  const gap = haystackIndex - previousMatchIndex - 1;
2902
- score += Math.max(0, PROXIMITY_THRESHOLD - gap);
3035
+ score += Math.max(0, FUZZY_PROXIMITY_THRESHOLD - gap);
2903
3036
  }
2904
3037
  previousMatchIndex = haystackIndex;
2905
3038
  needleIndex += 1;
2906
3039
  }
2907
3040
  if (needleIndex === needleLength) break;
2908
3041
  }
2909
- score -= Math.floor(lowerCaseHaystack.length / LENGTH_DIVISOR);
3042
+ score -= Math.floor(lowerCaseHaystack.length / FUZZY_LENGTH_DIVISOR);
2910
3043
  return Math.max(0, score);
2911
3044
  }
2912
3045
  function search(items, strings, input, options) {
@@ -2949,18 +3082,23 @@ function search(items, strings, input, options) {
2949
3082
  for (let index = 0; index < length; index += 1) {
2950
3083
  const key = keys[index];
2951
3084
  if (maxScore - key > options.tolerance) break;
2952
- similar.push(...getItems$1(scored[key]));
3085
+ similar.push(...getFuzzyItems(scored[key]));
2953
3086
  }
2954
3087
  }
2955
- result.exact = getItems$1(options.limit == null ? exact : exact.slice(0, options.limit));
3088
+ result.exact = getFuzzyItems(options.limit == null ? exact : exact.slice(0, options.limit));
2956
3089
  if (options.limit == null) result.similar = similar;
2957
3090
  else result.similar = similar.slice(0, options.limit - result.exact.length);
2958
3091
  return result;
2959
3092
  }
2960
- const LENGTH_DIVISOR = 3;
2961
- const MESSAGE_ARRAY = "Fuzzy requires an array of items";
2962
- const MESSAGE_HANDLER = "Fuzzy requires a key or function to stringify items";
2963
- const PROXIMITY_THRESHOLD = 5;
3093
+ function setItems(state, value) {
3094
+ if (!Array.isArray(value)) throw new TypeError(FUZZY_MESSAGE_ARRAY);
3095
+ state.items = value.slice();
3096
+ state.strings = value.map(state.handler);
3097
+ }
3098
+ const FUZZY_LENGTH_DIVISOR = 3;
3099
+ const FUZZY_MESSAGE_ARRAY = "Fuzzy requires an array of items";
3100
+ const FUZZY_MESSAGE_HANDLER = "Fuzzy requires a key or function to stringify items";
3101
+ const FUZZY_PROXIMITY_THRESHOLD = 5;
2964
3102
  //#endregion
2965
3103
  //#region src/string/index.ts
2966
3104
  function dedent(value, ...values) {
@@ -2999,16 +3137,16 @@ function getUuid(html) {
2999
3137
  crypto.getRandomValues(bytes);
3000
3138
  bytes[6] = bytes[6] & 15 | 64;
3001
3139
  bytes[8] = bytes[8] & 63 | 128;
3002
- const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, ZERO)).join("");
3140
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, STRING_ZERO)).join("");
3003
3141
  const first = hex.substring(0, 8);
3004
- if (forHTML && NUMERICAL_PREFIX_PATTERN.test(first)) continue;
3142
+ if (forHTML && STRING_NUMERICAL_PREFIX_PATTERN.test(first)) continue;
3005
3143
  return [
3006
3144
  first,
3007
3145
  hex.substring(8, 12),
3008
3146
  hex.substring(12, 16),
3009
3147
  hex.substring(16, 20),
3010
3148
  hex.substring(20, 32)
3011
- ].join(forHTML ? DELIMITER_UUID_HTML : DELIMITER_UUID_DEFAULT);
3149
+ ].join(forHTML ? STRING_DELIMITER_UUID_HTML : STRING_DELIMITER_UUID_DEFAULT);
3012
3150
  }
3013
3151
  }
3014
3152
  /**
@@ -3051,10 +3189,10 @@ function truncate(value, length, suffix) {
3051
3189
  const truncatedLength = length - actualSuffixLength;
3052
3190
  return `${value.slice(0, truncatedLength)}${actualSuffix}`;
3053
3191
  }
3054
- const DELIMITER_UUID_DEFAULT = "-";
3055
- const DELIMITER_UUID_HTML = "_";
3056
- const NUMERICAL_PREFIX_PATTERN = /^\d/;
3057
- const ZERO = "0";
3192
+ const STRING_DELIMITER_UUID_DEFAULT = "-";
3193
+ const STRING_DELIMITER_UUID_HTML = "_";
3194
+ const STRING_NUMERICAL_PREFIX_PATTERN = /^\d/;
3195
+ const STRING_ZERO = "0";
3058
3196
  //#endregion
3059
3197
  //#region src/string/normalize.ts
3060
3198
  /**
@@ -3066,8 +3204,8 @@ const ZERO = "0";
3066
3204
  function deburr(value) {
3067
3205
  if (typeof value !== "string") return "";
3068
3206
  deburrMemoizer ??= memoize((value) => {
3069
- let deburred = value.normalize(DEBURR_NORMALIZATION).replace(DEBURR_PATTERN_SIMPLE, "");
3070
- deburred = deburred.replace(DEBURR_PATTERN_CHARACTERS, (_, character) => DEBURR_CHARACTERS[character]);
3207
+ let deburred = value.normalize(NORMALIZE_DEBURR_NORMALIZATION).replace(NORMALIZE_DEBURR_PATTERN_SIMPLE, "");
3208
+ deburred = deburred.replace(NORMALIZE_DEBURR_PATTERN_CHARACTERS, (_, character) => NORMALIZE_DEBURR_CHARACTERS[character]);
3071
3209
  return deburred;
3072
3210
  });
3073
3211
  return deburrMemoizer.run(value);
@@ -3111,13 +3249,13 @@ function normalizeString(value, options) {
3111
3249
  if (typeof value !== "string") return "";
3112
3250
  let result = value;
3113
3251
  if (options.trim) result = result.trim();
3114
- if (options.whitespace) result = result.replace(WHITESPACE_PATTERN, WHITESPACE_REPLACEMENT);
3252
+ if (options.whitespace) result = result.replace(NORMALIZE_WHITESPACE_PATTERN, NORMALIZE_WHITESPACE_REPLACEMENT);
3115
3253
  if (options.deburr) result = deburr(result);
3116
3254
  if (options.lowerCase) result = lowerCase(result);
3117
- if (options.special) result = result.replace(SPECIAL_PATTERN, SPECIAL_REPLACEMENT);
3118
- return result.normalize(NORMALIZATION_NORMALIZATION);
3255
+ if (options.special) result = result.replace(NORMALIZE_SPECIAL_PATTERN, NORMALIZE_SPECIAL_REPLACEMENT);
3256
+ return result.normalize(NORMALIZE_NORMALIZATION_NORMALIZATION);
3119
3257
  }
3120
- const DEBURR_CHARACTERS = {
3258
+ const NORMALIZE_DEBURR_CHARACTERS = {
3121
3259
  Æ: "AE",
3122
3260
  æ: "ae",
3123
3261
  Ð: "D",
@@ -3149,14 +3287,14 @@ const DEBURR_CHARACTERS = {
3149
3287
  Ŧ: "T",
3150
3288
  ŧ: "t"
3151
3289
  };
3152
- const DEBURR_NORMALIZATION = "NFD";
3153
- const DEBURR_PATTERN_CHARACTERS = new RegExp(`(${Object.keys(DEBURR_CHARACTERS).join("|")})`, "g");
3154
- const DEBURR_PATTERN_SIMPLE = /[\u0300-\u036f]/g;
3155
- const NORMALIZATION_NORMALIZATION = "NFC";
3156
- const SPECIAL_PATTERN = /[\p{P}\p{S}]/gu;
3157
- const SPECIAL_REPLACEMENT = "";
3158
- const WHITESPACE_PATTERN = /\s+/g;
3159
- const WHITESPACE_REPLACEMENT = " ";
3290
+ const NORMALIZE_DEBURR_NORMALIZATION = "NFD";
3291
+ const NORMALIZE_DEBURR_PATTERN_CHARACTERS = new RegExp(`(${Object.keys(NORMALIZE_DEBURR_CHARACTERS).join("|")})`, "g");
3292
+ const NORMALIZE_DEBURR_PATTERN_SIMPLE = /[\u0300-\u036f]/g;
3293
+ const NORMALIZE_NORMALIZATION_NORMALIZATION = "NFC";
3294
+ const NORMALIZE_SPECIAL_PATTERN = /[\p{P}\p{S}]/gu;
3295
+ const NORMALIZE_SPECIAL_REPLACEMENT = "";
3296
+ const NORMALIZE_WHITESPACE_PATTERN = /\s+/g;
3297
+ const NORMALIZE_WHITESPACE_REPLACEMENT = " ";
3160
3298
  let deburrMemoizer;
3161
3299
  //#endregion
3162
3300
  //#region src/string/template.ts
@@ -3169,7 +3307,7 @@ function getTemplateOptions(input) {
3169
3307
  const options = isPlainObject(input) ? input : {};
3170
3308
  return {
3171
3309
  ignoreCase: options.ignoreCase === true,
3172
- pattern: options.pattern instanceof RegExp ? options.pattern : EXPRESSION_VARIABLE
3310
+ pattern: options.pattern instanceof RegExp ? options.pattern : TEMPLATE_EXPRESSION_VARIABLE
3173
3311
  };
3174
3312
  }
3175
3313
  function handleTemplate(value, pattern, ignoreCase, variables) {
@@ -3204,7 +3342,7 @@ function template(value, ...parameters) {
3204
3342
  return handleTemplate(value, pattern, ignoreCase, parameters[0]);
3205
3343
  }
3206
3344
  template.initialize = initializeTemplater;
3207
- const EXPRESSION_VARIABLE = /{{([\s\S]+?)}}/g;
3345
+ const TEMPLATE_EXPRESSION_VARIABLE = /{{([\s\S]+?)}}/g;
3208
3346
  //#endregion
3209
3347
  //#region src/value/clone.ts
3210
3348
  const CLONE_NAME = "clone";
@@ -3218,21 +3356,21 @@ clone.handlers = getSelfHandlers(clone, {
3218
3356
  clone.deregister = deregisterCloner;
3219
3357
  clone.register = registerCloner;
3220
3358
  function cloneArrayBuffer(value, depth, references) {
3221
- if (typeof depth === "number" && depth >= MAX_CLONE_DEPTH) return value;
3359
+ if (typeof depth === "number" && depth >= CLONE_MAX_DEPTH) return value;
3222
3360
  const cloned = new ArrayBuffer(value.byteLength);
3223
3361
  new Uint8Array(cloned).set(new Uint8Array(value));
3224
3362
  references?.set(value, cloned);
3225
3363
  return cloned;
3226
3364
  }
3227
3365
  function cloneDataView(value, depth, references) {
3228
- if (depth >= MAX_CLONE_DEPTH) return value;
3366
+ if (depth >= CLONE_MAX_DEPTH) return value;
3229
3367
  const buffer = cloneArrayBuffer(value.buffer);
3230
3368
  const cloned = new DataView(buffer, value.byteOffset, value.byteLength);
3231
3369
  references.set(value, cloned);
3232
3370
  return cloned;
3233
3371
  }
3234
3372
  function cloneMap(map, depth, references, flat) {
3235
- if (depth >= MAX_CLONE_DEPTH) return map;
3373
+ if (depth >= CLONE_MAX_DEPTH) return map;
3236
3374
  const cloned = /* @__PURE__ */ new Map();
3237
3375
  const entries = map.entries();
3238
3376
  for (const entry of entries) cloned.set(flat ? entry[0] : cloneValue(entry[0], depth + 1, references, false), flat ? entry[1] : cloneValue(entry[1], depth + 1, references, false));
@@ -3240,13 +3378,13 @@ function cloneMap(map, depth, references, flat) {
3240
3378
  return cloned;
3241
3379
  }
3242
3380
  function cloneNode(node, depth, references) {
3243
- if (depth >= MAX_CLONE_DEPTH) return node;
3381
+ if (depth >= CLONE_MAX_DEPTH) return node;
3244
3382
  const cloned = node.cloneNode(true);
3245
3383
  references.set(node, cloned);
3246
3384
  return cloned;
3247
3385
  }
3248
3386
  function cloneObject(value, depth, references, flat) {
3249
- if (flat || depth >= MAX_CLONE_DEPTH) return Array.isArray(value) ? value.slice() : { ...value };
3387
+ if (flat || depth >= CLONE_MAX_DEPTH) return Array.isArray(value) ? value.slice() : { ...value };
3250
3388
  const cloned = Array.isArray(value) ? [] : {};
3251
3389
  const keys = [...Object.keys(value), ...Object.getOwnPropertySymbols(value)];
3252
3390
  const { length } = keys;
@@ -3258,14 +3396,14 @@ function cloneObject(value, depth, references, flat) {
3258
3396
  return cloned;
3259
3397
  }
3260
3398
  function cloneRegularExpression(value, depth, references) {
3261
- if (depth >= MAX_CLONE_DEPTH) return value;
3399
+ if (depth >= CLONE_MAX_DEPTH) return value;
3262
3400
  const cloned = new RegExp(value.source, value.flags);
3263
3401
  cloned.lastIndex = value.lastIndex;
3264
3402
  references.set(value, cloned);
3265
3403
  return cloned;
3266
3404
  }
3267
3405
  function cloneSet(set, depth, references, flat) {
3268
- if (depth >= MAX_CLONE_DEPTH) return set;
3406
+ if (depth >= CLONE_MAX_DEPTH) return set;
3269
3407
  const cloned = /* @__PURE__ */ new Set();
3270
3408
  const values = [...set.values()];
3271
3409
  const { length } = values;
@@ -3274,7 +3412,7 @@ function cloneSet(set, depth, references, flat) {
3274
3412
  return cloned;
3275
3413
  }
3276
3414
  function cloneTypedArray(value, depth, references) {
3277
- if (depth >= MAX_CLONE_DEPTH) return value;
3415
+ if (depth >= CLONE_MAX_DEPTH) return value;
3278
3416
  const cloned = new value.constructor(value);
3279
3417
  references.set(value, cloned);
3280
3418
  return cloned;
@@ -3335,7 +3473,7 @@ function registerCloner(constructor, handler) {
3335
3473
  clone.handlers.register(constructor, handler);
3336
3474
  }
3337
3475
  function tryStructuredClone(value, depth, references) {
3338
- if (depth >= MAX_CLONE_DEPTH) return value;
3476
+ if (depth >= CLONE_MAX_DEPTH) return value;
3339
3477
  try {
3340
3478
  const cloned = structuredClone(value);
3341
3479
  references.set(value, cloned);
@@ -3345,7 +3483,7 @@ function tryStructuredClone(value, depth, references) {
3345
3483
  return value;
3346
3484
  }
3347
3485
  }
3348
- const MAX_CLONE_DEPTH = 100;
3486
+ const CLONE_MAX_DEPTH = 100;
3349
3487
  //#endregion
3350
3488
  //#region src/value/collection.ts
3351
3489
  function inMap(map, value, key) {
@@ -3609,7 +3747,7 @@ function shake(value) {
3609
3747
  //#endregion
3610
3748
  //#region src/value/smush.ts
3611
3749
  function flattenObject(value, depth, smushed, prefix) {
3612
- if (depth >= MAX_DEPTH) return {};
3750
+ if (depth >= SMUSH_MAX_DEPTH) return {};
3613
3751
  if (smushed.has(value)) return smushed.get(value);
3614
3752
  const keys = Object.keys(value);
3615
3753
  const { length } = keys;
@@ -3641,7 +3779,7 @@ function flattenObject(value, depth, smushed, prefix) {
3641
3779
  function smush(value) {
3642
3780
  return typeof value === "object" && value !== null ? flattenObject(value, 0, /* @__PURE__ */ new WeakMap()) : {};
3643
3781
  }
3644
- const MAX_DEPTH = 100;
3782
+ const SMUSH_MAX_DEPTH = 100;
3645
3783
  //#endregion
3646
3784
  //#region src/value/unsmush.ts
3647
3785
  function getKeys(value) {
@@ -3813,6 +3951,142 @@ function transformValue(value, transformer) {
3813
3951
  return value;
3814
3952
  }
3815
3953
  //#endregion
3954
+ //#region src/internal/subscription.ts
3955
+ function addSubscription(subscriptions, subscription, state) {
3956
+ const { key, value } = state.parameters;
3957
+ const { items, values } = subscriptions.state;
3958
+ if (!isKey(key)) {
3959
+ items.any.add(subscription);
3960
+ values.from.any.set(value, subscription);
3961
+ values.to.any.set(subscription, value);
3962
+ return;
3963
+ }
3964
+ /* istanbul ignore if */
3965
+ if (items.keyed == null || values.from.keyed == null || values.to.keyed == null)
3966
+ // istanbul ignore next
3967
+ return;
3968
+ let keyedItems = items.keyed.get(key);
3969
+ if (keyedItems == null) {
3970
+ keyedItems = /* @__PURE__ */ new Set();
3971
+ items.keyed.set(key, keyedItems);
3972
+ }
3973
+ keyedItems.add(subscription);
3974
+ let keyedFrom = values.from.keyed.get(key);
3975
+ if (keyedFrom == null) {
3976
+ keyedFrom = /* @__PURE__ */ new Map();
3977
+ values.from.keyed.set(key, keyedFrom);
3978
+ }
3979
+ keyedFrom.set(value, subscription);
3980
+ let keyedTo = values.to.keyed.get(key);
3981
+ if (keyedTo == null) {
3982
+ keyedTo = /* @__PURE__ */ new Map();
3983
+ values.to.keyed.set(key, keyedTo);
3984
+ }
3985
+ keyedTo.set(subscription, value);
3986
+ }
3987
+ function clearSubscriptions(store) {
3988
+ for (const susbcription of store.values.to.any.keys()) susbcription.unsubscribe();
3989
+ if (store.values.to.keyed != null) for (const values of store.values.to.keyed.values()) for (const susbcription of values.keys()) susbcription.unsubscribe();
3990
+ }
3991
+ function createSubscription(subscriptions, property, parameters) {
3992
+ if (parameters.signal?.aborted ?? false) throw new Error(parameters.signal?.reason);
3993
+ const state = {
3994
+ parameters,
3995
+ active: true
3996
+ };
3997
+ const existing = getExistingSubscription(subscriptions, state);
3998
+ if (existing != null) return [existing, true];
3999
+ if (subscriptions.state.keys != null && isKey(parameters.key) && !subscriptions.state.keys.has(parameters.key)) throw new Error(SUBSCRIPTION_INVALID_KEY);
4000
+ state.aborter = createAborter(parameters.signal, () => unsubscribe(subscriptions, instance, state));
4001
+ const instance = { unsubscribe: () => unsubscribe(subscriptions, instance, state) };
4002
+ Object.defineProperties(instance, {
4003
+ [SUBSCRIPTION_PROPERTY]: { value: true },
4004
+ [property.key]: { value: property.value ?? "subscription" },
4005
+ active: {
4006
+ enumerable: true,
4007
+ get: () => (parameters.isActive?.() ?? true) && state.active
4008
+ }
4009
+ });
4010
+ addSubscription(subscriptions, instance, state);
4011
+ return [Object.freeze(instance), false];
4012
+ }
4013
+ function createSubscriptions(parameters) {
4014
+ const { keys, property } = parameters;
4015
+ const state = {
4016
+ keys,
4017
+ items: {
4018
+ any: /* @__PURE__ */ new Set(),
4019
+ keyed: keys == null ? void 0 : /* @__PURE__ */ new Map()
4020
+ },
4021
+ values: {
4022
+ from: {
4023
+ any: /* @__PURE__ */ new Map(),
4024
+ keyed: keys == null ? void 0 : /* @__PURE__ */ new Map()
4025
+ },
4026
+ to: {
4027
+ any: /* @__PURE__ */ new Map(),
4028
+ keyed: keys == null ? void 0 : /* @__PURE__ */ new Map()
4029
+ }
4030
+ }
4031
+ };
4032
+ const instance = {
4033
+ state,
4034
+ clear: () => clearSubscriptions(state),
4035
+ create: (parameters) => createSubscription(instance, property, parameters)
4036
+ };
4037
+ return instance;
4038
+ }
4039
+ function getExistingSubscription(subscriptions, state) {
4040
+ const { parameters } = state;
4041
+ const { values } = subscriptions.state;
4042
+ return isKey(parameters.key) ? values.from.keyed?.get(parameters.key)?.get(parameters.value) : values.from.any.get(parameters.value);
4043
+ }
4044
+ /**
4045
+ * Is the value a subscription?
4046
+ *
4047
+ * @param value Value to check
4048
+ * @returns `true` if the value is a subscription, otherwise `false`
4049
+ */
4050
+ function isSubscription(value) {
4051
+ return isPlainObject(value) && SUBSCRIPTION_PROPERTY in value && value[SUBSCRIPTION_PROPERTY] === true;
4052
+ }
4053
+ function removeFromStore(items, values, subscription, value, key) {
4054
+ items.delete(subscription);
4055
+ if (key == null) {
4056
+ values.from.any.delete(value);
4057
+ values.to.any.delete(subscription);
4058
+ } else {
4059
+ values.from.keyed?.get(key)?.delete(value);
4060
+ values.to.keyed?.get(key)?.delete(subscription);
4061
+ }
4062
+ }
4063
+ function removeSubscription(subscriptions, subscription, state) {
4064
+ if (!state.active) return;
4065
+ state.aborter = void 0;
4066
+ state.active = false;
4067
+ state.parameters.isActive = void 0;
4068
+ state.parameters.signal = void 0;
4069
+ const { key, value } = state.parameters;
4070
+ const { items, values } = subscriptions.state;
4071
+ if (!isKey(key)) {
4072
+ removeFromStore(items.any, values, subscription, value);
4073
+ return;
4074
+ }
4075
+ const keyed = items.keyed?.get(key);
4076
+ /* istanbul ignore if */
4077
+ if (items.keyed == null || keyed == null)
4078
+ // istanbul ignore next
4079
+ return;
4080
+ removeFromStore(keyed, values, subscription, value, key);
4081
+ if (keyed.size === 0) items.keyed.delete(key);
4082
+ }
4083
+ function unsubscribe(subscriptions, subscription, state) {
4084
+ state.aborter?.cancel();
4085
+ removeSubscription(subscriptions, subscription, state);
4086
+ }
4087
+ const SUBSCRIPTION_INVALID_KEY = "Invalid key for subscription";
4088
+ const SUBSCRIPTION_PROPERTY = "$subscription";
4089
+ //#endregion
3816
4090
  //#region src/beacon.ts
3817
4091
  /**
3818
4092
  * Create a new beacon
@@ -3827,38 +4101,23 @@ function beacon(value, options) {
3827
4101
  active: true,
3828
4102
  observable: void 0,
3829
4103
  options: getBeaconOptions(options),
3830
- subscriptions: getSubscriptions()
4104
+ subscriptions: createSubscriptions({ property: beaconSubscription })
3831
4105
  };
3832
4106
  const instance = {
3833
- deactivate: () => {
3834
- finishBeacon(state, false);
3835
- },
3836
- emit: (value, finish) => {
3837
- update$1(TYPE_NEXT, state, value, finish);
3838
- },
3839
- error: (value, finish) => {
3840
- update$1(TYPE_ERROR, state, value, finish);
3841
- },
3842
- finish: () => {
3843
- finishBeacon(state, true);
3844
- }
4107
+ deactivate: () => finishBeacon(state, false),
4108
+ emit: (value, finish) => updateBeacon(BEACON_TYPE_NEXT, state, value, finish),
4109
+ error: (value, finish) => updateBeacon(BEACON_TYPE_ERROR, state, value, finish),
4110
+ finish: () => finishBeacon(state, true)
3845
4111
  };
3846
4112
  Object.defineProperties(instance, {
3847
- [KEY_BEACON]: {
3848
- enumerable: false,
3849
- value: NAME_BEACON
3850
- },
4113
+ [BEACON_PROPERTY]: { value: BEACON_NAME },
3851
4114
  active: {
3852
4115
  enumerable: true,
3853
4116
  get: () => state.active
3854
4117
  },
3855
4118
  observable: {
3856
4119
  enumerable: true,
3857
- get: () => {
3858
- if (!state.active) throw new Error(MESSAGE_BEACON);
3859
- state.observable ??= observe(state);
3860
- return state.observable;
3861
- }
4120
+ get: () => getObservable(state)
3862
4121
  },
3863
4122
  value: {
3864
4123
  enumerable: true,
@@ -3870,8 +4129,8 @@ function beacon(value, options) {
3870
4129
  function finishBeacon(state, emit) {
3871
4130
  if (!state.active) return;
3872
4131
  state.active = false;
3873
- for (const [, observer] of state.subscriptions.values.to.any) if (emit) observer.complete?.();
3874
- clearSubscriptions(state.subscriptions);
4132
+ for (const [, observer] of state.subscriptions.state.values.to.any) if (emit) observer.complete?.();
4133
+ state.subscriptions.clear();
3875
4134
  state.observable?.deactivate();
3876
4135
  state.observable = void 0;
3877
4136
  }
@@ -3880,6 +4139,11 @@ function getBeaconOptions(input) {
3880
4139
  options.equal = typeof options.equal === "function" ? options.equal : Object.is;
3881
4140
  return options;
3882
4141
  }
4142
+ function getObservable(state) {
4143
+ if (!state.active) throw new Error(BEACON_MESSAGE_RETRIEVE);
4144
+ state.observable ??= observeBeacon(state);
4145
+ return state.observable;
4146
+ }
3883
4147
  function getObservableCallback(value) {
3884
4148
  return typeof value === "function" ? value : noop;
3885
4149
  }
@@ -3904,10 +4168,19 @@ function getObserver(first, second, third) {
3904
4168
  * @returns `true` if the value is a beacon, otherwise `false`
3905
4169
  */
3906
4170
  function isBeacon(value) {
3907
- return isBeaconInstance(NAME_BEACON, value);
4171
+ return isBeaconInstance(BEACON_NAME, value);
3908
4172
  }
3909
4173
  function isBeaconInstance(name, value) {
3910
- return isPlainObject(value) && value[KEY_BEACON] === name;
4174
+ return isPlainObject(value) && value[BEACON_PROPERTY] === name;
4175
+ }
4176
+ /**
4177
+ * Is the value a beacon subscription?
4178
+ *
4179
+ * @param value Value to check
4180
+ * @returns `true` if the value is a beacon subscription, otherwise `false`
4181
+ */
4182
+ function isBeaconSubscription(value) {
4183
+ return isSubscription(value) && value[BEACON_PROPERTY] === "subscription";
3911
4184
  }
3912
4185
  /**
3913
4186
  * Is the value an observable?
@@ -3916,9 +4189,9 @@ function isBeaconInstance(name, value) {
3916
4189
  * @returns `true` if the value is an observable, otherwise `false`
3917
4190
  */
3918
4191
  function isObservable(value) {
3919
- return isBeaconInstance(NAME_OBSERVABLE, value);
4192
+ return isBeaconInstance(BEACON_OBSERVABLE, value);
3920
4193
  }
3921
- function observe(beacon) {
4194
+ function observeBeacon(beacon) {
3922
4195
  const state = {
3923
4196
  beacon,
3924
4197
  active: beacon.active
@@ -3927,24 +4200,10 @@ function observe(beacon) {
3927
4200
  deactivate: () => {
3928
4201
  state.active = false;
3929
4202
  },
3930
- subscribe(first, second, third) {
3931
- if (!beacon.active || !state.active) throw new Error(MESSAGE_OBSERVABLE);
3932
- const observer = getObserver(first, second, third);
3933
- const subscription = getSubscription({
3934
- isActive: () => beacon.active && state.active,
3935
- property: beaconSubscription,
3936
- subscriptions: beacon.subscriptions,
3937
- value: observer
3938
- });
3939
- observer.next?.(beacon.value);
3940
- return subscription;
3941
- }
4203
+ subscribe: (first, second, third) => subscribeToObservable(state, first, second, third)
3942
4204
  };
3943
4205
  Object.defineProperties(instance, {
3944
- [KEY_BEACON]: {
3945
- enumerable: false,
3946
- value: NAME_OBSERVABLE
3947
- },
4206
+ [BEACON_PROPERTY]: { value: BEACON_OBSERVABLE },
3948
4207
  active: {
3949
4208
  enumerable: true,
3950
4209
  get: () => beacon.active && state.active
@@ -3952,26 +4211,139 @@ function observe(beacon) {
3952
4211
  });
3953
4212
  return Object.freeze(instance);
3954
4213
  }
3955
- function update$1(type, state, value, finish) {
3956
- if (!state.active) return;
3957
- if (type === TYPE_NEXT) {
3958
- if (state.options.equal(state.value, value)) return;
3959
- state.value = value;
3960
- }
3961
- for (const [, observer] of state.subscriptions.values.to.any) observer[type]?.(value);
3962
- if (finish === true) finishBeacon(state, true);
4214
+ function subscribeToObservable(state, first, second, third) {
4215
+ if (!state.beacon.active || !state.active) throw new Error(BEACON_MESSAGE_SUBSCRIBE);
4216
+ const observer = getObserver(first, second, third);
4217
+ const [subscription] = state.beacon.subscriptions.create({
4218
+ isActive: () => state.beacon.active && state.active,
4219
+ value: observer
4220
+ });
4221
+ observer.next?.(state.beacon.value);
4222
+ return subscription;
4223
+ }
4224
+ function updateBeacon(type, state, value, finish) {
4225
+ if (!state.active) return;
4226
+ if (type === BEACON_TYPE_NEXT) {
4227
+ if (state.options.equal(state.value, value)) return;
4228
+ state.value = value;
4229
+ }
4230
+ for (const [, observer] of state.subscriptions.state.values.to.any) observer[type]?.(value);
4231
+ if (finish === true) finishBeacon(state, true);
4232
+ }
4233
+ const BEACON_MESSAGE_RETRIEVE = "Cannot retrieve observable from a closed beacon";
4234
+ const BEACON_MESSAGE_SUBSCRIBE = "Cannot subscribe to a closed observable";
4235
+ const BEACON_PROPERTY = "$beacon";
4236
+ const BEACON_NAME = "beacon";
4237
+ const BEACON_OBSERVABLE = "observable";
4238
+ const BEACON_TYPE_ERROR = "error";
4239
+ const BEACON_TYPE_NEXT = "next";
4240
+ const beaconSubscription = { key: BEACON_PROPERTY };
4241
+ //#endregion
4242
+ //#region src/internal/herald.ts
4243
+ function createEvents(herald, state) {
4244
+ const events = {};
4245
+ Object.defineProperty(events, HERALD_PROPERTY, { value: HERALD_NAME_EVENTS });
4246
+ for (const key of state.keys) events[key] = (callback, signal) => herald.subscribe(key, callback, signal);
4247
+ return Object.freeze(events);
4248
+ }
4249
+ function emitForHerald(state, event, ...parameters) {
4250
+ const items = state.subscriptions.state.values.from.keyed?.get(event);
4251
+ if (items == null || items.size === 0) return;
4252
+ for (const [callback] of items) callback(...parameters);
4253
+ }
4254
+ function getHeraldSubscriptionProperty(input) {
4255
+ if (input == null) return heraldSubscription;
4256
+ const property = isPlainObject(input) ? input : {};
4257
+ if (typeof property.key !== "string" || property.value != null && typeof property.value !== "string") throw new Error(HERALD_MESSAGE_PROPERTY);
4258
+ return {
4259
+ key: property.key,
4260
+ value: property.value
4261
+ };
4262
+ }
4263
+ function getHeraldState(input) {
4264
+ const options = isPlainObject(input) ? input : {};
4265
+ if (!Array.isArray(options.names) || options.names.length === 0 || !options.names.every((name) => typeof name === "string")) throw new Error(HERALD_MESSAGE_ARRAY);
4266
+ if (options.onCreate != null && typeof options.onCreate !== "function") throw new Error(HERALD_MESSAGE_ONCREATE);
4267
+ const keys = new Set(options.names);
4268
+ return {
4269
+ keys,
4270
+ subscriptions: createSubscriptions({
4271
+ keys,
4272
+ property: getHeraldSubscriptionProperty(options.property)
4273
+ }),
4274
+ onCreate: options.onCreate
4275
+ };
4276
+ }
4277
+ /**
4278
+ * Create a _Herald_ for announcing named events
4279
+ *
4280
+ * @param names Event names
4281
+ * @param property Optional property for subscription identification _(defaults to `$herald`)_
4282
+ * @returns _Herald_ instance
4283
+ */
4284
+ function herald(options) {
4285
+ const state = getHeraldState(options);
4286
+ const instance = {
4287
+ clear: () => state.subscriptions.clear(),
4288
+ emit: (event, ...parameters) => emitForHerald(state, event, ...parameters),
4289
+ observed: (event) => (state.subscriptions.state.items.keyed?.get(event)?.size ?? 0) > 0,
4290
+ subscribe: (key, callback, signal) => subscribeToHerald(state, key, callback, signal)
4291
+ };
4292
+ Object.defineProperties(instance, {
4293
+ [HERALD_PROPERTY]: { value: HERALD_NAME_HERALD },
4294
+ events: {
4295
+ enumerable: true,
4296
+ value: createEvents(instance, state)
4297
+ }
4298
+ });
4299
+ return Object.freeze(instance);
4300
+ }
4301
+ /**
4302
+ * Is the value a herald?
4303
+ *
4304
+ * @param value Value to check
4305
+ * @returns `true` if the value is a herald, otherwise `false`
4306
+ */
4307
+ function isHerald(value) {
4308
+ return isHeraldInstance(HERALD_NAME_HERALD, value);
4309
+ }
4310
+ /**
4311
+ * Is the value events for a herald?
4312
+ *
4313
+ * @param value Value to check
4314
+ * @returns `true` if the value is events for a herald, otherwise `false`
4315
+ */
4316
+ function isHeraldEvents(value) {
4317
+ return isHeraldInstance(HERALD_NAME_EVENTS, value);
3963
4318
  }
3964
- const KEY_BEACON = "$beacon";
3965
- const MESSAGE_BEACON = "Cannot retrieve observable from a closed beacon";
3966
- const MESSAGE_OBSERVABLE = "Cannot subscribe to a closed observable";
3967
- const NAME_BEACON = "beacon";
3968
- const NAME_OBSERVABLE = "observable";
3969
- const TYPE_ERROR = "error";
3970
- const TYPE_NEXT = "next";
3971
- const beaconSubscription = {
3972
- key: KEY_BEACON,
3973
- value: "subscription"
3974
- };
4319
+ function isHeraldInstance(name, value) {
4320
+ return isPlainObject(value) && HERALD_PROPERTY in value && value[HERALD_PROPERTY] === name;
4321
+ }
4322
+ /**
4323
+ * Is the value a herald subscription?
4324
+ *
4325
+ * @param value Value to check
4326
+ * @returns `true` if the value is a herald subscription, otherwise `false`
4327
+ */
4328
+ function isHeraldSubscription(value) {
4329
+ return isSubscription(value) && value[HERALD_PROPERTY] === "subscription";
4330
+ }
4331
+ function subscribeToHerald(state, key, callback, signal) {
4332
+ const [subscription, existing] = state.subscriptions.create({
4333
+ key,
4334
+ signal,
4335
+ value: callback
4336
+ });
4337
+ if (!existing) state.onCreate?.(key, callback, subscription);
4338
+ return subscription;
4339
+ }
4340
+ const HERALD_PROPERTY = "$herald";
4341
+ const HERALD_MESSAGE_ARRAY = "Herald requires an array of event names.";
4342
+ const HERALD_MESSAGE_ONCREATE = `Herald requires a valid onCreate callback for subscription creation`;
4343
+ const HERALD_MESSAGE_PROPERTY = `Herald requires valid property information for subscription identification`;
4344
+ const HERALD_NAME_EVENTS = "events";
4345
+ const HERALD_NAME_HERALD = "herald";
4346
+ const heraldSubscription = { key: HERALD_PROPERTY };
3975
4347
  //#endregion
3976
4348
  //#region src/color/constants.ts
3977
4349
  const COLOR_ALPHA = {
@@ -4042,10 +4414,7 @@ const COLOR_MAX = {
4042
4414
  hex: 255,
4043
4415
  percent: 100
4044
4416
  };
4045
- const COLOR_PROPERTY = {
4046
- name: "$color",
4047
- subscription: "subscription"
4048
- };
4417
+ const COLOR_PROPERTY = { name: "$color" };
4049
4418
  const COLOR_TYPE = {
4050
4419
  all: void 0,
4051
4420
  hex: "hex",
@@ -4055,7 +4424,8 @@ const COLOR_TYPE = {
4055
4424
  hwb: "hwb",
4056
4425
  hwba: "hwba",
4057
4426
  rgb: "rgb",
4058
- rgba: "rgba"
4427
+ rgba: "rgba",
4428
+ wildcard: "*"
4059
4429
  };
4060
4430
  COLOR_TYPE.all = /* @__PURE__ */ new Set([
4061
4431
  COLOR_ALPHA.name,
@@ -4967,7 +5337,7 @@ function getDefaultColorState() {
4967
5337
  origin: COLOR_TYPE.hex
4968
5338
  };
4969
5339
  }
4970
- function setColorValue(color, state, subscriptions, type, value, alpha) {
5340
+ function setColorValue(color, state, changes, type, value, alpha) {
4971
5341
  state.hex = void 0;
4972
5342
  state.hsl = void 0;
4973
5343
  state.hwb = void 0;
@@ -4975,36 +5345,33 @@ function setColorValue(color, state, subscriptions, type, value, alpha) {
4975
5345
  state.origin = type;
4976
5346
  state[type] = value;
4977
5347
  if (alpha != null) state.alpha = getAlpha(alpha, type === COLOR_TYPE.hex);
4978
- for (const type of COLOR_TYPE.all) {
4979
- const callbacks = subscriptions.values.to.keyed?.get(type);
4980
- if (callbacks != null) for (const callback of callbacks.values()) callback(color[type]);
4981
- }
4982
- for (const callback of subscriptions.values.to.any.values()) callback(color);
5348
+ for (const type of COLOR_TYPE.all) if (changes.observed(type)) changes.emit(type, color[type]);
5349
+ changes.emit(COLOR_TYPE.wildcard, color);
4983
5350
  }
4984
- function setHexColor(color, state, subscriptions, value, alpha) {
5351
+ function setHexColor(color, state, changes, value, alpha) {
4985
5352
  if (!isHexColor(value) || !alpha && value === state.hex) return;
4986
5353
  const normalized = getNormalizedHex(value, true);
4987
- setColorValue(color, state, subscriptions, COLOR_TYPE.hex, normalized.slice(0, COLOR_LENGTHS.hexLong), alpha ? normalized.slice(COLOR_LENGTHS.hexLong) : void 0);
5354
+ setColorValue(color, state, changes, COLOR_TYPE.hex, normalized.slice(0, COLOR_LENGTHS.hexLong), alpha ? normalized.slice(COLOR_LENGTHS.hexLong) : void 0);
4988
5355
  }
4989
- function setHSLColor(color, state, subscriptions, value, alpha) {
5356
+ function setHSLColor(color, state, changes, value, alpha) {
4990
5357
  if (!isHslLike(value)) return;
4991
- setColorValue(color, state, subscriptions, COLOR_TYPE.hsl, {
5358
+ setColorValue(color, state, changes, COLOR_TYPE.hsl, {
4992
5359
  hue: getDegrees(value.hue),
4993
5360
  saturation: getPercentage(value.saturation),
4994
5361
  lightness: getPercentage(value.lightness)
4995
5362
  }, alpha ? value.alpha : void 0);
4996
5363
  }
4997
- function setHWBColor(color, state, subscriptions, value, alpha) {
5364
+ function setHWBColor(color, state, changes, value, alpha) {
4998
5365
  if (!isHwbLike(value)) return;
4999
- setColorValue(color, state, subscriptions, COLOR_TYPE.hwb, {
5366
+ setColorValue(color, state, changes, COLOR_TYPE.hwb, {
5000
5367
  hue: getDegrees(value.hue),
5001
5368
  whiteness: getPercentage(value.whiteness),
5002
5369
  blackness: getPercentage(value.blackness)
5003
5370
  }, alpha ? value.alpha : void 0);
5004
5371
  }
5005
- function setRGBColor(color, state, subscriptions, value, alpha) {
5372
+ function setRGBColor(color, state, changes, value, alpha) {
5006
5373
  if (!isRgbLike(value)) return;
5007
- setColorValue(color, state, subscriptions, COLOR_TYPE.rgb, {
5374
+ setColorValue(color, state, changes, COLOR_TYPE.rgb, {
5008
5375
  red: getHexValue(value.red),
5009
5376
  green: getHexValue(value.green),
5010
5377
  blue: getHexValue(value.blue)
@@ -5018,6 +5385,9 @@ const getters = {
5018
5385
  };
5019
5386
  //#endregion
5020
5387
  //#region src/color/misc/format.ts
5388
+ function formatHexColor(color, alpha) {
5389
+ return `#${alpha === true ? color.hexa : color.hex}`;
5390
+ }
5021
5391
  function formatHslColor(state, alpha) {
5022
5392
  const { hue, lightness, saturation } = getColorFromState(state, COLOR_TYPE.hsl);
5023
5393
  return `hsl(${hue}deg ${saturation}% ${lightness}%${getSuffix(state, alpha)})`;
@@ -5036,51 +5406,56 @@ function getSuffix(state, alpha) {
5036
5406
  //#endregion
5037
5407
  //#region src/color/instance.ts
5038
5408
  function color(value) {
5409
+ const changes = herald({
5410
+ names: [COLOR_TYPE.wildcard, ...COLOR_TYPE.all],
5411
+ property: colorSubscription,
5412
+ onCreate: (event, callback) => onCreateSubscription(instance, event, callback)
5413
+ });
5039
5414
  const state = getColorState(value);
5040
- const subscriptions = getSubscriptions(COLOR_TYPE.all);
5041
5415
  const instance = {
5042
- subscribe: (first, second) => subscribeToColor(subscriptions, first, second),
5043
- toHexString: (alpha) => `#${alpha === true ? instance.hexa : instance.hex}`,
5416
+ subscribe: (callback, signal) => changes.subscribe(COLOR_TYPE.wildcard, callback, signal),
5417
+ toHexString: (alpha) => formatHexColor(instance, alpha),
5044
5418
  toHslString: (alpha) => formatHslColor(state, alpha),
5045
5419
  toHwbString: (alpha) => formatHwbColor(state, alpha),
5046
5420
  toRgbString: (alpha) => formatRgbColor(state, alpha),
5047
5421
  toString: () => instance.toHexString(),
5048
- unsubscribe: () => clearSubscriptions(subscriptions)
5422
+ unsubscribe: () => changes.clear()
5049
5423
  };
5050
5424
  Object.defineProperties(instance, {
5051
- [COLOR_PROPERTY.name]: {
5052
- enumerable: false,
5053
- value: true
5054
- },
5425
+ [COLOR_PROPERTY.name]: { value: true },
5055
5426
  alpha: {
5056
5427
  enumerable: true,
5057
5428
  get: () => state.alpha.value,
5058
5429
  set: (value) => setAlphaValue(state, value)
5059
5430
  },
5060
- hex: getProperty(COLOR_TYPE.hex, instance, state, subscriptions, false),
5061
- hexa: getProperty(COLOR_TYPE.hex, instance, state, subscriptions, true),
5062
- hsl: getProperty(COLOR_TYPE.hsl, instance, state, subscriptions, false),
5063
- hsla: getProperty(COLOR_TYPE.hsl, instance, state, subscriptions, true),
5064
- hwb: getProperty(COLOR_TYPE.hwb, instance, state, subscriptions, false),
5065
- hwba: getProperty(COLOR_TYPE.hwb, instance, state, subscriptions, true),
5431
+ changes: {
5432
+ enumerable: true,
5433
+ value: changes.events
5434
+ },
5435
+ hex: getColorProperty(COLOR_TYPE.hex, instance, state, changes, false),
5436
+ hexa: getColorProperty(COLOR_TYPE.hex, instance, state, changes, true),
5437
+ hsl: getColorProperty(COLOR_TYPE.hsl, instance, state, changes, false),
5438
+ hsla: getColorProperty(COLOR_TYPE.hsl, instance, state, changes, true),
5439
+ hwb: getColorProperty(COLOR_TYPE.hwb, instance, state, changes, false),
5440
+ hwba: getColorProperty(COLOR_TYPE.hwb, instance, state, changes, true),
5066
5441
  origin: {
5067
5442
  enumerable: true,
5068
5443
  get: () => state.origin
5069
5444
  },
5070
- rgb: getProperty(COLOR_TYPE.rgb, instance, state, subscriptions, false),
5071
- rgba: getProperty(COLOR_TYPE.rgb, instance, state, subscriptions, true)
5445
+ rgb: getColorProperty(COLOR_TYPE.rgb, instance, state, changes, false),
5446
+ rgba: getColorProperty(COLOR_TYPE.rgb, instance, state, changes, true)
5072
5447
  });
5073
5448
  return Object.freeze(instance);
5074
5449
  }
5075
- function getProperty(space, color, state, subscriptions, alpha) {
5450
+ function getColorProperty(space, color, state, changes, alpha) {
5076
5451
  const setValue = setters[space];
5077
5452
  return {
5078
5453
  enumerable: true,
5079
- get: () => getValue$1(space, state, alpha),
5080
- set: (value) => setValue(color, state, subscriptions, value, alpha)
5454
+ get: () => getColorValue(space, state, alpha),
5455
+ set: (value) => setValue(color, state, changes, value, alpha)
5081
5456
  };
5082
5457
  }
5083
- function getValue$1(space, state, alpha) {
5458
+ function getColorValue(space, state, alpha) {
5084
5459
  const value = getColorFromState(state, space);
5085
5460
  if (typeof value === "string") return alpha ? `${value}${state.alpha.hex}` : value;
5086
5461
  return alpha ? {
@@ -5088,28 +5463,16 @@ function getValue$1(space, state, alpha) {
5088
5463
  alpha: state.alpha.value
5089
5464
  } : { ...value };
5090
5465
  }
5466
+ function onCreateSubscription(instance, event, callback) {
5467
+ let value;
5468
+ if (event === COLOR_TYPE.wildcard) value = instance;
5469
+ else value = instance[event];
5470
+ callback(value);
5471
+ }
5091
5472
  function setAlphaValue(state, value) {
5092
5473
  if (typeof value === "number" && !Number.isNaN(value)) state.alpha = getAlpha(value, false);
5093
5474
  }
5094
- function subscribeToColor(subscriptions, first, second) {
5095
- let key;
5096
- let value;
5097
- if (typeof first === "string") {
5098
- key = first;
5099
- value = second;
5100
- } else if (typeof first === "function") value = first;
5101
- if (typeof value !== "function") throw new Error();
5102
- return getSubscription({
5103
- key,
5104
- subscriptions,
5105
- value,
5106
- property: colorSubscription
5107
- });
5108
- }
5109
- const colorSubscription = {
5110
- key: COLOR_PROPERTY.name,
5111
- value: COLOR_PROPERTY.subscription
5112
- };
5475
+ const colorSubscription = { key: COLOR_PROPERTY.name };
5113
5476
  const setters = {
5114
5477
  hex: setHexColor,
5115
5478
  hsl: setHSLColor,
@@ -5252,13 +5615,13 @@ const EXPRESSION_WHITESPACE = /^\s*$/;
5252
5615
  //#endregion
5253
5616
  //#region src/logger.ts
5254
5617
  function isLogger(value) {
5255
- return isLoggerInstance(NAME_LOGGER, value);
5618
+ return isLoggerInstance(LOGGER_NAME, value);
5256
5619
  }
5257
5620
  function isLoggerInstance(name, value) {
5258
- return typeof value === "object" && value !== null && value[KEY_LOGGER] === name;
5621
+ return typeof value === "object" && value !== null && value[LOGGER_PROPERTY] === name;
5259
5622
  }
5260
5623
  function isTimedLogger(value) {
5261
- return isLoggerInstance(NAME_TIMED, value);
5624
+ return isLoggerInstance(LOGGER_NAME_TIMED, value);
5262
5625
  }
5263
5626
  function timedLogger(label) {
5264
5627
  function stop() {
@@ -5277,35 +5640,20 @@ function timedLogger(label) {
5277
5640
  };
5278
5641
  const instance = {};
5279
5642
  Object.defineProperties(instance, {
5280
- [KEY_LOGGER]: {
5281
- enumerable: false,
5282
- value: NAME_TIMED
5283
- },
5643
+ [LOGGER_PROPERTY]: { value: LOGGER_NAME_TIMED },
5284
5644
  active: {
5285
5645
  enumerable: true,
5286
- get() {
5287
- return state.started && !state.stopped && enabled;
5288
- }
5289
- },
5290
- log: {
5291
- enumerable: true,
5292
- get() {
5293
- return this.active ? logger : noop;
5294
- }
5646
+ get: () => state.started && !state.stopped && enabled
5295
5647
  },
5296
- stop: {
5297
- enumerable: true,
5298
- get() {
5299
- return instance.active ? stop() : noop;
5300
- }
5301
- }
5648
+ log: { get: () => instance.active ? logger : noop },
5649
+ stop: { get: () => instance.active ? stop() : noop }
5302
5650
  });
5303
5651
  if (state.started) console.time(label);
5304
5652
  return Object.freeze(instance);
5305
5653
  }
5306
- const KEY_LOGGER = "$logger";
5307
- const NAME_LOGGER = "Logger";
5308
- const NAME_TIMED = "TimedLogger";
5654
+ const LOGGER_NAME = "Logger";
5655
+ const LOGGER_NAME_TIMED = "TimedLogger";
5656
+ const LOGGER_PROPERTY = "$logger";
5309
5657
  const methods = [
5310
5658
  "debug",
5311
5659
  "dir",
@@ -5324,349 +5672,84 @@ const methods = [
5324
5672
  const Logger = (() => {
5325
5673
  const instance = {};
5326
5674
  Object.defineProperties(instance, {
5327
- [KEY_LOGGER]: {
5328
- enumerable: false,
5329
- value: NAME_LOGGER
5330
- },
5675
+ [LOGGER_PROPERTY]: { value: LOGGER_NAME },
5331
5676
  enabled: {
5332
5677
  enumerable: true,
5333
- get() {
5334
- return enabled;
5335
- },
5336
- set(value) {
5678
+ get: () => enabled,
5679
+ set: (value) => {
5337
5680
  enabled = typeof value === "boolean" ? value : enabled;
5338
5681
  }
5339
5682
  },
5340
- time: {
5341
- enumerable: true,
5342
- value(label) {
5343
- return timedLogger(label);
5344
- }
5345
- }
5346
- });
5347
- for (const method of methods) Object.defineProperty(instance, method, {
5348
- enumerable: true,
5349
- get() {
5350
- return enabled ? console[method].bind(console) : noop;
5351
- }
5683
+ time: { value: (label) => timedLogger(getString(label)) }
5352
5684
  });
5353
- return Object.freeze(instance);
5354
- })();
5355
- let enabled = true;
5356
- //#endregion
5357
- //#region src/math.ts
5358
- function average(array, key) {
5359
- const aggregated = aggregate(AGGREGATION_AVERAGE, array, key);
5360
- return aggregated.count > 0 ? aggregated.value / aggregated.count : NaN;
5361
- }
5362
- /**
5363
- * Round a number up
5364
- *
5365
- * @param value Number to round up
5366
- * @param decimals Number of decimal places to round to _(defaults to `0`)_
5367
- * @returns Rounded number, or `Number.NaN` if the value if unable to be rounded
5368
- */
5369
- function ceil(value, decimals) {
5370
- return roundNumber(Math.ceil, value, decimals);
5371
- }
5372
- function count(array, key, value) {
5373
- if (!Array.isArray(array)) return NaN;
5374
- const { length } = array;
5375
- const callback = getAggregateCallback(key);
5376
- if (callback == null) return length;
5377
- let counted = 0;
5378
- for (let index = 0; index < length; index += 1) {
5379
- const item = array[index];
5380
- if (Object.is(callback(item, index, array), value)) counted += 1;
5381
- }
5382
- return counted;
5383
- }
5384
- /**
5385
- * Round a number down
5386
- *
5387
- * @param value Number to round down
5388
- * @param decimals Number of decimal places to round to _(defaults to `0`)_
5389
- * @returns Rounded number, or `Number.NaN` if the value if unable to be rounded
5390
- */
5391
- function floor(value, decimals) {
5392
- return roundNumber(Math.floor, value, decimals);
5393
- }
5394
- function median(array, key) {
5395
- let length = Array.isArray(array) ? array.length : 0;
5396
- if (!Array.isArray(array) || length === 0) return NaN;
5397
- let values = array;
5398
- const callback = getAggregateCallback(key);
5399
- if (callback != null) values = array.map((item, index) => callback(item, index, array));
5400
- const numbers = values.filter(isNumber).sort((first, second) => first - second);
5401
- length = numbers.length;
5402
- if (length === 1) return numbers[0];
5403
- if (length % 2 === 0) {
5404
- const first = length / 2 - 1;
5405
- const second = length / 2;
5406
- return (numbers[first] + numbers[second]) / 2;
5407
- }
5408
- return numbers[Math.floor(length / 2)];
5409
- }
5410
- function min(array, key) {
5411
- return getAggregated("min", array, key);
5412
- }
5413
- function sum(array, key) {
5414
- return getAggregated("sum", array, key);
5415
- }
5416
- //#endregion
5417
- //#region src/promise/models.ts
5418
- /**
5419
- * A _Promise_ that can be canceled
5420
- */
5421
- var CancelablePromise = class extends Promise {
5422
- #rejector;
5423
- constructor(executor) {
5424
- let rejector;
5425
- super((resolve, reject) => {
5426
- rejector = reject;
5427
- executor(resolve, reject);
5428
- });
5429
- this.#rejector = rejector;
5430
- }
5431
- /**
5432
- * Cancel the _Promise_, rejecting it with an optional reason
5433
- *
5434
- * @param reason Optional reason for canceling the _Promise_
5435
- */
5436
- cancel(reason) {
5437
- this.#rejector(reason);
5438
- }
5439
- };
5440
- /**
5441
- * An error thrown when a promise times out
5442
- */
5443
- var PromiseTimeoutError = class extends Error {
5444
- constructor() {
5445
- super(PROMISE_MESSAGE_TIMEOUT);
5446
- this.name = PROMISE_ERROR_NAME;
5447
- }
5448
- };
5449
- const PROMISE_ABORT_EVENT = "abort";
5450
- const PROMISE_ABORT_OPTIONS = { once: true };
5451
- const PROMISE_ERROR_NAME = "PromiseTimeoutError";
5452
- const PROMISE_MESSAGE_EXPECTATION_ATTEMPT = "Attempt expected a function or a promise";
5453
- const PROMISE_MESSAGE_EXPECTATION_RESULT = "toResult expected a Promise";
5454
- const PROMISE_MESSAGE_EXPECTATION_TIMED = "Timed function expected a Promise";
5455
- const PROMISE_MESSAGE_TIMEOUT = "Promise timed out";
5456
- const PROMISE_STRATEGY_ALL = /* @__PURE__ */ new Set(["complete", "first"]);
5457
- const PROMISE_STRATEGY_DEFAULT = "complete";
5458
- const PROMISE_TYPE_FULFILLED = "fulfilled";
5459
- const PROMISE_TYPE_REJECTED = "rejected";
5460
- //#endregion
5461
- //#region src/promise/helpers.ts
5462
- function getPromiseOptions(input) {
5463
- if (typeof input === "number") return { time: getNumberOrDefault(input, 0) };
5464
- if (input instanceof AbortSignal) return {
5465
- signal: input,
5466
- time: 0
5467
- };
5468
- const options = typeof input === "object" && input !== null ? input : {};
5469
- return {
5470
- signal: options.signal instanceof AbortSignal ? options.signal : void 0,
5471
- time: getNumberOrDefault(options.time, 0)
5472
- };
5473
- }
5474
- function getPromisesOptions(input) {
5475
- if (typeof input === "string") return { strategy: getStrategyOrDefault(input) };
5476
- if (input instanceof AbortSignal) return {
5477
- signal: input,
5478
- strategy: PROMISE_STRATEGY_DEFAULT
5479
- };
5480
- const options = typeof input === "object" && input !== null ? input : {};
5481
- return {
5482
- signal: options.signal instanceof AbortSignal ? options.signal : void 0,
5483
- strategy: getStrategyOrDefault(options.strategy)
5484
- };
5485
- }
5486
- function getResultsFromPromises(promised) {
5487
- return promised.map((result) => isFulfilled(result) ? ok(result.value) : error(result.reason));
5488
- }
5489
- function getStrategyOrDefault(value) {
5490
- return PROMISE_STRATEGY_ALL.has(value) ? value : PROMISE_STRATEGY_DEFAULT;
5491
- }
5492
- /**
5493
- * Is the value a fulfilled _Promise_ result?
5494
- *
5495
- * @param value Value to check
5496
- * @returns `true` if the value is a fulfilled _Promise_ result, otherwise `false`
5497
- */
5498
- function isFulfilled(value) {
5499
- return isType(value, PROMISE_TYPE_FULFILLED);
5500
- }
5501
- /**
5502
- * Is the value a rejected _Promise_ result?
5503
- *
5504
- * @param value Value to check
5505
- * @returns `true` if the value is a rejected _Promise_ result, otherwise `false`
5506
- */
5507
- function isRejected(value) {
5508
- return isType(value, PROMISE_TYPE_REJECTED);
5509
- }
5510
- function isType(value, type) {
5511
- return typeof value === "object" && value !== null && value.status === type;
5512
- }
5513
- //#endregion
5514
- //#region src/promise/misc.ts
5515
- /**
5516
- * Create a cancelable _Promise_
5517
- *
5518
- * @param executor Executor function for the _Promise_
5519
- * @returns Cancelable _Promise_
5520
- */
5521
- function cancelable(executor) {
5522
- return new CancelablePromise(executor);
5523
- }
5524
- function handleResult(status, parameters) {
5525
- const { abort, complete, data, handlers, index, signal, value } = parameters;
5526
- if (signal?.aborted ?? false) return;
5527
- if (!complete && status === "rejected") {
5528
- settlePromise(abort, handlers.reject, value, signal);
5529
- return;
5530
- }
5531
- data.result[index] = !complete ? value : status === "fulfilled" ? {
5532
- status,
5533
- value
5534
- } : {
5535
- status,
5536
- reason: value
5537
- };
5538
- if (index === data.last) settlePromise(abort, handlers.resolve, data.result, signal);
5539
- }
5540
- function settlePromise(aborter, settler, value, signal) {
5541
- signal?.removeEventListener(PROMISE_ABORT_EVENT, aborter);
5542
- settler(value);
5543
- }
5544
- async function toResult(value) {
5545
- const actual = typeof value === "function" ? value() : value;
5546
- if (!(actual instanceof Promise)) return Promise.reject(/* @__PURE__ */ new TypeError(PROMISE_MESSAGE_EXPECTATION_RESULT));
5547
- return actual.then((result) => ok(result)).catch((reason) => error(reason));
5548
- }
5549
- //#endregion
5550
- //#region src/promise/delay.ts
5551
- function delay(options) {
5552
- const { signal, time } = getPromiseOptions(options);
5553
- if (signal?.aborted ?? false) return Promise.reject(signal.reason);
5554
- function abort() {
5555
- timer.cancel();
5556
- rejector(signal.reason);
5557
- }
5558
- const timer = getTimer(TIMER_WAIT, () => {
5559
- settlePromise(abort, resolver, void 0, signal);
5560
- }, time);
5561
- signal?.addEventListener(PROMISE_ABORT_EVENT, abort, PROMISE_ABORT_OPTIONS);
5562
- let rejector;
5563
- let resolver;
5564
- return new Promise((resolve, reject) => {
5565
- rejector = reject;
5566
- resolver = resolve;
5567
- if (time === 0) settlePromise(abort, resolve, void 0, signal);
5568
- else timer();
5685
+ for (const method of methods) Object.defineProperty(instance, method, {
5686
+ enumerable: true,
5687
+ get() {
5688
+ return enabled ? console[method].bind(console) : noop;
5689
+ }
5569
5690
  });
5570
- }
5691
+ return Object.freeze(instance);
5692
+ })();
5693
+ let enabled = true;
5571
5694
  //#endregion
5572
- //#region src/promise/timed.ts
5573
- async function getTimedPromise(promise, time, signal) {
5574
- function abort() {
5575
- timer.cancel();
5576
- rejector(signal.reason);
5577
- }
5578
- signal?.addEventListener(PROMISE_ABORT_EVENT, abort, PROMISE_ABORT_OPTIONS);
5579
- const timer = getTimer(TIMER_WAIT, () => {
5580
- settlePromise(abort, rejector, new PromiseTimeoutError(), signal);
5581
- }, time);
5582
- let rejector;
5583
- return Promise.race([promise, new Promise((_, reject) => {
5584
- rejector = reject;
5585
- timer();
5586
- })]).then((value) => {
5587
- timer.cancel();
5588
- rejector(void 0);
5589
- signal?.removeEventListener(PROMISE_ABORT_EVENT, abort);
5590
- return value;
5591
- });
5695
+ //#region src/math.ts
5696
+ function average(array, key) {
5697
+ const aggregated = aggregate(AGGREGATION_AVERAGE, array, key);
5698
+ return aggregated.count > 0 ? aggregated.value / aggregated.count : NaN;
5592
5699
  }
5593
- async function timed(promise, options) {
5594
- if (!(promise instanceof Promise)) return Promise.reject(/* @__PURE__ */ new TypeError(PROMISE_MESSAGE_EXPECTATION_TIMED));
5595
- const { signal, time } = getPromiseOptions(options);
5596
- if (signal?.aborted ?? false) return Promise.reject(signal.reason);
5597
- return time > 0 ? getTimedPromise(promise, time, signal) : promise;
5700
+ /**
5701
+ * Round a number up
5702
+ *
5703
+ * @param value Number to round up
5704
+ * @param decimals Number of decimal places to round to _(defaults to `0`)_
5705
+ * @returns Rounded number, or `Number.NaN` if the value if unable to be rounded
5706
+ */
5707
+ function ceil(value, decimals) {
5708
+ return roundNumber(Math.ceil, value, decimals);
5598
5709
  }
5599
- //#endregion
5600
- //#region src/promise/index.ts
5601
- async function attemptPromise(value, options) {
5602
- const isFunction = typeof value === "function";
5603
- if (!isFunction && !(value instanceof Promise)) return Promise.reject(/* @__PURE__ */ new TypeError(PROMISE_MESSAGE_EXPECTATION_ATTEMPT));
5604
- const { signal, time } = getPromiseOptions(options);
5605
- if (signal?.aborted ?? false) return Promise.reject(signal.reason);
5606
- function abort() {
5607
- rejector(signal.reason);
5608
- }
5609
- async function handler(resolve, reject) {
5610
- try {
5611
- let result = isFunction ? value() : await value;
5612
- if (result instanceof Promise) result = await result;
5613
- settlePromise(abort, resolve, result, signal);
5614
- } catch (error) {
5615
- settlePromise(abort, reject, error, signal);
5616
- }
5710
+ function count(array, key, value) {
5711
+ if (!Array.isArray(array)) return NaN;
5712
+ const { length } = array;
5713
+ const callback = getAggregateCallback(key);
5714
+ if (callback == null) return length;
5715
+ let counted = 0;
5716
+ for (let index = 0; index < length; index += 1) {
5717
+ const item = array[index];
5718
+ if (Object.is(callback(item, index, array), value)) counted += 1;
5617
5719
  }
5618
- let rejector;
5619
- signal?.addEventListener(PROMISE_ABORT_EVENT, abort, PROMISE_ABORT_OPTIONS);
5620
- const promise = new Promise((resolve, reject) => {
5621
- rejector = reject;
5622
- handler(resolve, reject);
5623
- });
5624
- return time > 0 ? getTimedPromise(promise, time, signal) : promise;
5720
+ return counted;
5625
5721
  }
5626
- async function promises(items, options) {
5627
- const { signal, strategy } = getPromisesOptions(options);
5628
- if (signal?.aborted ?? false) return Promise.reject(signal.reason);
5629
- if (!Array.isArray(items)) return Promise.resolve([]);
5630
- const actual = items.map((item) => typeof item === "function" ? item() : item).filter((item) => item instanceof Promise);
5631
- const { length } = actual;
5632
- if (length === 0) return Promise.resolve([]);
5633
- const complete = strategy === PROMISE_STRATEGY_DEFAULT;
5634
- function abort() {
5635
- handlers.reject(signal.reason);
5722
+ /**
5723
+ * Round a number down
5724
+ *
5725
+ * @param value Number to round down
5726
+ * @param decimals Number of decimal places to round to _(defaults to `0`)_
5727
+ * @returns Rounded number, or `Number.NaN` if the value if unable to be rounded
5728
+ */
5729
+ function floor(value, decimals) {
5730
+ return roundNumber(Math.floor, value, decimals);
5731
+ }
5732
+ function median(array, key) {
5733
+ let length = Array.isArray(array) ? array.length : 0;
5734
+ if (!Array.isArray(array) || length === 0) return NaN;
5735
+ let values = array;
5736
+ const callback = getAggregateCallback(key);
5737
+ if (callback != null) values = array.map((item, index) => callback(item, index, array));
5738
+ const numbers = values.filter(isNumber).sort((first, second) => first - second);
5739
+ length = numbers.length;
5740
+ if (length === 1) return numbers[0];
5741
+ if (length % 2 === 0) {
5742
+ const first = length / 2 - 1;
5743
+ const second = length / 2;
5744
+ return (numbers[first] + numbers[second]) / 2;
5636
5745
  }
5637
- signal?.addEventListener(PROMISE_ABORT_EVENT, abort, PROMISE_ABORT_OPTIONS);
5638
- const data = {
5639
- last: length - 1,
5640
- result: []
5641
- };
5642
- let handlers;
5643
- return new Promise((resolve, reject) => {
5644
- handlers = {
5645
- reject,
5646
- resolve
5647
- };
5648
- for (let index = 0; index < length; index += 1) actual[index].then((value) => handleResult(PROMISE_TYPE_FULFILLED, {
5649
- abort,
5650
- complete,
5651
- data,
5652
- handlers,
5653
- index,
5654
- signal,
5655
- value
5656
- })).catch((reason) => handleResult(PROMISE_TYPE_REJECTED, {
5657
- abort,
5658
- complete,
5659
- data,
5660
- handlers,
5661
- index,
5662
- signal,
5663
- value: reason
5664
- }));
5665
- });
5746
+ return numbers[Math.floor(length / 2)];
5666
5747
  }
5667
- promises.result = resultPromises;
5668
- async function resultPromises(items, signal) {
5669
- return promises(items, signal).then(getResultsFromPromises);
5748
+ function min(array, key) {
5749
+ return getAggregated("min", array, key);
5750
+ }
5751
+ function sum(array, key) {
5752
+ return getAggregated("sum", array, key);
5670
5753
  }
5671
5754
  //#endregion
5672
5755
  //#region src/query.ts
@@ -5678,15 +5761,15 @@ async function resultPromises(items, signal) {
5678
5761
  */
5679
5762
  function fromQuery(query) {
5680
5763
  if (typeof query !== "string" || query.trim().length === 0) return {};
5681
- const parts = query.split(AMPERSAND).map((part) => part.split(EQUAL).map(tryDecode)).sort(([first], [second]) => first.localeCompare(second));
5764
+ const parts = query.split(QUERY_AMPERSAND).map((part) => part.split(QUERY_EQUAL).map(tryDecode)).sort(([first], [second]) => first.localeCompare(second));
5682
5765
  const { length } = parts;
5683
5766
  const parameters = {};
5684
5767
  let position = 0;
5685
5768
  let array;
5686
5769
  for (let index = 0; index < length; index += 1) {
5687
5770
  const [key, value] = parts[index];
5688
- if (EXPRESSION_ARRAY_SUFFIX.test(key)) {
5689
- const named = key.replace(EXPRESSION_ARRAY_SUFFIX, "");
5771
+ if (QUERY_EXPRESSION_ARRAY_SUFFIX.test(key)) {
5772
+ const named = key.replace(QUERY_EXPRESSION_ARRAY_SUFFIX, "");
5690
5773
  if (named !== array) {
5691
5774
  array = named;
5692
5775
  position = 0;
@@ -5708,9 +5791,9 @@ function getParts(value, fromArray, prefix) {
5708
5791
  for (let index = 0; index < length; index += 1) {
5709
5792
  const key = keys[index];
5710
5793
  const val = value[key];
5711
- const fullKey = join([prefix, fromArray ? void 0 : key], DOT);
5794
+ const fullKey = join([prefix, fromArray ? void 0 : key], QUERY_DOT);
5712
5795
  const encodedKey = getString(tryEncode(fullKey));
5713
- const prefixedKey = fromArray ? join([encodedKey, index], DOT) : encodedKey;
5796
+ const prefixedKey = fromArray ? join([encodedKey, index], QUERY_DOT) : encodedKey;
5714
5797
  if (Array.isArray(val)) parts.push(...getParts(val, true, fullKey));
5715
5798
  else if (isPlainObject(val)) parts.push(...getParts(val, false, fullKey));
5716
5799
  else if (isDecodable(val)) parts.push(`${prefixedKey}=${getString(tryEncode(val))}`);
@@ -5719,7 +5802,7 @@ function getParts(value, fromArray, prefix) {
5719
5802
  return parts;
5720
5803
  }
5721
5804
  function getQueryValue(value) {
5722
- if (EXPRESSION_BOOLEAN.test(value)) return value === TRUE;
5805
+ if (QUERY_EXPRESSION_BOOLEAN.test(value)) return value === QUERY_TRUE;
5723
5806
  const asNumber = getNumber(value);
5724
5807
  if (!Number.isNaN(asNumber)) return asNumber;
5725
5808
  const parsed = Date.parse(value);
@@ -5728,7 +5811,7 @@ function getQueryValue(value) {
5728
5811
  return date.toJSON() === value ? date : value;
5729
5812
  }
5730
5813
  function isDecodable(value) {
5731
- return TYPES.has(typeof value);
5814
+ return QUERY_TYPES.has(typeof value);
5732
5815
  }
5733
5816
  /**
5734
5817
  * Convert a plain _(nested)_ object to a query string
@@ -5737,15 +5820,15 @@ function isDecodable(value) {
5737
5820
  * @returns Query string representation of the object
5738
5821
  */
5739
5822
  function toQuery(parameters) {
5740
- return isPlainObject(parameters) ? join(getParts(parameters, false).filter((part) => part.length > 0), AMPERSAND) : "";
5741
- }
5742
- const AMPERSAND = "&";
5743
- const DOT = ".";
5744
- const EQUAL = "=";
5745
- const EXPRESSION_ARRAY_SUFFIX = /\[\]$/;
5746
- const EXPRESSION_BOOLEAN = /^(false|true)$/;
5747
- const TRUE = "true";
5748
- const TYPES = /* @__PURE__ */ new Set([
5823
+ return isPlainObject(parameters) ? join(getParts(parameters, false).filter((part) => part.length > 0), QUERY_AMPERSAND) : "";
5824
+ }
5825
+ const QUERY_AMPERSAND = "&";
5826
+ const QUERY_DOT = ".";
5827
+ const QUERY_EQUAL = "=";
5828
+ const QUERY_EXPRESSION_ARRAY_SUFFIX = /\[\]$/;
5829
+ const QUERY_EXPRESSION_BOOLEAN = /^(false|true)$/;
5830
+ const QUERY_TRUE = "true";
5831
+ const QUERY_TYPES = /* @__PURE__ */ new Set([
5749
5832
  "boolean",
5750
5833
  "number",
5751
5834
  "string"
@@ -5758,11 +5841,47 @@ const TYPES = /* @__PURE__ */ new Set([
5758
5841
  var QueueError = class extends Error {
5759
5842
  constructor(message) {
5760
5843
  super(message);
5761
- this.name = ERROR_NAME;
5844
+ this.name = QUEUE_ERROR_NAME;
5762
5845
  }
5763
5846
  };
5847
+ function addToQueue(instance, state, parameters, signal) {
5848
+ if (instance.full) throw new QueueError(QUEUE_MESSAGE_MAXIMUM);
5849
+ const abortSignal = signal instanceof AbortSignal ? signal : void 0;
5850
+ if (abortSignal?.aborted ?? false) throw new Error(abortSignal?.reason);
5851
+ const id = identify(state);
5852
+ let rejector;
5853
+ let resolver;
5854
+ const promise = new Promise((resolve, reject) => {
5855
+ rejector = reject;
5856
+ resolver = resolve;
5857
+ });
5858
+ const aborter = createAborter(abortSignal, () => rejector(abortSignal?.reason));
5859
+ state.items.push({
5860
+ aborter,
5861
+ id,
5862
+ parameters,
5863
+ promise,
5864
+ key: state.key,
5865
+ reject: rejector,
5866
+ resolve: resolver
5867
+ });
5868
+ if (state.options.autostart) run(state);
5869
+ return {
5870
+ id,
5871
+ promise
5872
+ };
5873
+ }
5874
+ function clearQueue(state) {
5875
+ const items = state.items.splice(0);
5876
+ const { length } = items;
5877
+ for (let index = 0; index < length; index += 1) {
5878
+ const { aborter, reject } = items[index];
5879
+ aborter?.cancel();
5880
+ reject(new QueueError(QUEUE_MESSAGE_CLEAR));
5881
+ }
5882
+ }
5764
5883
  function createQueue(callback, options, key) {
5765
- if (typeof callback !== "function") throw new TypeError(MESSAGE_CALLBACK);
5884
+ if (typeof callback !== "function") throw new TypeError(QUEUE_MESSAGE_CALLBACK);
5766
5885
  const state = {
5767
5886
  callback,
5768
5887
  key,
@@ -5774,71 +5893,16 @@ function createQueue(callback, options, key) {
5774
5893
  runners: 0
5775
5894
  };
5776
5895
  const instance = {
5777
- add: (parameters, signal) => {
5778
- if (instance.full) throw new QueueError(MESSAGE_MAXIMUM);
5779
- const abortSignal = signal instanceof AbortSignal ? signal : void 0;
5780
- if (abortSignal?.aborted ?? false) throw new Error(abortSignal.reason);
5781
- const id = identify(state);
5782
- let rejector;
5783
- let resolver;
5784
- const promise = new Promise((resolve, reject) => {
5785
- rejector = reject;
5786
- resolver = resolve;
5787
- });
5788
- const aborter = abortSignal == null ? void 0 : () => rejector(abortSignal.reason);
5789
- signal?.addEventListener(EVENT_NAME, aborter, EVENT_OPTIONS);
5790
- state.items.push({
5791
- id,
5792
- parameters,
5793
- promise,
5794
- abort: aborter,
5795
- key: state.key,
5796
- reject: rejector,
5797
- resolve: resolver,
5798
- signal: abortSignal
5799
- });
5800
- if (state.options.autostart) run(state);
5801
- return {
5802
- id,
5803
- promise
5804
- };
5805
- },
5806
- clear: () => {
5807
- const items = state.items.splice(0);
5808
- const { length } = items;
5809
- for (let index = 0; index < length; index += 1) {
5810
- const { abort, reject, signal } = items[index];
5811
- reject(new QueueError(MESSAGE_CLEAR));
5812
- signal?.removeEventListener(EVENT_NAME, abort);
5813
- }
5814
- },
5896
+ add: (parameters, signal) => addToQueue(instance, state, parameters, signal),
5897
+ clear: () => clearQueue(state),
5815
5898
  pause: () => {
5816
5899
  state.paused = true;
5817
5900
  },
5818
- remove: (id) => {
5819
- const index = state.items.findIndex((item) => item.id === id);
5820
- if (index > -1) {
5821
- const { abort, reject, signal } = state.items.splice(index, 1)[0];
5822
- reject(new QueueError(MESSAGE_REMOVE));
5823
- signal?.removeEventListener(EVENT_NAME, abort);
5824
- }
5825
- },
5826
- resume: () => {
5827
- if (state.paused) {
5828
- const handled = state.handled.splice(0);
5829
- const { length } = handled;
5830
- for (let index = 0; index < length; index += 1) handled[index]();
5831
- }
5832
- state.paused = false;
5833
- const length = Math.min(state.options.concurrency, state.items.length);
5834
- for (let index = 0; index < length; index += 1) run(state);
5835
- }
5901
+ remove: (id) => removeQueued(state, id),
5902
+ resume: () => resumeQueue(state)
5836
5903
  };
5837
5904
  Object.defineProperties(instance, {
5838
- [KEY_QUEUE]: {
5839
- enumerable: false,
5840
- value: NAME_QUEUE
5841
- },
5905
+ [QUEUE_PROPERTY]: { value: QUEUE_NAME_QUEUE },
5842
5906
  active: {
5843
5907
  enumerable: true,
5844
5908
  get: () => state.runners > 0
@@ -5874,15 +5938,6 @@ function createQueue(callback, options, key) {
5874
5938
  });
5875
5939
  return Object.freeze(instance);
5876
5940
  }
5877
- function getBooleanOrDefault(value, defaultValue) {
5878
- return typeof value === "boolean" ? value : defaultValue;
5879
- }
5880
- function getItems(state) {
5881
- const size = {};
5882
- const queues = state.queues.entries();
5883
- for (const [key, queue] of queues) size[key] = queue.size;
5884
- return size;
5885
- }
5886
5941
  function getOptions(input) {
5887
5942
  const options = typeof input === "object" && input != null ? input : {};
5888
5943
  return {
@@ -5892,7 +5947,7 @@ function getOptions(input) {
5892
5947
  };
5893
5948
  }
5894
5949
  function getQueue(state, key, add) {
5895
- if (typeof key !== "string" || key.trim().length === 0) throw new TypeError(MESSAGE_KEY);
5950
+ if (typeof key !== "string" || key.trim().length === 0) throw new TypeError(QUEUE_MESSAGE_KEY);
5896
5951
  let queue = state.queues.get(key);
5897
5952
  if (queue == null && add === true) {
5898
5953
  queue = createQueue(state.callback, state.options, key);
@@ -5900,6 +5955,12 @@ function getQueue(state, key, add) {
5900
5955
  }
5901
5956
  return queue;
5902
5957
  }
5958
+ function getQueueItems(state) {
5959
+ const size = {};
5960
+ const queues = state.queues.entries();
5961
+ for (const [key, queue] of queues) size[key] = queue.size;
5962
+ return size;
5963
+ }
5903
5964
  function getStatus(state, status) {
5904
5965
  const queues = state.queues.entries();
5905
5966
  const result = [];
@@ -5907,8 +5968,8 @@ function getStatus(state, status) {
5907
5968
  return result;
5908
5969
  }
5909
5970
  function handleQueuedResult(item, error, result) {
5910
- item.signal?.removeEventListener(EVENT_NAME, item.abort);
5911
- if (item.signal?.aborted ?? false) {
5971
+ item.aborter?.cancel();
5972
+ if (item.aborter?.signal?.aborted ?? false) {
5912
5973
  item.reject();
5913
5974
  return;
5914
5975
  }
@@ -5937,7 +5998,7 @@ function identify(state) {
5937
5998
  * @returns `true` if the value is a keyed queue, otherwise `false`
5938
5999
  */
5939
6000
  function isKeyedQueue(value) {
5940
- return isQueueInstance(NAME_KEYED, value);
6001
+ return isQueueInstance(QUEUE_NAME_KEYED, value);
5941
6002
  }
5942
6003
  /**
5943
6004
  * Is the value a queue?
@@ -5946,13 +6007,13 @@ function isKeyedQueue(value) {
5946
6007
  * @returns `true` if the value is a queue, otherwise `false`
5947
6008
  */
5948
6009
  function isQueue(value) {
5949
- return isQueueInstance(NAME_QUEUE, value);
6010
+ return isQueueInstance(QUEUE_NAME_QUEUE, value);
5950
6011
  }
5951
6012
  function isQueueInstance(name, value) {
5952
- return typeof value === "object" && value != null && value[KEY_QUEUE] === name;
6013
+ return typeof value === "object" && value != null && value[QUEUE_PROPERTY] === name;
5953
6014
  }
5954
6015
  function keyedQueue(callback, options) {
5955
- if (typeof callback !== "function") throw new TypeError(MESSAGE_CALLBACK);
6016
+ if (typeof callback !== "function") throw new TypeError(QUEUE_MESSAGE_CALLBACK);
5956
6017
  const state = {
5957
6018
  callback,
5958
6019
  options: getOptions(options),
@@ -5960,26 +6021,17 @@ function keyedQueue(callback, options) {
5960
6021
  };
5961
6022
  const instance = {
5962
6023
  add: (key, parameters, signal) => getQueue(state, key, true).add(parameters, signal),
5963
- clear: (key) => {
5964
- handleQueues(state, HANDLE_CLEAR, key);
5965
- },
6024
+ clear: (key) => handleQueues(state, QUEUE_HANDLE_CLEAR, key),
5966
6025
  get: (key) => getQueue(state, key),
5967
- pause: (key) => {
5968
- handleQueues(state, HANDLE_PAUSE, key);
5969
- },
6026
+ pause: (key) => handleQueues(state, QUEUE_HANDLE_PAUSE, key),
5970
6027
  remove: (key, id) => removeQueue(state, key, id),
5971
- resume: (key) => {
5972
- handleQueues(state, HANDLE_RESUME, key);
5973
- }
6028
+ resume: (key) => handleQueues(state, QUEUE_HANDLE_RESUME, key)
5974
6029
  };
5975
6030
  Object.defineProperties(instance, {
5976
- [KEY_QUEUE]: {
5977
- enumerable: false,
5978
- value: NAME_KEYED
5979
- },
6031
+ [QUEUE_PROPERTY]: { value: QUEUE_NAME_KEYED },
5980
6032
  active: {
5981
6033
  enumerable: true,
5982
- get: () => getStatus(state, STATUS_ACTIVE)
6034
+ get: () => getStatus(state, QUEUE_STATUS_ACTIVE)
5983
6035
  },
5984
6036
  autostart: {
5985
6037
  enumerable: true,
@@ -5991,15 +6043,15 @@ function keyedQueue(callback, options) {
5991
6043
  },
5992
6044
  empty: {
5993
6045
  enumerable: true,
5994
- get: () => getStatus(state, STATUS_EMPTY)
6046
+ get: () => getStatus(state, QUEUE_STATUS_EMPTY)
5995
6047
  },
5996
6048
  full: {
5997
6049
  enumerable: true,
5998
- get: () => getStatus(state, STATUS_FULL)
6050
+ get: () => getStatus(state, QUEUE_STATUS_FULL)
5999
6051
  },
6000
6052
  items: {
6001
6053
  enumerable: true,
6002
- get: () => getItems(state)
6054
+ get: () => getQueueItems(state)
6003
6055
  },
6004
6056
  keys: {
6005
6057
  enumerable: true,
@@ -6011,7 +6063,7 @@ function keyedQueue(callback, options) {
6011
6063
  },
6012
6064
  paused: {
6013
6065
  enumerable: true,
6014
- get: () => getStatus(state, STATUS_PAUSED)
6066
+ get: () => getStatus(state, QUEUE_STATUS_PAUSED)
6015
6067
  },
6016
6068
  queues: {
6017
6069
  enumerable: true,
@@ -6026,7 +6078,7 @@ function queue(callback, options) {
6026
6078
  queue.keyed = keyedQueue;
6027
6079
  function removeQueue(state, key, id) {
6028
6080
  if (key == null) {
6029
- handleQueues(state, HANDLE_CLEAR);
6081
+ handleQueues(state, QUEUE_HANDLE_CLEAR);
6030
6082
  state.queues.clear();
6031
6083
  return;
6032
6084
  }
@@ -6039,6 +6091,24 @@ function removeQueue(state, key, id) {
6039
6091
  queue.clear();
6040
6092
  state.queues.delete(key);
6041
6093
  }
6094
+ function removeQueued(state, id) {
6095
+ const index = state.items.findIndex((item) => item.id === id);
6096
+ if (index > -1) {
6097
+ const { aborter, reject } = state.items.splice(index, 1)[0];
6098
+ aborter?.cancel();
6099
+ reject(new QueueError(QUEUE_MESSAGE_REMOVE));
6100
+ }
6101
+ }
6102
+ function resumeQueue(state) {
6103
+ if (state.paused) {
6104
+ const handled = state.handled.splice(0);
6105
+ const { length } = handled;
6106
+ for (let index = 0; index < length; index += 1) handled[index]();
6107
+ }
6108
+ state.paused = false;
6109
+ const length = Math.min(state.options.concurrency, state.items.length);
6110
+ for (let index = 0; index < length; index += 1) run(state);
6111
+ }
6042
6112
  async function run(state) {
6043
6113
  if (state.paused || state.runners >= state.options.concurrency) return;
6044
6114
  state.runners += 1;
@@ -6047,7 +6117,7 @@ async function run(state) {
6047
6117
  let error = false;
6048
6118
  let result;
6049
6119
  try {
6050
- if (!(item.signal?.aborted ?? false)) {
6120
+ if (!(item.aborter?.signal?.aborted ?? false)) {
6051
6121
  const parameters = item.key == null ? item.parameters : [item.key, ...item.parameters];
6052
6122
  result = await state.callback(...parameters);
6053
6123
  }
@@ -6057,9 +6127,7 @@ async function run(state) {
6057
6127
  }
6058
6128
  if (state.paused) {
6059
6129
  const paused = item;
6060
- state.handled.push(() => {
6061
- handleQueuedResult(paused, error, result);
6062
- });
6130
+ state.handled.push(() => handleQueuedResult(paused, error, result));
6063
6131
  break;
6064
6132
  }
6065
6133
  handleQueuedResult(item, error, result);
@@ -6067,24 +6135,22 @@ async function run(state) {
6067
6135
  }
6068
6136
  state.runners -= 1;
6069
6137
  }
6070
- const ERROR_NAME = "QueueError";
6071
- const EVENT_NAME = "abort";
6072
- const EVENT_OPTIONS = { once: true };
6073
- const KEY_QUEUE = "$queue";
6074
- const HANDLE_CLEAR = "clear";
6075
- const HANDLE_PAUSE = "pause";
6076
- const HANDLE_RESUME = "resume";
6077
- const MESSAGE_CALLBACK = "A Queue requires a callback function";
6078
- const MESSAGE_CLEAR = "Queue was cleared";
6079
- const MESSAGE_KEY = "Key must be a non-empty string";
6080
- const MESSAGE_MAXIMUM = "Queue has reached its maximum size";
6081
- const MESSAGE_REMOVE = "Item removed from queue";
6082
- const NAME_KEYED = "keyedQueue";
6083
- const NAME_QUEUE = "queue";
6084
- const STATUS_ACTIVE = "active";
6085
- const STATUS_EMPTY = "empty";
6086
- const STATUS_FULL = "full";
6087
- const STATUS_PAUSED = "paused";
6138
+ const QUEUE_ERROR_NAME = "QueueError";
6139
+ const QUEUE_PROPERTY = "$queue";
6140
+ const QUEUE_HANDLE_CLEAR = "clear";
6141
+ const QUEUE_HANDLE_PAUSE = "pause";
6142
+ const QUEUE_HANDLE_RESUME = "resume";
6143
+ const QUEUE_MESSAGE_CALLBACK = "A Queue requires a callback function";
6144
+ const QUEUE_MESSAGE_CLEAR = "Queue was cleared";
6145
+ const QUEUE_MESSAGE_KEY = "Key must be a non-empty string";
6146
+ const QUEUE_MESSAGE_MAXIMUM = "Queue has reached its maximum size";
6147
+ const QUEUE_MESSAGE_REMOVE = "Item removed from queue";
6148
+ const QUEUE_NAME_KEYED = "keyedQueue";
6149
+ const QUEUE_NAME_QUEUE = "queue";
6150
+ const QUEUE_STATUS_ACTIVE = "active";
6151
+ const QUEUE_STATUS_EMPTY = "empty";
6152
+ const QUEUE_STATUS_FULL = "full";
6153
+ const QUEUE_STATUS_PAUSED = "paused";
6088
6154
  //#endregion
6089
6155
  //#region src/random.ts
6090
6156
  /**
@@ -6093,7 +6159,7 @@ const STATUS_PAUSED = "paused";
6093
6159
  * @returns Random boolean
6094
6160
  */
6095
6161
  function getRandomBoolean() {
6096
- return Math.random() > BOOLEAN_MODIFIER;
6162
+ return Math.random() > RANDOM_BOOLEAN_MODIFIER;
6097
6163
  }
6098
6164
  /**
6099
6165
  * Get a random string of characters with a specified length
@@ -6104,7 +6170,7 @@ function getRandomBoolean() {
6104
6170
  */
6105
6171
  function getRandomCharacters(length, selection) {
6106
6172
  if (typeof length !== "number" || length <= 0) return "";
6107
- const actual = typeof selection === "string" && selection.length > 0 ? selection : ALPHABET;
6173
+ const actual = typeof selection === "string" && selection.length > 0 ? selection : RANDOM_ALPHABET;
6108
6174
  let characters = "";
6109
6175
  for (let index = 0; index < length; index += 1) characters += actual.charAt(getRandomInteger(0, actual.length - 1));
6110
6176
  return characters;
@@ -6124,7 +6190,7 @@ function getRandomColor(prefix) {
6124
6190
  * @returns Random hexadecimal character from `0-9` and `A-F`
6125
6191
  */
6126
6192
  function getRandomHex() {
6127
- return HEX_CHARACTERS[getRandomInteger(0, HEX_MAXIMUM)];
6193
+ return RANDOM_HEX_CHARACTERS[getRandomInteger(0, RANDOM_HEX_MAXIMUM)];
6128
6194
  }
6129
6195
  /**
6130
6196
  * Get a random item from an array
@@ -6142,96 +6208,10 @@ function getRandomItems(array, amount) {
6142
6208
  if (amount === 1) return [array[getRandomInteger(0, array.length - 1)]];
6143
6209
  return typeof amount !== "number" || amount <= 0 || amount >= array.length ? shuffle(array) : shuffle(array).slice(0, amount);
6144
6210
  }
6145
- const ALPHABET = "abcdefghijklmnopqrstuvwxyz";
6146
- const BOOLEAN_MODIFIER = .5;
6147
- const HEX_CHARACTERS = "0123456789ABCDEF";
6148
- const HEX_MAXIMUM = 15;
6149
- //#endregion
6150
- //#region src/result/index.ts
6151
- async function asyncAttempt(value, err) {
6152
- try {
6153
- let result = typeof value === "function" ? value() : await value;
6154
- if (result instanceof Promise) result = await result;
6155
- return ok(result);
6156
- } catch (thrown) {
6157
- return getError(err ?? thrown, err == null ? void 0 : thrown);
6158
- }
6159
- }
6160
- function attempt(callback, err) {
6161
- try {
6162
- return ok(callback());
6163
- } catch (thrown) {
6164
- return getError(err ?? thrown, err == null ? void 0 : thrown);
6165
- }
6166
- }
6167
- attempt.async = asyncAttempt;
6168
- //#endregion
6169
- //#region src/result/match.ts
6170
- async function asyncMatchResult(result, first, error) {
6171
- let value;
6172
- if (typeof result === "function") value = await result();
6173
- else if (result instanceof Promise) value = await result;
6174
- else value = result;
6175
- if (!isResult(value)) throw new Error(MESSAGE_RESULT);
6176
- const hasObj = typeof first === "object" && first !== null;
6177
- const okHandler = hasObj ? first.ok : first;
6178
- const errorHandler = hasObj ? first.error : error;
6179
- if (isOk(value)) return okHandler(value.value);
6180
- return errorHandler(value.error, value.original);
6181
- }
6182
- function matchResult(result, first, error) {
6183
- const value = typeof result === "function" ? result() : result;
6184
- if (!isResult(value)) throw new Error(MESSAGE_RESULT);
6185
- const hasObj = typeof first === "object" && first !== null;
6186
- const okHandler = hasObj ? first.ok : first;
6187
- const errorHandler = hasObj ? first.error : error;
6188
- if (isOk(value)) return okHandler(value.value);
6189
- return errorHandler(value.error, value.original);
6190
- }
6191
- matchResult.async = asyncMatchResult;
6192
- const MESSAGE_RESULT = "`result.match` expected a Result or a function that returns a Result";
6193
- //#endregion
6194
- //#region src/result/work/flow.ts
6195
- function attemptAsyncFlow(...fns) {
6196
- let Flow;
6197
- return (...args) => attempt.async(() => {
6198
- Flow ??= flow.async(...fns);
6199
- return Flow(...args.map((value) => {
6200
- if (isError(value)) throw value.error;
6201
- return isOk(value) ? value.value : value;
6202
- }));
6203
- });
6204
- }
6205
- function attemptFlow(...fns) {
6206
- let Flow;
6207
- return (...args) => attempt(() => {
6208
- Flow ??= flow(...fns);
6209
- return Flow(...args.map((value) => {
6210
- if (isError(value)) throw value.error;
6211
- return isOk(value) ? value.value : value;
6212
- }));
6213
- });
6214
- }
6215
- attemptFlow.async = attemptAsyncFlow;
6216
- //#endregion
6217
- //#region src/result/work/pipe.ts
6218
- async function attemptAsyncPipe(initial, first, ...seconds) {
6219
- return attempt.async(() => {
6220
- if (isError(initial)) throw initial.error;
6221
- const value = typeof initial === "function" ? initial() : isOk(initial) ? initial.value : initial;
6222
- if (first == null) return value;
6223
- return asyncPipe(value, ...[first, ...seconds]);
6224
- });
6225
- }
6226
- function attemptPipe(initial, first, ...seconds) {
6227
- return attempt(() => {
6228
- if (isError(initial)) throw initial.error;
6229
- const value = typeof initial === "function" ? initial() : isOk(initial) ? initial.value : initial;
6230
- if (first == null) return value;
6231
- return pipe(value, ...[first, ...seconds]);
6232
- });
6233
- }
6234
- attemptPipe.async = attemptAsyncPipe;
6211
+ const RANDOM_ALPHABET = "abcdefghijklmnopqrstuvwxyz";
6212
+ const RANDOM_BOOLEAN_MODIFIER = .5;
6213
+ const RANDOM_HEX_CHARACTERS = "0123456789ABCDEF";
6214
+ const RANDOM_HEX_MAXIMUM = 15;
6235
6215
  //#endregion
6236
6216
  //#region src/sized/set.ts
6237
6217
  /**
@@ -6289,4 +6269,4 @@ var SizedSet = class extends Set {
6289
6269
  }
6290
6270
  };
6291
6271
  //#endregion
6292
- export { CancelablePromise, Logger, PROMISE_ABORT_EVENT, PROMISE_ABORT_OPTIONS, PROMISE_ERROR_NAME, PROMISE_MESSAGE_EXPECTATION_ATTEMPT, PROMISE_MESSAGE_EXPECTATION_RESULT, PROMISE_MESSAGE_EXPECTATION_TIMED, PROMISE_MESSAGE_TIMEOUT, PROMISE_STRATEGY_ALL, PROMISE_STRATEGY_DEFAULT, PROMISE_TYPE_FULFILLED, PROMISE_TYPE_REJECTED, PromiseTimeoutError, QueueError, RetryError, SORT_DIRECTION_ASCENDING, SORT_DIRECTION_DESCENDING, SizedMap, SizedSet, assert, assertCondition, assertDefined, assertInstanceOf, assertIs, assertProperty, assign, asyncAttempt, asyncDebounce, asyncFlow, asyncMatchResult, asyncOnce, asyncPipe, asyncThrottle, attempt, attemptAsyncFlow, attemptAsyncPipe, attemptFlow, attemptPipe, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, ceil, chunk, clamp, clone, compact, compare, copy, count, debounce, deburr, dedent, delay, deregisterCloner, deregisterComparator, deregisterEqualizer, diff, difference, drop, endsWith, endsWithArray, equal, error, exclude, exists, filter, find, findLast, first, firstOrDefault, flatFreeze, flatten, floor, flow, freeze, fromQuery, toPromise as fromResult, toPromise, fuzzy, fuzzyMatch, getArray, getArrayComparison, getColor, getError, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getHwbColor, getHwbaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloatingNumber as getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getSortedIndex, getString, getTimedPromise, getUuid, getValue, groupArraysBy, groupBy, handleResult, hasValue, hasValueResult, herald, hexToHsl, hexToHsla, hexToHwb, hexToHwba, hexToRgb, hexToRgba, hslToHex, hslToHwb, hslToHwba, hslToRgb, hslToRgba, hwbToHex, hwbToHsl, hwbToHsla, hwbToRgb, hwbToRgba, ignoreKey, inMap, inSet, includes, includesArray, indexOf, indexOfArray, initializeAssigner, initializeEqualizer, initializeMerger, initializeNormalizer, initializeSorter, initializeTemplater, initializeTransformer, insert, interpolate, intersection, isArrayOrPlainObject, isBeacon, isColor, isConstructor, isEmpty, isError, isEvents, isFrozen, isFulfilled, isHerald, isHexColor, isHslColor, isHslaColor, isHwbColor, isHwbaColor, isInstanceOf, isKey, isKeyedQueue, isLogger, isNonArrayOrPlainObject, isNonConstructor, isNonEmpty, isNonInstanceOf, isNonKey, isNonNullable, isNonNullableOrEmpty, isNonNullableOrWhitespace, isNonNumber, isNonNumerical, isNonObject, isNonPlainObject, isNonPrimitive, isNonTypedArray, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isObservable, isOk, isPlainObject, isPrimitive, isQueue, isQueueInstance, isRejected, isResult, isRgbColor, isRgbaColor, isSorted, isSubscription, isTimedLogger, isTypedArray, join, kebabCase, keyedQueue, last, lastIndexOf, lastOrDefault, lowerCase, matchResult, max, median, memoize, merge, min, move, moveIndices, moveToIndex, noop, normalize, ok, omit, once, parse, partition, pascalCase, pick, pipe, promises, push, queue, range, registerCloner, registerComparator, registerEqualizer, resultPromises, retry, reverse, rgbToHex, rgbToHsl, rgbToHsla, rgbToHwb, rgbToHwba, round, select, setValue, settlePromise, shake, shuffle, single, slice, smush, snakeCase, sort, splice, startsWith, startsWithArray, sum, swap, take, template, throttle, timed, times, titleCase, toMap, toMapArrays, toQuery, toRecord, toRecordArrays, toResult, toSet, toggle, transform, trim, truncate, tryDecode, tryEncode, union, unique, unsmush, unwrap, update, upperCase, words };
6272
+ export { CancelablePromise, Logger, PromiseTimeoutError, QueueError, RetryError, SORT_DIRECTION_ASCENDING, SORT_DIRECTION_DESCENDING, SizedMap, SizedSet, assert, assertCondition, assertDefined, assertInstanceOf, assertIs, assertProperty, assign, asyncAttempt, asyncDebounce, asyncFlow, asyncMatchResult, asyncOnce, asyncPipe, asyncThrottle, attempt, attemptAsyncFlow, attemptAsyncPipe, attemptFlow, attemptPipe, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, ceil, chunk, clamp, clone, compact, compare, copy, count, debounce, deburr, dedent, delay, deregisterCloner, deregisterComparator, deregisterEqualizer, diff, difference, drop, endsWith, endsWithArray, equal, error, exclude, exists, filter, find, findLast, first, firstOrDefault, flatFreeze, flatten, floor, flow, freeze, fromQuery, toPromise as fromResult, toPromise, fuzzy, fuzzyMatch, getArray, getArrayComparison, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getHwbColor, getHwbaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloatingNumber as getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getSortedIndex, getString, getTimedPromise, getUuid, getValue, groupArraysBy, groupBy, handleResult, hasValue, hasValueResult, herald, hexToHsl, hexToHsla, hexToHwb, hexToHwba, hexToRgb, hexToRgba, hslToHex, hslToHwb, hslToHwba, hslToRgb, hslToRgba, hwbToHex, hwbToHsl, hwbToHsla, hwbToRgb, hwbToRgba, ignoreKey, inMap, inSet, includes, includesArray, indexOf, indexOfArray, initializeAssigner, initializeEqualizer, initializeMerger, initializeNormalizer, initializeSorter, initializeTemplater, initializeTransformer, insert, interpolate, intersection, isArrayOrPlainObject, isBeacon, isBeaconSubscription, isColor, isConstructor, isEmpty, isError, isFrozen, isFulfilled, isHerald, isHeraldEvents, isHeraldSubscription, isHexColor, isHslColor, isHslaColor, isHwbColor, isHwbaColor, isInstanceOf, isKey, isKeyedQueue, isLogger, isNonArrayOrPlainObject, isNonConstructor, isNonEmpty, isNonInstanceOf, isNonKey, isNonNullable, isNonNullableOrEmpty, isNonNullableOrWhitespace, isNonNumber, isNonNumerical, isNonObject, isNonPlainObject, isNonPrimitive, isNonTypedArray, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isObservable, isOk, isPlainObject, isPrimitive, isQueue, isQueueInstance, isRejected, isResult, isRgbColor, isRgbaColor, isSorted, isSubscription, isTimedLogger, isTypedArray, join, kebabCase, keyedQueue, last, lastIndexOf, lastOrDefault, lowerCase, matchResult, max, median, memoize, merge, min, move, moveIndices, moveToIndex, noop, normalize, ok, omit, once, parse, partition, pascalCase, pick, pipe, promises, push, queue, range, registerCloner, registerComparator, registerEqualizer, resultPromises, retry, reverse, rgbToHex, rgbToHsl, rgbToHsla, rgbToHwb, rgbToHwba, round, select, setValue, settlePromise, shake, shuffle, single, slice, smush, snakeCase, sort, splice, startsWith, startsWithArray, sum, swap, take, template, throttle, timed, times, titleCase, toMap, toMapArrays, toQuery, toRecord, toRecordArrays, toResult, toSet, toggle, transform, trim, truncate, tryDecode, tryEncode, union, unique, unsmush, unwrap, update, upperCase, words };