@oscarpalmer/atoms 0.192.0 → 0.193.1

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 (130) hide show
  1. package/dist/index.d.mts +25 -23
  2. package/dist/index.mjs +30 -31
  3. package/dist/queue.d.mts +25 -23
  4. package/dist/queue.mjs +27 -28
  5. package/package.json +3 -4
  6. package/src/array/difference.ts +0 -73
  7. package/src/array/exists.ts +0 -93
  8. package/src/array/filter.ts +0 -182
  9. package/src/array/find.ts +0 -183
  10. package/src/array/first.ts +0 -196
  11. package/src/array/flatten.ts +0 -20
  12. package/src/array/from.ts +0 -129
  13. package/src/array/get.ts +0 -131
  14. package/src/array/group-by.ts +0 -369
  15. package/src/array/index.ts +0 -26
  16. package/src/array/insert.ts +0 -52
  17. package/src/array/intersection.ts +0 -72
  18. package/src/array/last.ts +0 -194
  19. package/src/array/match.ts +0 -436
  20. package/src/array/move.ts +0 -315
  21. package/src/array/partition.ts +0 -91
  22. package/src/array/push.ts +0 -23
  23. package/src/array/reverse.ts +0 -33
  24. package/src/array/select.ts +0 -260
  25. package/src/array/single.ts +0 -93
  26. package/src/array/slice.ts +0 -335
  27. package/src/array/sort.ts +0 -607
  28. package/src/array/splice.ts +0 -106
  29. package/src/array/swap.ts +0 -322
  30. package/src/array/to-map.ts +0 -371
  31. package/src/array/to-record.ts +0 -351
  32. package/src/array/to-set.ts +0 -80
  33. package/src/array/toggle.ts +0 -79
  34. package/src/array/union.ts +0 -72
  35. package/src/array/unique.ts +0 -67
  36. package/src/array/update.ts +0 -75
  37. package/src/beacon.ts +0 -378
  38. package/src/color/constants.ts +0 -137
  39. package/src/color/index.ts +0 -83
  40. package/src/color/instance.ts +0 -162
  41. package/src/color/misc/alpha.ts +0 -56
  42. package/src/color/misc/format.ts +0 -29
  43. package/src/color/misc/get.ts +0 -210
  44. package/src/color/misc/is.ts +0 -221
  45. package/src/color/misc/state.ts +0 -243
  46. package/src/color/models.ts +0 -389
  47. package/src/color/space/hex.ts +0 -184
  48. package/src/color/space/hsl.ts +0 -174
  49. package/src/color/space/hwb.ts +0 -153
  50. package/src/color/space/rgb.ts +0 -240
  51. package/src/function/assert.ts +0 -174
  52. package/src/function/index.ts +0 -2
  53. package/src/function/limit.ts +0 -83
  54. package/src/function/memoize.ts +0 -202
  55. package/src/function/once.ts +0 -200
  56. package/src/function/retry.ts +0 -175
  57. package/src/function/work.ts +0 -1007
  58. package/src/herald.ts +0 -216
  59. package/src/index.ts +0 -68
  60. package/src/internal/array/callbacks.ts +0 -46
  61. package/src/internal/array/chunk.ts +0 -51
  62. package/src/internal/array/compact.ts +0 -56
  63. package/src/internal/array/find.ts +0 -200
  64. package/src/internal/array/group.ts +0 -42
  65. package/src/internal/array/index-of.ts +0 -182
  66. package/src/internal/array/insert.ts +0 -80
  67. package/src/internal/array/overlap.ts +0 -35
  68. package/src/internal/array/sets.ts +0 -74
  69. package/src/internal/array/shuffle.ts +0 -33
  70. package/src/internal/array/update.ts +0 -52
  71. package/src/internal/function/misc.ts +0 -8
  72. package/src/internal/function/timer.ts +0 -168
  73. package/src/internal/is.ts +0 -244
  74. package/src/internal/math/aggregate.ts +0 -164
  75. package/src/internal/math/misc.ts +0 -28
  76. package/src/internal/number.ts +0 -129
  77. package/src/internal/random.ts +0 -49
  78. package/src/internal/result.ts +0 -92
  79. package/src/internal/sized.ts +0 -25
  80. package/src/internal/string.ts +0 -128
  81. package/src/internal/subscription.ts +0 -264
  82. package/src/internal/value/compare.ts +0 -170
  83. package/src/internal/value/equal.ts +0 -465
  84. package/src/internal/value/get.ts +0 -57
  85. package/src/internal/value/handlers.ts +0 -95
  86. package/src/internal/value/has.ts +0 -118
  87. package/src/internal/value/misc.ts +0 -125
  88. package/src/internal/value/partial.ts +0 -46
  89. package/src/internal/value/set.ts +0 -132
  90. package/src/is.ts +0 -182
  91. package/src/logger.ts +0 -230
  92. package/src/math.ts +0 -281
  93. package/src/models.ts +0 -286
  94. package/src/number.ts +0 -1
  95. package/src/promise/delay.ts +0 -62
  96. package/src/promise/helpers.ts +0 -96
  97. package/src/promise/index.ts +0 -300
  98. package/src/promise/misc.ts +0 -96
  99. package/src/promise/models.ts +0 -195
  100. package/src/promise/timed.ts +0 -91
  101. package/src/query.ts +0 -147
  102. package/src/queue.ts +0 -814
  103. package/src/random.ts +0 -125
  104. package/src/result/index.ts +0 -105
  105. package/src/result/match.ts +0 -124
  106. package/src/result/misc.ts +0 -129
  107. package/src/result/models.ts +0 -83
  108. package/src/result/work/flow.ts +0 -488
  109. package/src/result/work/pipe.ts +0 -496
  110. package/src/sized/map.ts +0 -110
  111. package/src/sized/set.ts +0 -107
  112. package/src/string/case.ts +0 -236
  113. package/src/string/fuzzy.ts +0 -444
  114. package/src/string/index.ts +0 -199
  115. package/src/string/match.ts +0 -80
  116. package/src/string/normalize.ts +0 -205
  117. package/src/string/template.ts +0 -161
  118. package/src/value/clone.ts +0 -319
  119. package/src/value/collection.ts +0 -63
  120. package/src/value/diff.ts +0 -232
  121. package/src/value/freeze.ts +0 -322
  122. package/src/value/handle.ts +0 -3
  123. package/src/value/index.ts +0 -5
  124. package/src/value/merge.ts +0 -278
  125. package/src/value/omit.ts +0 -20
  126. package/src/value/pick.ts +0 -20
  127. package/src/value/shake.ts +0 -45
  128. package/src/value/smush.ts +0 -89
  129. package/src/value/transform.ts +0 -153
  130. package/src/value/unsmush.ts +0 -84
@@ -1,240 +0,0 @@
1
- import {join} from '../../internal/string';
2
- import {COLOR_DEFAULTS, COLOR_MAX, COLOR_TYPE} from '../constants';
3
- import {getAlpha, getAlphaValue} from '../misc/alpha';
4
- import {getHexValue} from '../misc/get';
5
- import {isRgbLike} from '../misc/is';
6
- import type {
7
- ColorState,
8
- ColorType,
9
- HSLAColor,
10
- HSLColor,
11
- HWBAColor,
12
- HWBColor,
13
- RGBAColor,
14
- RGBColor,
15
- } from '../models';
16
-
17
- // #region Types
18
-
19
- type RgbValues = {
20
- blue: number;
21
- delta: number;
22
- green: number;
23
- max: number;
24
- min: number;
25
- red: number;
26
- };
27
-
28
- // #endregion
29
-
30
- // #region Functions
31
-
32
- export function convertRgbToHex(rgb: RGBAColor | RGBColor, alpha: boolean): string {
33
- const hex = `${join(
34
- [rgb.red, rgb.green, rgb.blue].map(color => {
35
- const hexString = color.toString(16);
36
-
37
- return hexString.length === 1 ? `0${hexString}` : hexString;
38
- }),
39
- )}`;
40
-
41
- let a = '';
42
-
43
- if (typeof alpha === 'boolean' && alpha) {
44
- a = getAlpha((rgb as RGBAColor).alpha, false).hex;
45
- }
46
-
47
- return `${hex}${a}`;
48
- }
49
-
50
- export function convertRgbToHsla(value: unknown): HSLAColor {
51
- const rgb = isRgbLike(value) ? getRgbValue(value) : {...COLOR_DEFAULTS.rgb};
52
- const values = getRgbValues(rgb);
53
-
54
- const {delta, max, min} = values;
55
-
56
- const lightness = (min + max) / 2;
57
-
58
- let hue = 0;
59
- let saturation = 0;
60
-
61
- if (delta !== 0) {
62
- saturation = (max - lightness) / Math.min(lightness, 1 - lightness);
63
-
64
- hue = getRgbHue(values);
65
-
66
- hue *= 60;
67
- }
68
-
69
- return {
70
- hue,
71
- saturation: saturation * COLOR_MAX.percent,
72
- lightness: lightness * COLOR_MAX.percent,
73
- alpha: getAlphaValue((value as RGBAColor)?.alpha ?? COLOR_MAX.percent),
74
- };
75
- }
76
-
77
- export function convertRgbToHwba(value: unknown): HWBAColor {
78
- const rgb = isRgbLike(value) ? getRgbValue(value) : {...COLOR_DEFAULTS.rgb};
79
- const values = getRgbValues(rgb);
80
-
81
- const {delta, max, min} = values;
82
-
83
- let hue = 0;
84
-
85
- if (delta !== 0) {
86
- hue = getRgbHue(values);
87
-
88
- hue *= 60;
89
- }
90
-
91
- return {
92
- hue,
93
- whiteness: min * COLOR_MAX.percent,
94
- blackness: (1 - max) * COLOR_MAX.percent,
95
- alpha: getAlphaValue((value as RGBAColor)?.alpha ?? COLOR_MAX.percent),
96
- };
97
- }
98
-
99
- export function getColorFromRgb<Type extends ColorType>(
100
- state: ColorState,
101
- type: Type,
102
- ): NonNullable<ColorState[Type]> {
103
- switch (type) {
104
- case COLOR_TYPE.hex:
105
- state.hex = rgbToHex(state.rgb!);
106
- break;
107
-
108
- case COLOR_TYPE.hsl:
109
- state.hsl = rgbToHsl(state.rgb!);
110
- break;
111
-
112
- case COLOR_TYPE.hwb:
113
- state.hwb = rgbToHwb(state.rgb!);
114
- break;
115
- }
116
-
117
- return state[type]!;
118
- }
119
-
120
- function getRgbHue(values: RgbValues): number {
121
- const {blue, delta, green, max, red} = values;
122
-
123
- switch (max) {
124
- case blue:
125
- return (red - green) / delta + 4;
126
-
127
- case green:
128
- return (blue - red) / delta + 2;
129
-
130
- default:
131
- return (green - blue) / delta + (green < blue ? 6 : 0);
132
- }
133
- }
134
-
135
- export function getRgbValue(value: Record<keyof RGBColor, unknown>): RGBColor {
136
- return {
137
- blue: getHexValue((value as RGBColor).blue),
138
- green: getHexValue((value as RGBColor).green),
139
- red: getHexValue((value as RGBColor).red),
140
- };
141
- }
142
-
143
- function getRgbValues(rgb: RGBColor): RgbValues {
144
- const blue = rgb.blue / COLOR_MAX.hex;
145
- const green = rgb.green / COLOR_MAX.hex;
146
- const red = rgb.red / COLOR_MAX.hex;
147
-
148
- const max = Math.max(blue, green, red);
149
- const min = Math.min(blue, green, red);
150
-
151
- const delta = max - min;
152
-
153
- return {blue, delta, green, max, min, red};
154
- }
155
-
156
- /**
157
- * Convert an _RGB(A)_ color to a hex color _(with optional alpha channel, i.e., opacity)_
158
- *
159
- * _If the value is unable to be converted, a black hex color will be returned_
160
- *
161
- * @param rgb _RGB(A)_ color
162
- * @param alpha Include alpha channel _(opacity)_? _(defaults to `false`)_
163
- * @returns Hex color string
164
- */
165
- export function rgbToHex(rgb: RGBAColor | RGBColor, alpha?: boolean): string {
166
- return convertRgbToHex(
167
- isRgbLike(rgb) ? getRgbValue(rgb) : {...COLOR_DEFAULTS.rgb},
168
- alpha ?? false,
169
- );
170
- }
171
-
172
- /**
173
- * Convert an _RGB(A)_ color to an _HSL_ color
174
- *
175
- * _If the value is unable to be converted, a black _HSL_ color will be returned_
176
- *
177
- * _Thanks, https://github.com/color-js/color.js/blob/main/src/spaces/hsl.js#L26_
178
- *
179
- * @param rgb _RGB(A)_ color
180
- * @returns _HSL_ color
181
- */
182
- export function rgbToHsl(rgb: RGBAColor | RGBColor): HSLColor {
183
- const {hue, lightness, saturation} = convertRgbToHsla(rgb);
184
-
185
- return {
186
- hue,
187
- lightness,
188
- saturation,
189
- };
190
- }
191
-
192
- /**
193
- * Convert an _RGB(A)_ color to an _HSLA_ color
194
- *
195
- * _If the value is unable to be converted, a black _HSLA_ color will be returned_
196
- *
197
- * _Thanks, https://github.com/color-js/color.js/blob/main/src/spaces/hsl.js#L26_
198
- *
199
- * @param rgb _RGB(A)_ color
200
- * @returns _HSLA_ color
201
- */
202
- export function rgbToHsla(rgb: RGBAColor | RGBColor): HSLAColor {
203
- return convertRgbToHsla(rgb);
204
- }
205
-
206
- /**
207
- * Convert an _RGB(A)_ color to an _HWB_ color
208
- *
209
- * _If the value is unable to be converted, a black _HWB_ color will be returned_
210
- *
211
- * _Thanks, https://github.com/color-js/color.js/blob/main/src/spaces/hsl.js#L26_
212
- *
213
- * @param rgb _RGB(A)_ color
214
- * @returns _HWB_ color
215
- */
216
- export function rgbToHwb(rgb: RGBAColor | RGBColor): HWBColor {
217
- const {blackness, hue, whiteness} = convertRgbToHwba(rgb);
218
-
219
- return {
220
- hue,
221
- whiteness,
222
- blackness,
223
- };
224
- }
225
-
226
- /**
227
- * Convert an _RGB(A)_ color to an _HWBA_ color
228
-
229
- * _If the value is unable to be converted, a black _HWBA_ color will be returned_
230
- *
231
- * _Thanks, https://github.com/color-js/color.js/blob/main/src/spaces/hsl.js#L26_
232
- *
233
- * @param rgb _RGB(A)_ color
234
- * @returns _HWBA_ color
235
- */
236
- export function rgbToHwba(rgb: RGBAColor | RGBColor): HWBAColor {
237
- return convertRgbToHwba(rgb);
238
- }
239
-
240
- // #endregion
@@ -1,174 +0,0 @@
1
- import {hasValueResult} from '../internal/value/has';
2
- import type {Constructor, NestedKeys, NestedValue, PlainObject} from '../models';
3
-
4
- // #region Types
5
-
6
- /**
7
- * Asserter for a 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
- */
18
- export type Asserter<Value> = (value: unknown) => asserts value is Value;
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
-
30
- // #endregion
31
-
32
- // #region Functions
33
-
34
- /**
35
- * Asserts that a condition is true, throwing an error if it is not
36
- *
37
- * @param condition Condition to assert
38
- * @param message Error message
39
- * @param error Error constructor _(defaults to `Error`)_
40
- */
41
- export function assert<Condition extends () => boolean>(
42
- condition: Condition,
43
- message: string,
44
- error?: ErrorConstructor,
45
- ): asserts condition {
46
- if (!condition()) {
47
- throw new (error ?? Error)(message);
48
- }
49
- }
50
-
51
- assert.condition = assertCondition;
52
- assert.defined = assertDefined;
53
- assert.instanceOf = assertInstanceOf;
54
- assert.is = assertIs;
55
- assert.property = assertProperty;
56
-
57
- /**
58
- * Creates an _Asserter_ that asserts a condition is true, throwing an error if it is not
59
- *
60
- * _Available as `assertCondition` and `assert.condition`_
61
- *
62
- * @param condition Condition to assert
63
- * @param message Error message
64
- * @param error Error constructor _(defaults to `Error`)_
65
- * @returns _Asserter_
66
- */
67
- export function assertCondition<Value>(
68
- condition: (value: unknown) => boolean,
69
- message: string,
70
- error?: ErrorConstructor,
71
- ): Asserter<Value> {
72
- return value => {
73
- assert(() => condition(value), message, error);
74
- };
75
- }
76
-
77
- /**
78
- * Asserts that a value is defined, throwing an error if it is not
79
- *
80
- * _Available as `assertDefined` and `assert.defined`_
81
- *
82
- * @param value Value to assert
83
- * @param message Error message
84
- * @param error Error constructor _(defaults to `Error`)_
85
- */
86
- export function assertDefined<Value>(
87
- value: unknown,
88
- message?: string,
89
- error?: ErrorConstructor,
90
- ): asserts value is Exclude<Value, null | undefined> {
91
- assert(() => value != null, message ?? MESSAGE_VALUE_DEFINED, error);
92
- }
93
-
94
- /**
95
- * Creates an _Asserter_ that asserts a value is an instance of a constructor, throwing an error if it is not
96
- *
97
- * _Available as `assertInstanceOf` and `assert.instanceOf`_
98
- *
99
- * @param constructor Constructor to check against
100
- * @param message Error message
101
- * @param error Error constructor _(defaults to `Error`)_
102
- * @returns _Asserter_
103
- */
104
- export function assertInstanceOf<Value>(
105
- constructor: Constructor<Value>,
106
- message: string,
107
- error?: ErrorConstructor,
108
- ): Asserter<Value> {
109
- return value => {
110
- assert(() => value instanceof constructor, message, error);
111
- };
112
- }
113
-
114
- /**
115
- * Creates an _Asserter_ that asserts a value is of a specific type, throwing an error if it is not
116
- *
117
- * _Available as `assertIs` and `assert.is`_
118
- *
119
- * @param condition Type guard function to check the value
120
- * @param message Error message
121
- * @param error Error constructor _(defaults to `Error`)_
122
- * @returns _Asserter_
123
- */
124
- export function assertIs<Value>(
125
- condition: (value: unknown) => value is Value,
126
- message: string,
127
- error?: ErrorConstructor,
128
- ): Asserter<Value> {
129
- return value => {
130
- assert(() => condition(value), message, error);
131
- };
132
- }
133
-
134
- /**
135
- * Creates an _Asserter_ that asserts a property of a value exists and satisfies a condition, throwing an error if it does not
136
- *
137
- * _Available as `assertProperty` and `assert.property`_
138
- *
139
- * @param path Path to the property to check, e.g., `foo.bar.baz` for a nested property
140
- * @param condition Condition to assert for the property
141
- * @param message Error message
142
- * @param error Error constructor _(defaults to `Error`)_
143
- * @returns _Asserter_
144
- */
145
- export function assertProperty<
146
- Value extends PlainObject,
147
- Path extends NestedKeys<Value>,
148
- Asserted = NestedPick<Value, Path>,
149
- >(
150
- path: Path,
151
- condition: (value: NestedValue<Value, Path>) => boolean,
152
- message: string,
153
- error?: ErrorConstructor,
154
- ): Asserter<Asserted> {
155
- return (value: unknown): asserts value is Asserted => {
156
- assert(
157
- () => {
158
- const result = hasValueResult(value as never, path, false);
159
-
160
- return result.ok && condition(result.value as never);
161
- },
162
- message,
163
- error,
164
- );
165
- };
166
- }
167
-
168
- // #endregion
169
-
170
- // #region Variables
171
-
172
- const MESSAGE_VALUE_DEFINED = 'Expected value to be defined';
173
-
174
- // #endregion
@@ -1,2 +0,0 @@
1
- export {noop} from '../internal/function/misc';
2
- export {memoize, type Memoized, type MemoizedOptions} from './memoize';
@@ -1,83 +0,0 @@
1
- import {getAsyncTimer, getTimer, TIMER_DEBOUNCE, TIMER_THROTTLE} from '../internal/function/timer';
2
- import type {
3
- AsyncCancelableCallback,
4
- CancelableCallback,
5
- GenericAsyncCallback,
6
- GenericCallback,
7
- } from '../models';
8
-
9
- // #region Functions
10
-
11
- /**
12
- * Debounce a function, ensuring it is only called after `time` milliseconds have passed
13
- *
14
- * - When called, successful _(finished)_ results will resolve and errors will reject
15
- * - 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...)_
16
- *
17
- * _Available as `asyncDebounce` and `debounce.async`_
18
- *
19
- * @param callback Callback to debounce
20
- * @param time Time in milliseconds to wait before calling the callback _(defaults to `0`; e.g., as soon as possible)_
21
- * @returns Debounced callback handler with a `cancel` method
22
- */
23
- export function asyncDebounce<Callback extends GenericAsyncCallback | GenericCallback>(
24
- callback: Callback,
25
- time?: number,
26
- ): AsyncCancelableCallback<Callback> {
27
- return getAsyncTimer(TIMER_DEBOUNCE, callback, time);
28
- }
29
-
30
- /**
31
- * Throttle a function, ensuring it is only called once every `time` milliseconds
32
- *
33
- * - When called, successful _(finished)_ results will resolve and errors will reject
34
- * - 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...)_
35
- *
36
- * _Available as `asyncThrottle` and `throttle.async`_
37
- *
38
- * @param callback Callback to throttle
39
- * @param time Time in milliseconds to wait before calling the callback again _(defaults to `0`; e.g., as soon as possible)_
40
- * @returns Throttled callback handler with a `cancel` method
41
- */
42
- export function asyncThrottle<Callback extends GenericAsyncCallback | GenericCallback>(
43
- callback: Callback,
44
- time?: number,
45
- ): AsyncCancelableCallback<Callback> {
46
- return getAsyncTimer(TIMER_THROTTLE, callback, time);
47
- }
48
-
49
- /**
50
- * Debounce a function, ensuring it is only called after `time` milliseconds have passed
51
- *
52
- * On subsequent calls, the timer is reset and will wait another `time` milliseconds _(and so on...)_
53
- *
54
- * @param callback Callback to debounce
55
- * @param time Time in milliseconds to wait before calling the callback _(defaults to `0`; e.g., as soon as possible)_
56
- * @returns Debounced callback handler with a `cancel` method
57
- */
58
- export function debounce<Callback extends GenericCallback>(
59
- callback: Callback,
60
- time?: number,
61
- ): CancelableCallback<Callback> {
62
- return getTimer(TIMER_DEBOUNCE, callback, time);
63
- }
64
-
65
- debounce.async = asyncDebounce;
66
-
67
- /**
68
- * Throttle a function, ensuring it is only called once every `time` milliseconds
69
- *
70
- * @param callback Callback to throttle
71
- * @param time Time in milliseconds to wait before calling the callback again _(defaults to `0`; e.g., as soon as possible)_
72
- * @returns Throttled callback handler with a `cancel` method
73
- */
74
- export function throttle<Callback extends GenericCallback>(
75
- callback: Callback,
76
- time?: number,
77
- ): CancelableCallback<Callback> {
78
- return getTimer(TIMER_THROTTLE, callback, time);
79
- }
80
-
81
- throttle.async = asyncThrottle;
82
-
83
- // #endregion
@@ -1,202 +0,0 @@
1
- import {isPlainObject} from '../internal/is';
2
- import {getString, join} from '../internal/string';
3
- import type {GenericCallback} from '../models';
4
- import {SizedMap} from '../sized/map';
5
-
6
- // #region Types
7
-
8
- /**
9
- * A _Memoized_ function instance, caching and retrieving results based on the its parameters _(or a custom cache key)_
10
- */
11
- export type Memoized<Callback extends GenericCallback> = {
12
- /**
13
- * Maximum cache size
14
- *
15
- * @returns Maximum cache size _(or `Number.NaN` if the instance has been destroyed)_
16
- */
17
- get maximum(): number;
18
-
19
- /**
20
- * Current cache size
21
- *
22
- * @returns Current cache size _(or `Number.NaN` if the instance has been destroyed)_
23
- */
24
- get size(): number;
25
-
26
- /**
27
- * Clear the cache
28
- */
29
- clear(): void;
30
-
31
- /**
32
- * Delete a result from the cache
33
- *
34
- * @param key Key to delete
35
- * @returns `true` if the key existed and was removed, otherwise `false`
36
- */
37
- delete(key: unknown): boolean;
38
-
39
- /**
40
- * Destroy the instance
41
- *
42
- * _(When a Memoized instance is destroyed, its cache and callback are removed, and calls to `run` will throw an error)_
43
- */
44
- destroy(): void;
45
-
46
- /**
47
- * Get a result from the cache
48
- *
49
- * @param key Key to get
50
- * @returns Cached result or `undefined` if it does not exist
51
- */
52
- get(key: unknown): ReturnType<Callback> | undefined;
53
-
54
- /**
55
- * Does the result exist?
56
- *
57
- * @param key Key to check
58
- * @returns `true` if the result exists, otherwise `false`
59
- */
60
- has(key: unknown): boolean;
61
-
62
- /**
63
- * Run the callback with the provided parameters
64
- *
65
- * @param parameters Parameters to pass to the callback
66
- * @returns Cached or computed _(then cached)_ result
67
- */
68
- run(...parameters: Parameters<Callback>): ReturnType<Callback>;
69
- };
70
-
71
- /**
72
- * Options for a _Memoized_ function
73
- */
74
- export type MemoizedOptions<Callback extends GenericCallback> = {
75
- /**
76
- * Callback for getting a cache key for the provided parameters
77
- */
78
- cacheKey?: (...parameters: Parameters<Callback>) => unknown;
79
- /**
80
- * Size of the cache
81
- */
82
- cacheSize?: number;
83
- };
84
-
85
- type MemoizedState<Callback extends GenericCallback> = {
86
- cache?: SizedMap<unknown, ReturnType<Callback>>;
87
- getter?: (...parameters: Parameters<Callback>) => ReturnType<Callback>;
88
- options: Options;
89
- };
90
-
91
- type Options = {
92
- cacheKey?: GenericCallback;
93
- cacheSize: number;
94
- };
95
-
96
- // #endregion
97
-
98
- // #region Functions
99
-
100
- function getMemoizationOptions<Callback extends GenericCallback>(
101
- input?: MemoizedOptions<Callback>,
102
- ): Options {
103
- const {cacheKey, cacheSize} = isPlainObject(input) ? (input as MemoizedOptions<Callback>) : {};
104
-
105
- return {
106
- cacheKey: typeof cacheKey === 'function' ? cacheKey : undefined,
107
- cacheSize: typeof cacheSize === 'number' && cacheSize > 0 ? cacheSize : DEFAULT_CACHE_SIZE,
108
- };
109
- }
110
-
111
- /**
112
- * Memoize a function, caching and retrieving results based on the first parameter
113
- *
114
- * @param callback Callback to memoize
115
- * @param options Memoization options
116
- * @returns _Memoized_ instance
117
- */
118
- export function memoize<Callback extends GenericCallback>(
119
- callback: Callback,
120
- options?: MemoizedOptions<Callback>,
121
- ): Memoized<Callback> {
122
- if (typeof callback !== 'function') {
123
- throw new TypeError(MEMOIZED_ERROR_CALLBACK);
124
- }
125
-
126
- const state: MemoizedState<Callback> = {
127
- options: getMemoizationOptions(options),
128
- };
129
-
130
- state.cache = new SizedMap<unknown, ReturnType<Callback>>(state.options.cacheSize);
131
-
132
- state.getter = (...parameters: Parameters<Callback>): ReturnType<Callback> => {
133
- const key =
134
- state.options.cacheKey?.(...parameters) ??
135
- (parameters.length === 1 ? parameters[0] : join(parameters.map(getString), SEPARATOR));
136
-
137
- if (state.cache!.has(key)) {
138
- return state.cache!.get(key) as ReturnType<Callback>;
139
- }
140
-
141
- const value = callback(...parameters);
142
-
143
- state.cache?.set(key, value);
144
-
145
- return value;
146
- };
147
-
148
- const instance = {
149
- clear: () => {
150
- state.cache?.clear();
151
- },
152
- delete: (key: unknown) => {
153
- return state.cache?.delete(key) ?? false;
154
- },
155
- destroy: () => {
156
- state.cache?.clear();
157
-
158
- state.cache = undefined;
159
- state.getter = undefined;
160
- },
161
- get: (key: unknown) => {
162
- return state.cache?.get(key);
163
- },
164
- has: (key: unknown) => {
165
- return state.cache?.has(key) ?? false;
166
- },
167
- run: (...parameters: Parameters<Callback>) => {
168
- if (state.cache == null || state.getter == null) {
169
- throw new Error(MEMOIZED_ERROR_DESTROYED);
170
- }
171
-
172
- return state.getter(...parameters);
173
- },
174
- };
175
-
176
- Object.defineProperties(instance, {
177
- maximum: {
178
- enumerable: true,
179
- get: () => state.cache?.maximum ?? Number.NaN,
180
- },
181
- size: {
182
- enumerable: true,
183
- get: () => state.cache?.size ?? Number.NaN,
184
- },
185
- });
186
-
187
- return Object.freeze(instance) as Memoized<Callback>;
188
- }
189
-
190
- // #endregion
191
-
192
- // #region Variables
193
-
194
- const DEFAULT_CACHE_SIZE = 1024;
195
-
196
- const MEMOIZED_ERROR_CALLBACK = 'Memoized requires a callback function';
197
-
198
- const MEMOIZED_ERROR_DESTROYED = 'The Memoized instance has been destroyed';
199
-
200
- const SEPARATOR = '_';
201
-
202
- // #endregion