@oscarpalmer/atoms 0.184.1 → 0.185.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 (108) hide show
  1. package/dist/array/index.d.mts +2 -2
  2. package/dist/array/index.mjs +2 -2
  3. package/dist/array/{position.d.mts → match.d.mts} +9 -6
  4. package/dist/array/{position.mjs → match.mjs} +16 -16
  5. package/dist/array/move.mjs +1 -1
  6. package/dist/array/single.mjs +2 -2
  7. package/dist/array/sort.d.mts +9 -4
  8. package/dist/array/sort.mjs +6 -6
  9. package/dist/array/swap.mjs +1 -1
  10. package/dist/beacon.d.mts +12 -0
  11. package/dist/beacon.mjs +9 -0
  12. package/dist/color/instance.d.mts +8 -0
  13. package/dist/color/instance.mjs +5 -2
  14. package/dist/color/misc/get.mjs +8 -8
  15. package/dist/color/misc/state.d.mts +2 -2
  16. package/dist/color/misc/state.mjs +2 -2
  17. package/dist/color/models.d.mts +30 -0
  18. package/dist/function/assert.d.mts +29 -8
  19. package/dist/function/assert.mjs +29 -8
  20. package/dist/function/memoize.d.mts +3 -0
  21. package/dist/function/memoize.mjs +3 -0
  22. package/dist/function/once.mjs +9 -9
  23. package/dist/function/retry.d.mts +3 -0
  24. package/dist/function/retry.mjs +11 -8
  25. package/dist/function/work.mjs +1 -1
  26. package/dist/index.d.mts +272 -160
  27. package/dist/index.mjs +279 -216
  28. package/dist/internal/number.d.mts +2 -1
  29. package/dist/internal/number.mjs +4 -1
  30. package/dist/internal/value/compare.d.mts +2 -1
  31. package/dist/internal/value/equal.d.mts +5 -0
  32. package/dist/internal/value/equal.mjs +5 -5
  33. package/dist/internal/value/get.d.mts +2 -2
  34. package/dist/internal/value/has.d.mts +3 -3
  35. package/dist/internal/value/has.mjs +1 -1
  36. package/dist/internal/value/misc.d.mts +2 -2
  37. package/dist/internal/value/misc.mjs +10 -4
  38. package/dist/logger.d.mts +11 -0
  39. package/dist/logger.mjs +11 -0
  40. package/dist/models.d.mts +1 -1
  41. package/dist/promise/helpers.mjs +3 -5
  42. package/dist/promise/index.d.mts +0 -6
  43. package/dist/promise/models.d.mts +36 -0
  44. package/dist/promise/models.mjs +6 -0
  45. package/dist/queue.d.mts +13 -1
  46. package/dist/queue.mjs +14 -7
  47. package/dist/result/index.d.mts +0 -8
  48. package/dist/result/index.mjs +0 -8
  49. package/dist/result/match.d.mts +4 -4
  50. package/dist/result/work/flow.d.mts +12 -36
  51. package/dist/result/work/pipe.d.mts +11 -33
  52. package/dist/sized/set.d.mts +3 -2
  53. package/dist/sized/set.mjs +3 -2
  54. package/dist/string/fuzzy.mjs +2 -2
  55. package/dist/value/handle.mjs +1 -1
  56. package/dist/value/merge.d.mts +0 -1
  57. package/dist/value/merge.mjs +0 -1
  58. package/dist/value/shake.d.mts +3 -0
  59. package/dist/value/smush.d.mts +3 -0
  60. package/dist/value/transform.d.mts +9 -0
  61. package/dist/value/unsmush.d.mts +3 -0
  62. package/package.json +3 -3
  63. package/src/array/difference.ts +4 -0
  64. package/src/array/from.ts +4 -0
  65. package/src/array/index.ts +1 -1
  66. package/src/array/intersection.ts +4 -0
  67. package/src/array/{position.ts → match.ts} +28 -25
  68. package/src/array/move.ts +5 -1
  69. package/src/array/reverse.ts +4 -0
  70. package/src/array/select.ts +2 -0
  71. package/src/array/single.ts +2 -2
  72. package/src/array/sort.ts +14 -9
  73. package/src/array/swap.ts +5 -1
  74. package/src/array/toggle.ts +4 -0
  75. package/src/array/union.ts +4 -0
  76. package/src/beacon.ts +12 -0
  77. package/src/color/index.ts +0 -3
  78. package/src/color/instance.ts +11 -3
  79. package/src/color/misc/get.ts +8 -8
  80. package/src/color/misc/state.ts +1 -1
  81. package/src/color/models.ts +30 -0
  82. package/src/function/assert.ts +66 -7
  83. package/src/function/memoize.ts +3 -0
  84. package/src/function/once.ts +13 -9
  85. package/src/function/retry.ts +11 -8
  86. package/src/internal/number.ts +6 -0
  87. package/src/internal/value/compare.ts +2 -1
  88. package/src/internal/value/equal.ts +10 -5
  89. package/src/internal/value/get.ts +2 -2
  90. package/src/internal/value/has.ts +6 -6
  91. package/src/internal/value/misc.ts +24 -13
  92. package/src/logger.ts +11 -0
  93. package/src/models.ts +1 -1
  94. package/src/promise/helpers.ts +3 -6
  95. package/src/promise/index.ts +0 -6
  96. package/src/promise/models.ts +36 -0
  97. package/src/queue.ts +23 -11
  98. package/src/result/index.ts +0 -8
  99. package/src/result/match.ts +4 -4
  100. package/src/result/work/flow.ts +12 -36
  101. package/src/result/work/pipe.ts +11 -33
  102. package/src/sized/set.ts +4 -3
  103. package/src/string/fuzzy.ts +2 -2
  104. package/src/value/merge.ts +0 -1
  105. package/src/value/shake.ts +3 -0
  106. package/src/value/smush.ts +3 -0
  107. package/src/value/transform.ts +9 -0
  108. package/src/value/unsmush.ts +3 -0
@@ -1,9 +1,12 @@
1
- // #region Types
2
-
3
1
  import {getArrayCallback} from '../internal/array/callbacks';
4
2
  import type {PlainObject} from '../models';
5
3
 
6
- export type ArrayPosition = 'end' | 'inside' | 'invalid' | 'outside' | 'same' | 'start';
4
+ // #region Types
5
+
6
+ /**
7
+ * Comparison of an array within another array
8
+ */
9
+ export type ArrayComparison = 'end' | 'inside' | 'invalid' | 'outside' | 'same' | 'start';
7
10
 
8
11
  // #endregion
9
12
 
@@ -54,11 +57,11 @@ export function endsWithArray(haystack: unknown[], needle: unknown[], key?: unkn
54
57
  * @param key Key to get an item's value for matching
55
58
  * @returns Position of the needle within the haystack
56
59
  */
57
- export function getArrayPosition<Item extends PlainObject>(
60
+ export function getArrayComparison<Item extends PlainObject>(
58
61
  haystack: Item[],
59
62
  needle: Item[],
60
63
  key: keyof Item,
61
- ): ArrayPosition;
64
+ ): ArrayComparison;
62
65
 
63
66
  /**
64
67
  * Get the position of an array within another array
@@ -67,11 +70,11 @@ export function getArrayPosition<Item extends PlainObject>(
67
70
  * @param callback Callback to get an item's value for matching
68
71
  * @returns Position of the needle within the haystack
69
72
  */
70
- export function getArrayPosition<Item>(
73
+ export function getArrayComparison<Item>(
71
74
  haystack: Item[],
72
75
  needle: Item[],
73
76
  callback: (item: Item, index: number, array: Item[]) => unknown,
74
- ): ArrayPosition;
77
+ ): ArrayComparison;
75
78
 
76
79
  /**
77
80
  * Get the position of an array within another array
@@ -79,29 +82,29 @@ export function getArrayPosition<Item>(
79
82
  * @param needle Needle array
80
83
  * @returns Position of the needle within the haystack
81
84
  */
82
- export function getArrayPosition<Item>(haystack: Item[], needle: Item[]): ArrayPosition;
85
+ export function getArrayComparison<Item>(haystack: Item[], needle: Item[]): ArrayComparison;
83
86
 
84
- export function getArrayPosition(
87
+ export function getArrayComparison(
85
88
  haystack: unknown[],
86
89
  needle: unknown[],
87
90
  key?: unknown,
88
- ): ArrayPosition {
91
+ ): ArrayComparison {
89
92
  return getPosition(haystack, needle, key)[1];
90
93
  }
91
94
 
92
- function getName(start: number, haystack: number, needle: number): ArrayPosition {
95
+ function getName(start: number, haystack: number, needle: number): ArrayComparison {
93
96
  if (start === 0) {
94
- return haystack === needle ? POSITION_SAME : POSITION_START;
97
+ return haystack === needle ? COMPARISON_SAME : COMPARISON_START;
95
98
  }
96
99
 
97
- return start + needle === haystack ? POSITION_END : POSITION_INSIDE;
100
+ return start + needle === haystack ? COMPARISON_END : COMPARISON_INSIDE;
98
101
  }
99
102
 
100
103
  function getPosition(
101
104
  haystack: unknown[],
102
105
  needle: unknown[],
103
106
  key?: unknown,
104
- ): readonly [number, ArrayPosition] {
107
+ ): readonly [number, ArrayComparison] {
105
108
  if (!Array.isArray(haystack) || !Array.isArray(needle)) {
106
109
  return invalid;
107
110
  }
@@ -278,26 +281,26 @@ export function startsWithArray(haystack: unknown[], needle: unknown[], key?: un
278
281
 
279
282
  // #region Variables
280
283
 
281
- const POSITION_END: ArrayPosition = 'end';
284
+ const COMPARISON_END: ArrayComparison = 'end';
282
285
 
283
- const POSITION_INSIDE: ArrayPosition = 'inside';
286
+ const COMPARISON_INSIDE: ArrayComparison = 'inside';
284
287
 
285
- const POSITION_INVALID: ArrayPosition = 'invalid';
288
+ const COMPARISON_INVALID: ArrayComparison = 'invalid';
286
289
 
287
- const POSITION_OUTSIDE: ArrayPosition = 'outside';
290
+ const COMPARISON_OUTSIDE: ArrayComparison = 'outside';
288
291
 
289
- const POSITION_SAME: ArrayPosition = 'same';
292
+ const COMPARISON_SAME: ArrayComparison = 'same';
290
293
 
291
- const POSITION_START: ArrayPosition = 'start';
294
+ const COMPARISON_START: ArrayComparison = 'start';
292
295
 
293
- const endings = new Set<ArrayPosition>([POSITION_END, POSITION_SAME]);
296
+ const endings = new Set<ArrayComparison>([COMPARISON_END, COMPARISON_SAME]);
294
297
 
295
- const invalid = [-1, POSITION_INVALID] as const;
298
+ const invalid = [-1, COMPARISON_INVALID] as const;
296
299
 
297
- const outside = [-1, POSITION_OUTSIDE] as const;
300
+ const outside = [-1, COMPARISON_OUTSIDE] as const;
298
301
 
299
- const outsides = new Set<ArrayPosition>([POSITION_INVALID, POSITION_OUTSIDE]);
302
+ const outsides = new Set<ArrayComparison>([COMPARISON_INVALID, COMPARISON_OUTSIDE]);
300
303
 
301
- const starts = new Set<ArrayPosition>([POSITION_START, POSITION_SAME]);
304
+ const starts = new Set<ArrayComparison>([COMPARISON_START, COMPARISON_SAME]);
302
305
 
303
306
  // #endregion
package/src/array/move.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import {arraysOverlap} from '../internal/array/overlap';
2
2
  import type {PlainObject} from '../models';
3
- import {indexOfArray} from './position';
3
+ import {indexOfArray} from './match';
4
+
5
+ // #region Functions
4
6
 
5
7
  /**
6
8
  * Move an item _(or array of items)_ to the position of another item _(or array of items)_ within an array
@@ -239,3 +241,5 @@ export function moveToIndex(
239
241
 
240
242
  return array;
241
243
  }
244
+
245
+ // #endregion
@@ -1,3 +1,5 @@
1
+ // #region Functions
2
+
1
3
  /**
2
4
  * Reverse the order of items in an array
3
5
  * @param array Array to reverse
@@ -26,3 +28,5 @@ export function reverse<Item>(array: Item[]): Item[] {
26
28
 
27
29
  return array;
28
30
  }
31
+
32
+ // #endregion Functions
@@ -1,6 +1,8 @@
1
1
  import {FIND_VALUES_ALL, findValues} from '../internal/array/find';
2
2
  import type {PlainObject} from '../models';
3
3
 
4
+ // #region Functions
5
+
4
6
  /**
5
7
  * Get a filtered and mapped array of items
6
8
  * @param array Array to search in
@@ -49,7 +49,7 @@ export function single(array: unknown[], ...parameters: unknown[]): unknown {
49
49
  const {matched} = findValues(FIND_VALUES_ALL, array, parameters);
50
50
 
51
51
  if (matched.length > 1) {
52
- throw new Error(MESSAGE);
52
+ throw new Error(SINGLE_MESSAGE);
53
53
  }
54
54
 
55
55
  return matched[0];
@@ -59,6 +59,6 @@ export function single(array: unknown[], ...parameters: unknown[]): unknown {
59
59
 
60
60
  // #region Variables
61
61
 
62
- const MESSAGE = 'Multiple items were found';
62
+ const SINGLE_MESSAGE = 'Multiple items were found';
63
63
 
64
64
  // #endregion
package/src/array/sort.ts CHANGED
@@ -104,6 +104,11 @@ type InternalSorterCompare = {
104
104
  */
105
105
  export type SortDirection = 'ascending' | 'descending';
106
106
 
107
+ /**
108
+ * Sorter for an array with predefined sorters
109
+ *
110
+ * Can be used to sort an array, get the predicted index for an item, and check if an array is sorted
111
+ */
107
112
  export type Sorter<Item> = {
108
113
  /**
109
114
  * Sort an array of items
@@ -245,7 +250,7 @@ function getObjectSorter(obj: PlainObject, modifier: number): InternalSorter | u
245
250
  *
246
251
  * _(If the array is not sorted, it will be treated as sorted, and the result may be inaccurate)_
247
252
  *
248
- * Available as `getSortedIndex` and `sort.index`
253
+ * Available as `getSortedIndex` and `sort.getIndex`
249
254
  * @param array Array to get the index from
250
255
  * @param item Item to get the index for
251
256
  * @param sorters Sorters to use to determine sorting
@@ -264,7 +269,7 @@ export function getSortedIndex<Item>(
264
269
  *
265
270
  * _(If the array is not sorted, it will be treated as sorted, and the result may be inaccurate)_
266
271
  *
267
- * Available as `getSortedIndex` and `sort.index`
272
+ * Available as `getSortedIndex` and `sort.getIndex`
268
273
  * @param array Array to get the index from
269
274
  * @param item Item to get the index for
270
275
  * @param sorter Sorter to use to determine sorting
@@ -283,7 +288,7 @@ export function getSortedIndex<Item>(
283
288
  *
284
289
  * _(If the array is not sorted, it will be treated as sorted, and the result may be inaccurate)_
285
290
  *
286
- * Available as `getSortedIndex` and `sort.index`
291
+ * Available as `getSortedIndex` and `sort.getIndex`
287
292
  * @param array Array to get the index from
288
293
  * @param item Item to get the index for
289
294
  * @param descending Sorted in descending order? _(defaults to `false`)_
@@ -458,9 +463,9 @@ function isSortedArray(array: unknown[], sorters: InternalSorter[]): boolean {
458
463
 
459
464
  let offset = 0;
460
465
 
461
- if (length >= ARRAY_THRESHOLD) {
462
- offset = Math.round(length / ARRAY_PEEK_PERCENTAGE);
463
- offset = offset > ARRAY_THRESHOLD ? ARRAY_THRESHOLD : offset;
466
+ if (length >= SORT_THRESHOLD) {
467
+ offset = Math.round(length / SORT_PEEK_PERCENTAGE);
468
+ offset = offset > SORT_THRESHOLD ? SORT_THRESHOLD : offset;
464
469
 
465
470
  for (let index = 0; index < offset; index += 1) {
466
471
  const [firstItem, firstOffset] = [array[index], array[index + 1]];
@@ -552,7 +557,7 @@ function sortArray(array: unknown[], sorters: InternalSorter[]): unknown[] {
552
557
  : array;
553
558
  }
554
559
 
555
- sort.index = getSortedIndex;
560
+ sort.getIndex = getSortedIndex;
556
561
  sort.initialize = initializeSorter;
557
562
  sort.is = isSorted;
558
563
 
@@ -560,9 +565,9 @@ sort.is = isSorted;
560
565
 
561
566
  // #region Variables
562
567
 
563
- const ARRAY_PEEK_PERCENTAGE = 10;
568
+ const SORT_PEEK_PERCENTAGE = 10;
564
569
 
565
- const ARRAY_THRESHOLD = 100;
570
+ const SORT_THRESHOLD = 100;
566
571
 
567
572
  export const SORT_DIRECTION_ASCENDING: SortDirection = 'ascending';
568
573
 
package/src/array/swap.ts CHANGED
@@ -2,7 +2,9 @@ import {getArrayCallback} from '../internal/array/callbacks';
2
2
  import {indexOf} from '../internal/array/index-of';
3
3
  import {arraysOverlap} from '../internal/array/overlap';
4
4
  import type {PlainObject} from '../models';
5
- import {indexOfArray} from './position';
5
+ import {indexOfArray} from './match';
6
+
7
+ // #region Functions
6
8
 
7
9
  /**
8
10
  * Swap two smaller arrays within a larger array
@@ -211,3 +213,5 @@ function swapValues(array: unknown[], from: unknown, to: unknown, key?: unknown)
211
213
 
212
214
  return swapIndices(array, first, second);
213
215
  }
216
+
217
+ // #endregion
@@ -1,6 +1,8 @@
1
1
  import {updateInArray} from '../internal/array/update';
2
2
  import type {PlainObject} from '../models';
3
3
 
4
+ // #region Functions
5
+
4
6
  /**
5
7
  * Toggle an item in an array: if the item exists, it will be removed; if it doesn't, it will be added
6
8
  * @param destination Array to toggle within
@@ -38,3 +40,5 @@ export function toggle<Item>(destination: Item[], toggled: Item[]): Item[];
38
40
  export function toggle(array: unknown[], values: unknown[], key?: unknown): unknown[] {
39
41
  return updateInArray(array, values, key, false);
40
42
  }
43
+
44
+ // #endregion
@@ -1,5 +1,7 @@
1
1
  import {COMPARE_SETS_UNION, compareSets} from '../internal/array/sets';
2
2
 
3
+ // #region Functions
4
+
3
5
  /**
4
6
  * Get the combined, unique values from two arrays
5
7
  * @param first First array
@@ -37,3 +39,5 @@ export function union<First, Second>(first: First[], second: Second[]): (First |
37
39
  export function union(first: unknown[], second: unknown[], key?: unknown): unknown[] {
38
40
  return compareSets(COMPARE_SETS_UNION, first, second, key);
39
41
  }
42
+
43
+ // #endregion
package/src/beacon.ts CHANGED
@@ -4,6 +4,9 @@ import type {PlainObject} from './models';
4
4
 
5
5
  // #region Types
6
6
 
7
+ /**
8
+ * A beacon is a lighthouse, holding an observable value that can be subscribed to and emitted from
9
+ */
7
10
  class Beacon<Value> {
8
11
  readonly #options: Options;
9
12
  readonly #state: BeaconState<Value>;
@@ -122,6 +125,9 @@ type BeaconState<Value> = {
122
125
  value: Value;
123
126
  };
124
127
 
128
+ /**
129
+ * An observable holds a value and allows observers to subscribe to changes in that value
130
+ */
125
131
  class Observable<Value> {
126
132
  readonly #state: ObservableState<Value>;
127
133
 
@@ -186,6 +192,9 @@ type ObservableState<Value> = {
186
192
  observers: Map<Subscription<Value>, Observer<Value>>;
187
193
  };
188
194
 
195
+ /**
196
+ * An observer receives notifications from an observable
197
+ */
189
198
  type Observer<Value> = {
190
199
  /**
191
200
  * Callback for when the observable is completed
@@ -203,6 +212,9 @@ type Observer<Value> = {
203
212
 
204
213
  type Options = Required<BeaconOptions<unknown>>;
205
214
 
215
+ /**
216
+ * A subscription represents an active subscription to an observable, holding its state and allowing it to be destroyed or unsubscribed from
217
+ */
206
218
  class Subscription<Value> {
207
219
  readonly #state: SubscriptionState<Value>;
208
220
 
@@ -39,11 +39,8 @@ export {
39
39
  } from './misc/is';
40
40
 
41
41
  export {getNormalizedHex, hexToHsl, hexToHsla, hexToRgb, hexToRgba} from './space/hex';
42
-
43
42
  export {hslToHex, hslToRgb, hslToRgba} from './space/hsl';
44
-
45
43
  export {rgbToHex, rgbToHsl, rgbToHsla} from './space/rgb';
46
-
47
44
  export type {Color, HSLAColor, HSLColor, RGBAColor, RGBColor};
48
45
 
49
46
  // #endregion
@@ -1,12 +1,20 @@
1
1
  import {SPACE_HSL, SPACE_RGB} from './constants';
2
2
  import {formatColor} from './misc';
3
3
  import {getAlpha} from './misc/alpha';
4
- import {getState, setHexColor, setHSLColor, setRGBColor} from './misc/state';
4
+ import {getColorState, setHexColor, setHSLColor, setRGBColor} from './misc/state';
5
5
  import type {ColorState, HSLAColor, HSLColor, RGBAColor, RGBColor} from './models';
6
6
 
7
- // #region Classes
7
+ // #region Types
8
8
 
9
+ /**
10
+ * A color that is represented in multiple color formats
11
+ */
9
12
  export class Color {
13
+ /**
14
+ * A property to identify this as a Color instance, used for type checking
15
+ *
16
+ * @internal
17
+ */
10
18
  declare private readonly $color: boolean;
11
19
 
12
20
  readonly #state: ColorState;
@@ -118,7 +126,7 @@ export class Color {
118
126
  }
119
127
 
120
128
  constructor(value: unknown) {
121
- this.#state = getState(value);
129
+ this.#state = getColorState(value);
122
130
 
123
131
  Object.defineProperty(this, '$color', {
124
132
  value: true,
@@ -17,7 +17,7 @@ import {
17
17
  } from '../constants';
18
18
  import {Color} from '../instance';
19
19
  import type {HSLAColor, HSLColor, RGBAColor, RGBColor} from '../models';
20
- import {getState} from './state';
20
+ import {getColorState} from './state';
21
21
 
22
22
  // #region Functions
23
23
 
@@ -31,7 +31,7 @@ function getClampedValue(value: unknown, minimum: number, maximum: number): numb
31
31
  * @returns Foreground color
32
32
  */
33
33
  export function getForegroundColor(value: unknown): Color {
34
- const state = getState(value);
34
+ const state = getColorState(value);
35
35
  const {blue, green, red} = state.rgb;
36
36
 
37
37
  const values = [blue / MAX_HEX, green / MAX_HEX, red / MAX_HEX];
@@ -63,7 +63,7 @@ export function getForegroundColor(value: unknown): Color {
63
63
  * @returns Hex color
64
64
  */
65
65
  export function getHexaColor(value: unknown): string {
66
- const {alpha, hex} = getState(value);
66
+ const {alpha, hex} = getColorState(value);
67
67
 
68
68
  return `${hex}${alpha.hex}`;
69
69
  }
@@ -74,7 +74,7 @@ export function getHexaColor(value: unknown): string {
74
74
  * @returns Hex color
75
75
  */
76
76
  export function getHexColor(value: unknown): string {
77
- return getState(value).hex;
77
+ return getColorState(value).hex;
78
78
  }
79
79
 
80
80
  export function getHexValue(value: unknown): number {
@@ -91,7 +91,7 @@ export function getDegrees(value: unknown): number {
91
91
  * @returns HSLA color
92
92
  */
93
93
  export function getHslaColor(value: unknown): HSLAColor {
94
- const {alpha, hsl} = getState(value);
94
+ const {alpha, hsl} = getColorState(value);
95
95
 
96
96
  return {
97
97
  ...hsl,
@@ -105,7 +105,7 @@ export function getHslaColor(value: unknown): HSLAColor {
105
105
  * @returns HSL color
106
106
  */
107
107
  export function getHslColor(value: unknown): HSLColor {
108
- return getState(value).hsl;
108
+ return getColorState(value).hsl;
109
109
  }
110
110
 
111
111
  export function getPercentage(value: unknown): number {
@@ -118,7 +118,7 @@ export function getPercentage(value: unknown): number {
118
118
  * @returns RGBA color
119
119
  */
120
120
  export function getRgbaColor(value: unknown): RGBAColor {
121
- const {alpha, rgb} = getState(value);
121
+ const {alpha, rgb} = getColorState(value);
122
122
 
123
123
  return {
124
124
  ...rgb,
@@ -132,7 +132,7 @@ export function getRgbaColor(value: unknown): RGBAColor {
132
132
  * @returns RGB color
133
133
  */
134
134
  export function getRgbColor(value: unknown): RGBColor {
135
- return getState(value).rgb;
135
+ return getColorState(value).rgb;
136
136
  }
137
137
 
138
138
  // #endregion
@@ -17,7 +17,7 @@ import {isColor, isHexColor, isHslLike, isRgbLike} from './is';
17
17
 
18
18
  // #region Functions
19
19
 
20
- export function getState(value: unknown): ColorState {
20
+ export function getColorState(value: unknown): ColorState {
21
21
  if (typeof value === 'string') {
22
22
  const normalized = getNormalizedHex(value, true);
23
23
  const hex = normalized.slice(0, LENGTH_LONG);
@@ -9,19 +9,49 @@ type ColorWithAlpha = {
9
9
  alpha: number;
10
10
  };
11
11
 
12
+ /**
13
+ * An _HSL_-color with an alpha channel
14
+ */
12
15
  export type HSLAColor = HSLColor & ColorWithAlpha;
13
16
 
17
+ /**
18
+ * An _HSL_-color
19
+ */
14
20
  export type HSLColor = {
21
+ /**
22
+ * Hue of the color _(in degrees; 0-360)_
23
+ */
15
24
  hue: number;
25
+ /**
26
+ * Lightness of the color _(in percentage; 0-100)_
27
+ */
16
28
  lightness: number;
29
+ /**
30
+ * Saturation of the color _(in percentage; 0-100)_
31
+ */
17
32
  saturation: number;
18
33
  };
19
34
 
35
+ /**
36
+ * An _RGB_-color with an alpha channel
37
+ */
20
38
  export type RGBAColor = RGBColor & ColorWithAlpha;
21
39
 
40
+ /**
41
+ * An _RGB_-color
42
+ */
22
43
  export type RGBColor = {
44
+ /**
45
+ * Blue channel of the color _(in hexadecimal; 0-255)_
46
+ */
23
47
  blue: number;
48
+ /**
49
+ * Green channel of the color _(in hexadecimal; 0-255)_
50
+ */
24
51
  green: number;
52
+ /**
53
+ * Red channel of the color _(in hexadecimal; 0-255)_
54
+ */
25
55
  red: number;
26
56
  };
27
57
 
@@ -1,9 +1,32 @@
1
- import type {Constructor} from '../models';
1
+ import {hasValueResult} from '../internal/value/has';
2
+ import type {Constructor, NestedKeys, NestedValue, PlainObject} from '../models';
2
3
 
3
4
  // #region Types
4
5
 
6
+ /**
7
+ * Asserter for a nested property of a value
8
+ */
9
+ export type AssertProperty<
10
+ Value extends PlainObject,
11
+ Path extends NestedKeys<Value>,
12
+ Asserted extends NestedPick<Value, Path> = NestedPick<Value, Path>,
13
+ > = Asserter<Asserted>;
14
+
15
+ /**
16
+ * A function that asserts a value is of a specific type, throwing an error if it is not
17
+ */
5
18
  export type Asserter<Value> = (value: unknown) => asserts value is Value;
6
19
 
20
+ type NestedPick<Value, Path extends string> = Value extends PlainObject
21
+ ? Path extends `${infer Head}.${infer Rest}`
22
+ ? Head extends keyof Value
23
+ ? {[Key in Head]: NestedPick<Value[Key], Rest>}
24
+ : never
25
+ : Path extends keyof Value
26
+ ? {[Key in Path]: Value[Key]}
27
+ : never
28
+ : never;
29
+
7
30
  // #endregion
8
31
 
9
32
  // #region Functions
@@ -12,7 +35,7 @@ export type Asserter<Value> = (value: unknown) => asserts value is Value;
12
35
  * Asserts that a condition is true, throwing an error if it is not
13
36
  * @param condition Condition to assert
14
37
  * @param message Error message
15
- * @param error Error constructor
38
+ * @param error Error constructor _(defaults to `Error`)_
16
39
  */
17
40
  export function assert<Condition extends () => boolean>(
18
41
  condition: Condition,
@@ -28,6 +51,7 @@ assert.condition = assertCondition;
28
51
  assert.defined = assertDefined;
29
52
  assert.instanceOf = assertInstanceOf;
30
53
  assert.is = assertIs;
54
+ assert.property = assertProperty;
31
55
 
32
56
  /**
33
57
  * Creates an asserter that asserts a condition is true, throwing an error if it is not
@@ -35,7 +59,7 @@ assert.is = assertIs;
35
59
  * Available as `assertCondition` and `assert.condition`
36
60
  * @param condition Condition to assert
37
61
  * @param message Error message
38
- * @param error Error constructor
62
+ * @param error Error constructor _(defaults to `Error`)_
39
63
  * @returns Asserter
40
64
  */
41
65
  export function assertCondition<Value>(
@@ -49,17 +73,19 @@ export function assertCondition<Value>(
49
73
  }
50
74
 
51
75
  /**
52
- * Asserts that a value is defined throwing an error if it is not
76
+ * Asserts that a value is defined, throwing an error if it is not
53
77
  *
54
78
  * Available as `assertDefined` and `assert.defined`
55
79
  * @param value Value to assert
56
80
  * @param message Error message
81
+ * @param error Error constructor _(defaults to `Error`)_
57
82
  */
58
83
  export function assertDefined<Value>(
59
84
  value: unknown,
60
85
  message?: string,
86
+ error?: ErrorConstructor,
61
87
  ): asserts value is Exclude<Value, null | undefined> {
62
- assert(() => value != null, message ?? MESSAGE_VALUE_DEFINED);
88
+ assert(() => value != null, message ?? MESSAGE_VALUE_DEFINED, error);
63
89
  }
64
90
 
65
91
  /**
@@ -68,7 +94,7 @@ export function assertDefined<Value>(
68
94
  * Available as `assertInstanceOf` and `assert.instanceOf`
69
95
  * @param constructor Constructor to check against
70
96
  * @param message Error message
71
- * @param error Error constructor
97
+ * @param error Error constructor _(defaults to `Error`)_
72
98
  * @returns Asserter
73
99
  */
74
100
  export function assertInstanceOf<Value>(
@@ -87,7 +113,7 @@ export function assertInstanceOf<Value>(
87
113
  * Available as `assertIs` and `assert.is`
88
114
  * @param condition Type guard function to check the value
89
115
  * @param message Error message
90
- * @param error Error constructor
116
+ * @param error Error constructor _(defaults to `Error`)_
91
117
  * @returns Asserter
92
118
  */
93
119
  export function assertIs<Value>(
@@ -100,6 +126,39 @@ export function assertIs<Value>(
100
126
  };
101
127
  }
102
128
 
129
+ /**
130
+ * Creates an asserter that asserts a property of a value exists and satisfies a condition, throwing an error if it does not
131
+ *
132
+ * Available as `assertProperty` and `assert.property`
133
+ * @param path Path to the property to check, e.g., `foo.bar.baz` for a nested property
134
+ * @param condition Condition to assert for the property
135
+ * @param message Error message
136
+ * @param error Error constructor _(defaults to `Error`)_
137
+ * @returns Asserter
138
+ */
139
+ export function assertProperty<
140
+ Value extends PlainObject,
141
+ Path extends NestedKeys<Value>,
142
+ Asserted = NestedPick<Value, Path>,
143
+ >(
144
+ path: Path,
145
+ condition: (value: NestedValue<Value, Path>) => boolean,
146
+ message: string,
147
+ error?: ErrorConstructor,
148
+ ): Asserter<Asserted> {
149
+ return (value: unknown): asserts value is Asserted => {
150
+ assert(
151
+ () => {
152
+ const result = hasValueResult(value as never, path, false);
153
+
154
+ return result.ok && condition(result.value as never);
155
+ },
156
+ message,
157
+ error,
158
+ );
159
+ };
160
+ }
161
+
103
162
  // #endregion
104
163
 
105
164
  // #region Variables
@@ -5,6 +5,9 @@ import {SizedMap} from '../sized/map';
5
5
 
6
6
  // #region Types
7
7
 
8
+ /**
9
+ * A memoized function, caching and retrieving results based on the its parameters _(or a custom cache key)_
10
+ */
8
11
  class Memoized<Callback extends GenericCallback> {
9
12
  readonly #state: MemoizedState<Callback>;
10
13