@ls-stack/utils 3.65.0 → 3.67.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.
- package/dist/{arrayUtils.d.cts → arrayUtils.d.mts} +24 -23
- package/dist/arrayUtils.mjs +249 -0
- package/dist/assertions-qMxfVhSu.mjs +207 -0
- package/dist/{assertions.d.ts → assertions.d.mts} +4 -3
- package/dist/assertions.mjs +3 -0
- package/dist/asyncQueue.d.mts +497 -0
- package/dist/asyncQueue.mjs +757 -0
- package/dist/{awaitDebounce.d.cts → awaitDebounce.d.mts} +11 -6
- package/dist/awaitDebounce.mjs +54 -0
- package/dist/{cache.d.ts → cache.d.mts} +76 -68
- package/dist/cache.mjs +355 -0
- package/dist/castValues-DfICShCc.mjs +19 -0
- package/dist/{castValues.d.cts → castValues.d.mts} +3 -2
- package/dist/castValues.mjs +3 -0
- package/dist/{concurrentCalls.d.ts → concurrentCalls.d.mts} +74 -65
- package/dist/concurrentCalls.mjs +295 -0
- package/dist/consoleFmt.d.mts +55 -0
- package/dist/consoleFmt.mjs +63 -0
- package/dist/conversions-DTmwEMIu.mjs +12 -0
- package/dist/conversions.d.mts +4 -0
- package/dist/conversions.mjs +3 -0
- package/dist/createThrottleController.d.mts +18 -0
- package/dist/createThrottleController.mjs +40 -0
- package/dist/debounce.d.mts +47 -0
- package/dist/debounce.mjs +117 -0
- package/dist/dedent.d.mts +74 -0
- package/dist/dedent.mjs +80 -0
- package/dist/deepEqual-C7EZEixx.mjs +78 -0
- package/dist/{deepEqual.d.cts → deepEqual.d.mts} +3 -2
- package/dist/deepEqual.mjs +3 -0
- package/dist/{deepReplaceValues.d.cts → deepReplaceValues.d.mts} +4 -3
- package/dist/deepReplaceValues.mjs +61 -0
- package/dist/diffParser.d.mts +79 -0
- package/dist/diffParser.mjs +424 -0
- package/dist/enhancedMap.d.mts +21 -0
- package/dist/enhancedMap.mjs +69 -0
- package/dist/exhaustiveMatch.d.mts +10 -0
- package/dist/exhaustiveMatch.mjs +48 -0
- package/dist/{filterObjectOrArrayKeys.d.cts → filterObjectOrArrayKeys.d.mts} +15 -8
- package/dist/filterObjectOrArrayKeys.mjs +497 -0
- package/dist/{getAutoIncrementId.d.cts → getAutoIncrementId.d.mts} +9 -5
- package/dist/getAutoIncrementId.mjs +53 -0
- package/dist/{getCompositeKey.d.cts → getCompositeKey.d.mts} +3 -2
- package/dist/getCompositeKey.mjs +50 -0
- package/dist/{getValueStableKey.d.cts → getValueStableKey.d.mts} +5 -3
- package/dist/getValueStableKey.mjs +17 -0
- package/dist/{hash.d.cts → hash.d.mts} +3 -2
- package/dist/hash.mjs +28 -0
- package/dist/interpolate.d.mts +17 -0
- package/dist/interpolate.mjs +28 -0
- package/dist/{iteratorUtils.d.cts → iteratorUtils.d.mts} +5 -4
- package/dist/iteratorUtils.mjs +39 -0
- package/dist/keepPrevIfUnchanged.d.mts +12 -0
- package/dist/keepPrevIfUnchanged.mjs +9 -0
- package/dist/keyedMap.d.mts +76 -0
- package/dist/keyedMap.mjs +139 -0
- package/dist/keyedSet.d.mts +77 -0
- package/dist/keyedSet.mjs +129 -0
- package/dist/{levenshtein.d.cts → levenshtein.d.mts} +3 -2
- package/dist/levenshtein.mjs +121 -0
- package/dist/main.d.mts +4 -0
- package/dist/main.mjs +7 -0
- package/dist/matchPath.d.mts +50 -0
- package/dist/matchPath.mjs +81 -0
- package/dist/mathUtils-BDP1lM_z.mjs +81 -0
- package/dist/{mathUtils.d.cts → mathUtils.d.mts} +3 -2
- package/dist/mathUtils.mjs +3 -0
- package/dist/{mutationUtils.d.cts → mutationUtils.d.mts} +6 -5
- package/dist/mutationUtils.mjs +44 -0
- package/dist/{objUtils.d.ts → objUtils.d.mts} +8 -6
- package/dist/objUtils.mjs +115 -0
- package/dist/parallelAsyncCalls.d.mts +83 -0
- package/dist/parallelAsyncCalls.mjs +121 -0
- package/dist/partialEqual.d.mts +139 -0
- package/dist/partialEqual.mjs +1055 -0
- package/dist/promiseUtils.d.mts +9 -0
- package/dist/promiseUtils.mjs +17 -0
- package/dist/regexUtils.d.mts +18 -0
- package/dist/regexUtils.mjs +34 -0
- package/dist/{retryOnError.d.cts → retryOnError.d.mts} +38 -37
- package/dist/retryOnError.mjs +91 -0
- package/dist/{runShellCmd.d.ts → runShellCmd.d.mts} +24 -15
- package/dist/runShellCmd.mjs +151 -0
- package/dist/{safeJson.d.cts → safeJson.d.mts} +3 -2
- package/dist/safeJson.mjs +30 -0
- package/dist/{saferTyping.d.cts → saferTyping.d.mts} +4 -3
- package/dist/saferTyping.mjs +45 -0
- package/dist/serializeXML.d.mts +23 -0
- package/dist/serializeXML.mjs +74 -0
- package/dist/{shallowEqual.d.cts → shallowEqual.d.mts} +3 -2
- package/dist/shallowEqual.mjs +54 -0
- package/dist/sleep.d.mts +4 -0
- package/dist/sleep.mjs +7 -0
- package/dist/stringUtils-DjhWOiYn.mjs +113 -0
- package/dist/{stringUtils.d.cts → stringUtils.d.mts} +3 -2
- package/dist/stringUtils.mjs +3 -0
- package/dist/{testUtils.d.ts → testUtils.d.mts} +83 -52
- package/dist/testUtils.mjs +310 -0
- package/dist/{throttle.d.ts → throttle.d.mts} +18 -17
- package/dist/throttle.mjs +102 -0
- package/dist/time-sr2lhQRw.mjs +67 -0
- package/dist/{time.d.ts → time.d.mts} +8 -7
- package/dist/time.mjs +3 -0
- package/dist/{timers.d.cts → timers.d.mts} +22 -13
- package/dist/timers.mjs +220 -0
- package/dist/{tsResult.d.cts → tsResult.d.mts} +52 -48
- package/dist/tsResult.mjs +142 -0
- package/dist/typeGuards-B1mzA-Rz.mjs +128 -0
- package/dist/{typeGuards.d.cts → typeGuards.d.mts} +3 -2
- package/dist/typeGuards.mjs +3 -0
- package/dist/{typeUtils.d.ts → typeUtils.d.mts} +13 -34
- package/dist/typeUtils.mjs +1 -0
- package/dist/{typedStrings.d.cts → typedStrings.d.mts} +5 -4
- package/dist/typedStrings.mjs +131 -0
- package/dist/typingFnUtils-Bb8drgKF.mjs +101 -0
- package/dist/{typingFnUtils.d.cts → typingFnUtils.d.mts} +13 -22
- package/dist/typingFnUtils.mjs +3 -0
- package/dist/{typingTestUtils.d.cts → typingTestUtils.d.mts} +11 -15
- package/dist/typingTestUtils.mjs +80 -0
- package/dist/typingUtils.d.mts +20 -0
- package/dist/typingUtils.mjs +1 -0
- package/dist/yamlStringify.d.mts +17 -0
- package/dist/yamlStringify.mjs +189 -0
- package/package.json +65 -242
- package/dist/arrayUtils.cjs +0 -229
- package/dist/arrayUtils.d.ts +0 -171
- package/dist/arrayUtils.js +0 -42
- package/dist/assertions.cjs +0 -107
- package/dist/assertions.d.cts +0 -192
- package/dist/assertions.js +0 -25
- package/dist/asyncQueue.cjs +0 -672
- package/dist/asyncQueue.d.cts +0 -488
- package/dist/asyncQueue.d.ts +0 -488
- package/dist/asyncQueue.js +0 -631
- package/dist/awaitDebounce.cjs +0 -106
- package/dist/awaitDebounce.d.ts +0 -41
- package/dist/awaitDebounce.js +0 -28
- package/dist/cache.cjs +0 -367
- package/dist/cache.d.cts +0 -228
- package/dist/cache.js +0 -19
- package/dist/castValues.cjs +0 -50
- package/dist/castValues.d.ts +0 -4
- package/dist/castValues.js +0 -8
- package/dist/chunk-5DZT3Z5Z.js +0 -8
- package/dist/chunk-6FBIEPWU.js +0 -96
- package/dist/chunk-6FIBVC2P.js +0 -56
- package/dist/chunk-7CQPOM5I.js +0 -100
- package/dist/chunk-B6DNOZCP.js +0 -369
- package/dist/chunk-BM4PYVOX.js +0 -109
- package/dist/chunk-C2SVCIWE.js +0 -57
- package/dist/chunk-CCUPDGSZ.js +0 -132
- package/dist/chunk-DBOWTYR4.js +0 -49
- package/dist/chunk-DFXNVEH6.js +0 -14
- package/dist/chunk-DX2524CZ.js +0 -314
- package/dist/chunk-GMJTLFM6.js +0 -60
- package/dist/chunk-IATIXMCE.js +0 -20
- package/dist/chunk-II4R3VVX.js +0 -25
- package/dist/chunk-JF2MDHOJ.js +0 -40
- package/dist/chunk-JQFUKJU5.js +0 -71
- package/dist/chunk-MI4UE2PQ.js +0 -561
- package/dist/chunk-PUKVXYYL.js +0 -52
- package/dist/chunk-QQS7I7ZL.js +0 -16
- package/dist/chunk-VAAMRG4K.js +0 -20
- package/dist/chunk-WFQJUJTC.js +0 -182
- package/dist/chunk-ZXIKIA5B.js +0 -178
- package/dist/concurrentCalls.cjs +0 -406
- package/dist/concurrentCalls.d.cts +0 -116
- package/dist/concurrentCalls.js +0 -346
- package/dist/consoleFmt.cjs +0 -85
- package/dist/consoleFmt.d.cts +0 -54
- package/dist/consoleFmt.d.ts +0 -54
- package/dist/consoleFmt.js +0 -60
- package/dist/conversions.cjs +0 -44
- package/dist/conversions.d.cts +0 -3
- package/dist/conversions.d.ts +0 -3
- package/dist/conversions.js +0 -6
- package/dist/createThrottleController.cjs +0 -193
- package/dist/createThrottleController.d.cts +0 -13
- package/dist/createThrottleController.d.ts +0 -13
- package/dist/createThrottleController.js +0 -61
- package/dist/debounce.cjs +0 -157
- package/dist/debounce.d.cts +0 -46
- package/dist/debounce.d.ts +0 -46
- package/dist/debounce.js +0 -8
- package/dist/dedent.cjs +0 -104
- package/dist/dedent.d.cts +0 -73
- package/dist/dedent.d.ts +0 -73
- package/dist/dedent.js +0 -79
- package/dist/deepEqual.cjs +0 -96
- package/dist/deepEqual.d.ts +0 -21
- package/dist/deepEqual.js +0 -8
- package/dist/deepReplaceValues.cjs +0 -87
- package/dist/deepReplaceValues.d.ts +0 -27
- package/dist/deepReplaceValues.js +0 -7
- package/dist/enhancedMap.cjs +0 -131
- package/dist/enhancedMap.d.cts +0 -20
- package/dist/enhancedMap.d.ts +0 -20
- package/dist/enhancedMap.js +0 -10
- package/dist/exhaustiveMatch.cjs +0 -66
- package/dist/exhaustiveMatch.d.cts +0 -9
- package/dist/exhaustiveMatch.d.ts +0 -9
- package/dist/exhaustiveMatch.js +0 -40
- package/dist/filterObjectOrArrayKeys.cjs +0 -619
- package/dist/filterObjectOrArrayKeys.d.ts +0 -88
- package/dist/filterObjectOrArrayKeys.js +0 -9
- package/dist/getAutoIncrementId.cjs +0 -44
- package/dist/getAutoIncrementId.d.ts +0 -46
- package/dist/getAutoIncrementId.js +0 -18
- package/dist/getCompositeKey.cjs +0 -86
- package/dist/getCompositeKey.d.ts +0 -11
- package/dist/getCompositeKey.js +0 -8
- package/dist/getValueStableKey.cjs +0 -89
- package/dist/getValueStableKey.d.ts +0 -15
- package/dist/getValueStableKey.js +0 -11
- package/dist/hash.cjs +0 -57
- package/dist/hash.d.ts +0 -7
- package/dist/hash.js +0 -32
- package/dist/interpolate.cjs +0 -88
- package/dist/interpolate.d.cts +0 -11
- package/dist/interpolate.d.ts +0 -11
- package/dist/interpolate.js +0 -46
- package/dist/iteratorUtils.cjs +0 -73
- package/dist/iteratorUtils.d.ts +0 -10
- package/dist/iteratorUtils.js +0 -44
- package/dist/keepPrevIfUnchanged.cjs +0 -102
- package/dist/keepPrevIfUnchanged.d.cts +0 -7
- package/dist/keepPrevIfUnchanged.d.ts +0 -7
- package/dist/keepPrevIfUnchanged.js +0 -7
- package/dist/keyedMap.cjs +0 -224
- package/dist/keyedMap.d.cts +0 -75
- package/dist/keyedMap.d.ts +0 -75
- package/dist/keyedMap.js +0 -145
- package/dist/keyedSet.cjs +0 -205
- package/dist/keyedSet.d.cts +0 -76
- package/dist/keyedSet.d.ts +0 -76
- package/dist/keyedSet.js +0 -126
- package/dist/levenshtein.cjs +0 -180
- package/dist/levenshtein.d.ts +0 -5
- package/dist/levenshtein.js +0 -153
- package/dist/main.cjs +0 -32
- package/dist/main.d.cts +0 -3
- package/dist/main.d.ts +0 -3
- package/dist/main.js +0 -7
- package/dist/matchPath.cjs +0 -155
- package/dist/matchPath.d.cts +0 -53
- package/dist/matchPath.d.ts +0 -53
- package/dist/matchPath.js +0 -108
- package/dist/mathUtils.cjs +0 -81
- package/dist/mathUtils.d.ts +0 -54
- package/dist/mathUtils.js +0 -22
- package/dist/mutationUtils.cjs +0 -153
- package/dist/mutationUtils.d.ts +0 -15
- package/dist/mutationUtils.js +0 -55
- package/dist/objUtils.cjs +0 -242
- package/dist/objUtils.d.cts +0 -28
- package/dist/objUtils.js +0 -38
- package/dist/parallelAsyncCalls.cjs +0 -162
- package/dist/parallelAsyncCalls.d.cts +0 -82
- package/dist/parallelAsyncCalls.d.ts +0 -82
- package/dist/parallelAsyncCalls.js +0 -126
- package/dist/partialEqual.cjs +0 -1196
- package/dist/partialEqual.d.cts +0 -141
- package/dist/partialEqual.d.ts +0 -141
- package/dist/partialEqual.js +0 -1168
- package/dist/promiseUtils.cjs +0 -38
- package/dist/promiseUtils.d.cts +0 -8
- package/dist/promiseUtils.d.ts +0 -8
- package/dist/promiseUtils.js +0 -6
- package/dist/regexUtils.cjs +0 -60
- package/dist/regexUtils.d.cts +0 -17
- package/dist/regexUtils.d.ts +0 -17
- package/dist/regexUtils.js +0 -33
- package/dist/retryOnError.cjs +0 -130
- package/dist/retryOnError.d.ts +0 -83
- package/dist/retryOnError.js +0 -101
- package/dist/runShellCmd.cjs +0 -127
- package/dist/runShellCmd.d.cts +0 -90
- package/dist/runShellCmd.js +0 -98
- package/dist/safeJson.cjs +0 -45
- package/dist/safeJson.d.ts +0 -16
- package/dist/safeJson.js +0 -8
- package/dist/saferTyping.cjs +0 -52
- package/dist/saferTyping.d.ts +0 -47
- package/dist/saferTyping.js +0 -23
- package/dist/serializeXML.cjs +0 -154
- package/dist/serializeXML.d.cts +0 -22
- package/dist/serializeXML.d.ts +0 -22
- package/dist/serializeXML.js +0 -116
- package/dist/shallowEqual.cjs +0 -88
- package/dist/shallowEqual.d.ts +0 -4
- package/dist/shallowEqual.js +0 -63
- package/dist/sleep.cjs +0 -32
- package/dist/sleep.d.cts +0 -3
- package/dist/sleep.d.ts +0 -3
- package/dist/sleep.js +0 -6
- package/dist/stringUtils.cjs +0 -155
- package/dist/stringUtils.d.ts +0 -55
- package/dist/stringUtils.js +0 -50
- package/dist/testUtils.cjs +0 -1490
- package/dist/testUtils.d.cts +0 -133
- package/dist/testUtils.js +0 -359
- package/dist/throttle.cjs +0 -282
- package/dist/throttle.d.cts +0 -98
- package/dist/throttle.js +0 -38
- package/dist/time.cjs +0 -152
- package/dist/time.d.cts +0 -25
- package/dist/time.js +0 -38
- package/dist/timers.cjs +0 -194
- package/dist/timers.d.ts +0 -121
- package/dist/timers.js +0 -156
- package/dist/tsResult.cjs +0 -226
- package/dist/tsResult.d.ts +0 -114
- package/dist/tsResult.js +0 -180
- package/dist/typeGuards.cjs +0 -70
- package/dist/typeGuards.d.ts +0 -111
- package/dist/typeGuards.js +0 -18
- package/dist/typeUtils.cjs +0 -18
- package/dist/typeUtils.d.cts +0 -61
- package/dist/typeUtils.js +0 -0
- package/dist/typedStrings.cjs +0 -90
- package/dist/typedStrings.d.ts +0 -163
- package/dist/typedStrings.js +0 -57
- package/dist/typingFnUtils.cjs +0 -96
- package/dist/typingFnUtils.d.ts +0 -100
- package/dist/typingFnUtils.js +0 -30
- package/dist/typingTestUtils.cjs +0 -52
- package/dist/typingTestUtils.d.ts +0 -79
- package/dist/typingTestUtils.js +0 -27
- package/dist/typingUtils.cjs +0 -18
- package/dist/typingUtils.d.cts +0 -35
- package/dist/typingUtils.d.ts +0 -35
- package/dist/typingUtils.js +0 -0
- package/dist/yamlStringify.cjs +0 -423
- package/dist/yamlStringify.d.cts +0 -10
- package/dist/yamlStringify.d.ts +0 -10
- package/dist/yamlStringify.js +0 -9
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { __LEGIT_ANY__ } from
|
|
1
|
+
import { __LEGIT_ANY__ } from "./saferTyping.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/awaitDebounce.d.ts
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Creates an awaitable debounce mechanism that allows you to debounce async
|
|
@@ -33,9 +35,12 @@ import { __LEGIT_ANY__ } from './saferTyping.cjs';
|
|
|
33
35
|
* @returns Promise that resolves to 'continue' if this call should proceed, or
|
|
34
36
|
* 'skip' if it was superseded
|
|
35
37
|
*/
|
|
36
|
-
declare function awaitDebounce({
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
declare function awaitDebounce({
|
|
39
|
+
callId: _callId,
|
|
40
|
+
debounce
|
|
41
|
+
}: {
|
|
42
|
+
callId: __LEGIT_ANY__;
|
|
43
|
+
debounce: number;
|
|
39
44
|
}): Promise<'continue' | 'skip'>;
|
|
40
|
-
|
|
41
|
-
export { awaitDebounce };
|
|
45
|
+
//#endregion
|
|
46
|
+
export { awaitDebounce };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { getCompositeKey } from "./getCompositeKey.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/awaitDebounce.ts
|
|
4
|
+
const resolvers = {};
|
|
5
|
+
const debouncers = {};
|
|
6
|
+
/**
|
|
7
|
+
* Creates an awaitable debounce mechanism that allows you to debounce async
|
|
8
|
+
* operations. When called multiple times with the same `callId`, only the last
|
|
9
|
+
* call will resolve with 'continue', while all previous calls resolve with
|
|
10
|
+
* 'skip'.
|
|
11
|
+
*
|
|
12
|
+
* This is useful for debouncing API calls, search operations, or any async work
|
|
13
|
+
* where you want to ensure only the most recent request is processed.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* async function searchUsers(query: string) {
|
|
18
|
+
* const result = await awaitDebounce({ callId: 'search', debounce: 300 });
|
|
19
|
+
* if (result === 'skip') return; // This search was superseded
|
|
20
|
+
*
|
|
21
|
+
* // Only the most recent search will reach here
|
|
22
|
+
* const users = await fetchUsers(query);
|
|
23
|
+
* updateUI(users);
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* // Called rapidly - only the last call will execute
|
|
27
|
+
* searchUsers('a');
|
|
28
|
+
* searchUsers('ab');
|
|
29
|
+
* searchUsers('abc'); // Only this one will continue
|
|
30
|
+
* ```;
|
|
31
|
+
*
|
|
32
|
+
* @param options - Configuration object
|
|
33
|
+
* @param options.callId - Unique identifier for the debounce group. Calls with
|
|
34
|
+
* the same ID are debounced together
|
|
35
|
+
* @param options.debounce - Debounce delay in milliseconds
|
|
36
|
+
* @returns Promise that resolves to 'continue' if this call should proceed, or
|
|
37
|
+
* 'skip' if it was superseded
|
|
38
|
+
*/
|
|
39
|
+
async function awaitDebounce({ callId: _callId, debounce }) {
|
|
40
|
+
const callId = getCompositeKey(_callId);
|
|
41
|
+
if (debouncers[callId]) clearTimeout(debouncers[callId]);
|
|
42
|
+
debouncers[callId] = globalThis.setTimeout(() => {
|
|
43
|
+
const resolve = resolvers[callId];
|
|
44
|
+
resolvers[callId] = void 0;
|
|
45
|
+
resolve?.("continue");
|
|
46
|
+
}, debounce);
|
|
47
|
+
if (resolvers[callId]) resolvers[callId]("skip");
|
|
48
|
+
return new Promise((resolve) => {
|
|
49
|
+
resolvers[callId] = resolve;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
//#endregion
|
|
54
|
+
export { awaitDebounce };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { DurationObj } from
|
|
1
|
+
import { DurationObj } from "./time.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/cache.d.ts
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Creates a cached getter that only calls the provided function once. The first
|
|
@@ -19,24 +21,24 @@ import { DurationObj } from './time.js';
|
|
|
19
21
|
* @returns Object with a `value` property that caches the result
|
|
20
22
|
*/
|
|
21
23
|
declare function cachedGetter<T>(getter: () => T): {
|
|
22
|
-
|
|
24
|
+
value: T;
|
|
23
25
|
};
|
|
24
26
|
type Options = {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
27
|
+
/**
|
|
28
|
+
* The maximum number of items in the cache.
|
|
29
|
+
*
|
|
30
|
+
* @default 1000
|
|
31
|
+
*/
|
|
32
|
+
maxCacheSize?: number;
|
|
33
|
+
/** The maximum age of items in the cache. */
|
|
34
|
+
maxItemAge?: DurationObj;
|
|
35
|
+
/**
|
|
36
|
+
* The throttle for checking expired items in milliseconds.
|
|
37
|
+
*
|
|
38
|
+
* @default
|
|
39
|
+
* 10_000
|
|
40
|
+
*/
|
|
41
|
+
expirationThrottle?: number;
|
|
40
42
|
};
|
|
41
43
|
/**
|
|
42
44
|
* Wrapper class that prevents a value from being cached. When returned from a
|
|
@@ -54,8 +56,8 @@ type Options = {
|
|
|
54
56
|
* });
|
|
55
57
|
*/
|
|
56
58
|
declare class SkipCaching<T> {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
value: T;
|
|
60
|
+
constructor(value: T);
|
|
59
61
|
}
|
|
60
62
|
/**
|
|
61
63
|
* Wrapper class that sets a custom expiration time for a cached value. Allows
|
|
@@ -77,53 +79,53 @@ declare class SkipCaching<T> {
|
|
|
77
79
|
* );
|
|
78
80
|
*/
|
|
79
81
|
declare class WithExpiration<T> {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
value: T;
|
|
83
|
+
expiration: number;
|
|
84
|
+
/**
|
|
85
|
+
* @param value - The value to store in the cache.
|
|
86
|
+
* @param expiration - The expiration time of the value in seconds or a
|
|
87
|
+
* duration object.
|
|
88
|
+
*/
|
|
89
|
+
constructor(value: T, expiration: DurationObj);
|
|
88
90
|
}
|
|
89
91
|
type Utils<T> = {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
92
|
+
skipCaching: (value: T) => SkipCaching<T>;
|
|
93
|
+
/**
|
|
94
|
+
* Create a new WithExpiration object with the given value and expiration
|
|
95
|
+
* time.
|
|
96
|
+
*
|
|
97
|
+
* @param value - The value to store in the cache.
|
|
98
|
+
* @param expiration - The expiration time of the value in seconds or a
|
|
99
|
+
* duration object.
|
|
100
|
+
*/
|
|
101
|
+
withExpiration: (value: T, expiration: DurationObj) => WithExpiration<T>;
|
|
100
102
|
};
|
|
101
103
|
type GetOptions<T> = {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
104
|
+
/**
|
|
105
|
+
* A function that determines whether a value should be rejected from being
|
|
106
|
+
* cached. If the function returns true, the value will be returned but not
|
|
107
|
+
* cached.
|
|
108
|
+
*
|
|
109
|
+
* @param value The value to check
|
|
110
|
+
* @returns True if the value should be rejected, false otherwise
|
|
111
|
+
*/
|
|
112
|
+
skipCachingWhen?: (value: T) => boolean;
|
|
111
113
|
};
|
|
112
114
|
type Cache<T> = {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
115
|
+
getOrInsert: (cacheKey: string, val: (utils: Utils<T>) => T | SkipCaching<T>, options?: GetOptions<T>) => T;
|
|
116
|
+
getOrInsertAsync: (cacheKey: string, val: (utils: Utils<T>) => Promise<T | SkipCaching<T>>, options?: GetOptions<T>) => Promise<T>;
|
|
117
|
+
clear: () => void;
|
|
118
|
+
get: (cacheKey: string) => T | undefined;
|
|
119
|
+
set: (cacheKey: string, value: T | WithExpiration<T>) => void;
|
|
120
|
+
cleanExpiredItems: () => void;
|
|
121
|
+
getAsync: (cacheKey: string) => Promise<T | undefined>;
|
|
122
|
+
setAsync: (cacheKey: string, value: (utils: Utils<T>) => Promise<T | WithExpiration<T>>) => Promise<T>;
|
|
123
|
+
[' cache']: {
|
|
124
|
+
map: Map<string, {
|
|
125
|
+
value: T | Promise<T>;
|
|
126
|
+
timestamp: number;
|
|
127
|
+
}>;
|
|
128
|
+
};
|
|
127
129
|
};
|
|
128
130
|
/**
|
|
129
131
|
* Creates a full-featured cache with time-based expiration, async support, and
|
|
@@ -189,9 +191,13 @@ type Cache<T> = {
|
|
|
189
191
|
* @returns A cache instance with various methods for storing and retrieving
|
|
190
192
|
* values
|
|
191
193
|
*/
|
|
192
|
-
declare function createCache<T>({
|
|
194
|
+
declare function createCache<T>({
|
|
195
|
+
maxCacheSize,
|
|
196
|
+
maxItemAge,
|
|
197
|
+
expirationThrottle
|
|
198
|
+
}?: Options): Cache<T>;
|
|
193
199
|
type FastCacheOptions = {
|
|
194
|
-
|
|
200
|
+
maxCacheSize?: number;
|
|
195
201
|
};
|
|
196
202
|
/**
|
|
197
203
|
* Creates a simple, fast cache with FIFO (First In, First Out) eviction policy.
|
|
@@ -219,10 +225,12 @@ type FastCacheOptions = {
|
|
|
219
225
|
* When exceeded, oldest items are removed first. Defaults to 1000.
|
|
220
226
|
* @returns An object with cache methods
|
|
221
227
|
*/
|
|
222
|
-
declare function fastCache<T>({
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
228
|
+
declare function fastCache<T>({
|
|
229
|
+
maxCacheSize
|
|
230
|
+
}?: FastCacheOptions): {
|
|
231
|
+
getOrInsert: (cacheKey: string, val: () => T) => T;
|
|
232
|
+
/** Clears all cached values */
|
|
233
|
+
clear: () => void;
|
|
226
234
|
};
|
|
227
|
-
|
|
228
|
-
export {
|
|
235
|
+
//#endregion
|
|
236
|
+
export { Cache, SkipCaching, WithExpiration, cachedGetter, createCache, fastCache };
|
package/dist/cache.mjs
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { c as isPromise } from "./assertions-qMxfVhSu.mjs";
|
|
2
|
+
import { p as durationObjToMs } from "./time-sr2lhQRw.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/cache.ts
|
|
5
|
+
/**
|
|
6
|
+
* Creates a cached getter that only calls the provided function once. The first
|
|
7
|
+
* access computes and caches the value; subsequent accesses return the cached
|
|
8
|
+
* result. This is useful for lazy initialization of expensive computations.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* const expensive = cachedGetter(() => {
|
|
12
|
+
* console.log('Computing...');
|
|
13
|
+
* return heavyComputation();
|
|
14
|
+
* });
|
|
15
|
+
*
|
|
16
|
+
* console.log(expensive.value); // Logs "Computing..." and returns result
|
|
17
|
+
* console.log(expensive.value); // Returns cached result without logging
|
|
18
|
+
* console.log(expensive.value); // Returns cached result without logging
|
|
19
|
+
*
|
|
20
|
+
* @param getter - Function that computes the value to cache
|
|
21
|
+
* @returns Object with a `value` property that caches the result
|
|
22
|
+
*/
|
|
23
|
+
function cachedGetter(getter) {
|
|
24
|
+
return { get value() {
|
|
25
|
+
const value = getter();
|
|
26
|
+
Object.defineProperty(this, "value", { value });
|
|
27
|
+
return value;
|
|
28
|
+
} };
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Wrapper class that prevents a value from being cached. When returned from a
|
|
32
|
+
* cache computation function, the value will be returned to the caller but not
|
|
33
|
+
* stored in the cache.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* const cache = createCache<string>();
|
|
37
|
+
* const result = cache.getOrInsert('dynamic', ({ skipCaching }) => {
|
|
38
|
+
* const data = generateData();
|
|
39
|
+
* if (data.isTemporary) {
|
|
40
|
+
* return skipCaching(data); // Won't be cached
|
|
41
|
+
* }
|
|
42
|
+
* return data; // Will be cached
|
|
43
|
+
* });
|
|
44
|
+
*/
|
|
45
|
+
var SkipCaching = class {
|
|
46
|
+
value;
|
|
47
|
+
constructor(value) {
|
|
48
|
+
this.value = value;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Wrapper class that sets a custom expiration time for a cached value. Allows
|
|
53
|
+
* individual cache entries to have different expiration times than the default
|
|
54
|
+
* cache expiration.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* const cache = createCache<string>({ maxItemAge: { hours: 1 } }); // Default 1 hour
|
|
58
|
+
*
|
|
59
|
+
* const result = cache.getOrInsert('short-lived', ({ withExpiration }) => {
|
|
60
|
+
* return withExpiration('temporary data', { minutes: 5 }); // Expires in 5 minutes
|
|
61
|
+
* });
|
|
62
|
+
*
|
|
63
|
+
* const longLived = cache.getOrInsert(
|
|
64
|
+
* 'long-lived',
|
|
65
|
+
* ({ withExpiration }) => {
|
|
66
|
+
* return withExpiration('persistent data', { days: 1 }); // Expires in 1 day
|
|
67
|
+
* },
|
|
68
|
+
* );
|
|
69
|
+
*/
|
|
70
|
+
var WithExpiration = class {
|
|
71
|
+
value;
|
|
72
|
+
expiration;
|
|
73
|
+
/**
|
|
74
|
+
* @param value - The value to store in the cache.
|
|
75
|
+
* @param expiration - The expiration time of the value in seconds or a
|
|
76
|
+
* duration object.
|
|
77
|
+
*/
|
|
78
|
+
constructor(value, expiration) {
|
|
79
|
+
this.value = value;
|
|
80
|
+
this.expiration = durationObjToMs(expiration);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Creates a full-featured cache with time-based expiration, async support, and
|
|
85
|
+
* advanced features. This is a more powerful alternative to `fastCache` when
|
|
86
|
+
* you need expiration, async operations, or advanced caching strategies.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* // Basic usage with expiration
|
|
90
|
+
* const cache = createCache<string>({
|
|
91
|
+
* maxCacheSize: 100,
|
|
92
|
+
* maxItemAge: { minutes: 5 },
|
|
93
|
+
* });
|
|
94
|
+
*
|
|
95
|
+
* // Simple caching
|
|
96
|
+
* const result = cache.getOrInsert('user:123', () => {
|
|
97
|
+
* return fetchUserFromDatabase('123');
|
|
98
|
+
* });
|
|
99
|
+
*
|
|
100
|
+
* // Async caching with promise deduplication
|
|
101
|
+
* const asyncResult = await cache.getOrInsertAsync(
|
|
102
|
+
* 'api:data',
|
|
103
|
+
* async () => {
|
|
104
|
+
* return await fetchFromApi('/data');
|
|
105
|
+
* },
|
|
106
|
+
* );
|
|
107
|
+
*
|
|
108
|
+
* // Skip caching for certain values
|
|
109
|
+
* const value = cache.getOrInsert('dynamic', ({ skipCaching }) => {
|
|
110
|
+
* const data = generateDynamicData();
|
|
111
|
+
* if (data.shouldNotCache) {
|
|
112
|
+
* return skipCaching(data); // Won't be cached
|
|
113
|
+
* }
|
|
114
|
+
* return data;
|
|
115
|
+
* });
|
|
116
|
+
*
|
|
117
|
+
* // Custom expiration per item
|
|
118
|
+
* const shortLivedValue = cache.getOrInsert(
|
|
119
|
+
* 'temp',
|
|
120
|
+
* ({ withExpiration }) => {
|
|
121
|
+
* return withExpiration('temporary data', { seconds: 30 });
|
|
122
|
+
* },
|
|
123
|
+
* );
|
|
124
|
+
*
|
|
125
|
+
* // Conditional caching based on the computed value
|
|
126
|
+
* const result = cache.getOrInsert(
|
|
127
|
+
* 'conditional',
|
|
128
|
+
* () => {
|
|
129
|
+
* return computeValue();
|
|
130
|
+
* },
|
|
131
|
+
* {
|
|
132
|
+
* skipCachingWhen: (value) => value === null || value.error,
|
|
133
|
+
* },
|
|
134
|
+
* );
|
|
135
|
+
*
|
|
136
|
+
* @param options - Configuration options for the cache
|
|
137
|
+
* @param options.maxCacheSize - Maximum number of items to store. When
|
|
138
|
+
* exceeded, oldest items are removed first. Defaults to 1000.
|
|
139
|
+
* @param options.maxItemAge - Default expiration time for all cached items.
|
|
140
|
+
* Items older than this will be automatically removed.
|
|
141
|
+
* @param options.expirationThrottle - Minimum time in milliseconds between
|
|
142
|
+
* expiration cleanup runs. Prevents excessive cleanup operations. Defaults to
|
|
143
|
+
* 10,000ms.
|
|
144
|
+
* @returns A cache instance with various methods for storing and retrieving
|
|
145
|
+
* values
|
|
146
|
+
*/
|
|
147
|
+
function createCache({ maxCacheSize = 1e3, maxItemAge, expirationThrottle = 1e4 } = {}) {
|
|
148
|
+
const cache = /* @__PURE__ */ new Map();
|
|
149
|
+
let lastExpirationCheck = 0;
|
|
150
|
+
const defaultMaxItemAgeMs = maxItemAge && durationObjToMs(maxItemAge);
|
|
151
|
+
function cleanExpiredItems() {
|
|
152
|
+
const now = Date.now();
|
|
153
|
+
if (!defaultMaxItemAgeMs || now - lastExpirationCheck < expirationThrottle) return;
|
|
154
|
+
lastExpirationCheck = now;
|
|
155
|
+
for (const [key, item] of cache.entries()) if (isExpired(item, now)) cache.delete(key);
|
|
156
|
+
}
|
|
157
|
+
function trimToSize() {
|
|
158
|
+
const currentSize = cache.size;
|
|
159
|
+
if (currentSize > maxCacheSize) {
|
|
160
|
+
const keysToRemove = currentSize - maxCacheSize;
|
|
161
|
+
const iterator = cache.keys();
|
|
162
|
+
for (let i = 0; i < keysToRemove; i++) {
|
|
163
|
+
const { value: key } = iterator.next();
|
|
164
|
+
if (key) cache.delete(key);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function isExpired(entry, now) {
|
|
169
|
+
const maxItemAgeMs = entry.expiration ?? defaultMaxItemAgeMs;
|
|
170
|
+
return !!maxItemAgeMs && now - entry.timestamp > maxItemAgeMs;
|
|
171
|
+
}
|
|
172
|
+
function unwrapValue(value, now) {
|
|
173
|
+
if (value instanceof WithExpiration) return {
|
|
174
|
+
value: value.value,
|
|
175
|
+
timestamp: now,
|
|
176
|
+
expiration: value.expiration ? typeof value.expiration === "number" ? value.expiration : now + durationObjToMs(value.expiration) : void 0
|
|
177
|
+
};
|
|
178
|
+
return {
|
|
179
|
+
value,
|
|
180
|
+
timestamp: now,
|
|
181
|
+
expiration: void 0
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
const utils = {
|
|
185
|
+
skipCaching: (value) => new SkipCaching(value),
|
|
186
|
+
withExpiration: (value, expiration) => {
|
|
187
|
+
return new WithExpiration(value, expiration);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
function refreshEntry(key, now) {
|
|
191
|
+
const entry = cache.get(key);
|
|
192
|
+
if (entry && !isExpired(entry, now)) {
|
|
193
|
+
cache.delete(key);
|
|
194
|
+
cache.set(key, entry);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
getOrInsert(cacheKey, val, options) {
|
|
199
|
+
const now = Date.now();
|
|
200
|
+
const entry = cache.get(cacheKey);
|
|
201
|
+
if (!entry || isExpired(entry, now)) {
|
|
202
|
+
const value = val(utils);
|
|
203
|
+
if (value instanceof SkipCaching) return value.value;
|
|
204
|
+
if (options?.skipCachingWhen?.(value)) return value;
|
|
205
|
+
const unwrappedValue = unwrapValue(value, now);
|
|
206
|
+
cache.set(cacheKey, unwrappedValue);
|
|
207
|
+
trimToSize();
|
|
208
|
+
cleanExpiredItems();
|
|
209
|
+
return unwrappedValue.value;
|
|
210
|
+
}
|
|
211
|
+
if (isPromise(entry.value)) throw new Error("Cache value is a promise, use getOrInsertAsync instead");
|
|
212
|
+
refreshEntry(cacheKey, now);
|
|
213
|
+
return entry.value;
|
|
214
|
+
},
|
|
215
|
+
async getOrInsertAsync(cacheKey, val, options) {
|
|
216
|
+
const entry = cache.get(cacheKey);
|
|
217
|
+
if (entry && isPromise(entry.value)) return entry.value;
|
|
218
|
+
const now = Date.now();
|
|
219
|
+
if (entry && !isExpired(entry, now)) {
|
|
220
|
+
refreshEntry(cacheKey, now);
|
|
221
|
+
return entry.value;
|
|
222
|
+
}
|
|
223
|
+
const promise = val(utils).then((result) => {
|
|
224
|
+
if (result instanceof SkipCaching) {
|
|
225
|
+
if (cache.get(cacheKey)?.value === promise) cache.delete(cacheKey);
|
|
226
|
+
return result.value;
|
|
227
|
+
}
|
|
228
|
+
if (options?.skipCachingWhen?.(result)) {
|
|
229
|
+
if (cache.get(cacheKey)?.value === promise) cache.delete(cacheKey);
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
const unwrappedValue = unwrapValue(result, Date.now());
|
|
233
|
+
cache.set(cacheKey, unwrappedValue);
|
|
234
|
+
return unwrappedValue.value;
|
|
235
|
+
}).catch((error) => {
|
|
236
|
+
cache.delete(cacheKey);
|
|
237
|
+
throw error;
|
|
238
|
+
});
|
|
239
|
+
cache.set(cacheKey, {
|
|
240
|
+
value: promise,
|
|
241
|
+
timestamp: now,
|
|
242
|
+
expiration: void 0
|
|
243
|
+
});
|
|
244
|
+
trimToSize();
|
|
245
|
+
cleanExpiredItems();
|
|
246
|
+
return promise;
|
|
247
|
+
},
|
|
248
|
+
clear() {
|
|
249
|
+
cache.clear();
|
|
250
|
+
},
|
|
251
|
+
get(cacheKey) {
|
|
252
|
+
const entry = cache.get(cacheKey);
|
|
253
|
+
const now = Date.now();
|
|
254
|
+
if (!entry || isExpired(entry, now)) return;
|
|
255
|
+
if (isPromise(entry.value)) throw new Error("Cache value is a promise, use getAsync instead");
|
|
256
|
+
refreshEntry(cacheKey, now);
|
|
257
|
+
return entry.value;
|
|
258
|
+
},
|
|
259
|
+
set(cacheKey, value) {
|
|
260
|
+
cache.set(cacheKey, unwrapValue(value, Date.now()));
|
|
261
|
+
trimToSize();
|
|
262
|
+
cleanExpiredItems();
|
|
263
|
+
},
|
|
264
|
+
async getAsync(cacheKey) {
|
|
265
|
+
const entry = cache.get(cacheKey);
|
|
266
|
+
const now = Date.now();
|
|
267
|
+
if (!entry || isExpired(entry, now)) return;
|
|
268
|
+
refreshEntry(cacheKey, now);
|
|
269
|
+
return entry.value;
|
|
270
|
+
},
|
|
271
|
+
async setAsync(cacheKey, value) {
|
|
272
|
+
const promise = value(utils).then((result) => {
|
|
273
|
+
if (result instanceof SkipCaching) {
|
|
274
|
+
if (cache.get(cacheKey)?.value === promise) cache.delete(cacheKey);
|
|
275
|
+
return result.value;
|
|
276
|
+
}
|
|
277
|
+
const unwrappedValue = unwrapValue(result, Date.now());
|
|
278
|
+
cache.set(cacheKey, unwrappedValue);
|
|
279
|
+
return unwrappedValue.value;
|
|
280
|
+
}).catch((error) => {
|
|
281
|
+
cache.delete(cacheKey);
|
|
282
|
+
throw error;
|
|
283
|
+
});
|
|
284
|
+
cache.set(cacheKey, {
|
|
285
|
+
value: promise,
|
|
286
|
+
timestamp: Date.now(),
|
|
287
|
+
expiration: void 0
|
|
288
|
+
});
|
|
289
|
+
trimToSize();
|
|
290
|
+
cleanExpiredItems();
|
|
291
|
+
return promise;
|
|
292
|
+
},
|
|
293
|
+
cleanExpiredItems,
|
|
294
|
+
" cache": { map: cache }
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Creates a simple, fast cache with FIFO (First In, First Out) eviction policy.
|
|
299
|
+
* This is a lightweight alternative to `createCache` for basic caching needs
|
|
300
|
+
* without expiration, async support, or advanced features.
|
|
301
|
+
*
|
|
302
|
+
* @example
|
|
303
|
+
* const cache = fastCache<string>({ maxCacheSize: 100 });
|
|
304
|
+
*
|
|
305
|
+
* // Cache expensive computation
|
|
306
|
+
* const result = cache.getOrInsert('user:123', () => {
|
|
307
|
+
* return fetchUserFromDatabase('123');
|
|
308
|
+
* });
|
|
309
|
+
*
|
|
310
|
+
* // Subsequent calls return cached value without re-computation
|
|
311
|
+
* const cachedResult = cache.getOrInsert('user:123', () => {
|
|
312
|
+
* return fetchUserFromDatabase('123'); // Won't be called
|
|
313
|
+
* });
|
|
314
|
+
*
|
|
315
|
+
* // Clear all cached values
|
|
316
|
+
* cache.clear();
|
|
317
|
+
*
|
|
318
|
+
* @param options - Configuration options for the cache
|
|
319
|
+
* @param options.maxCacheSize - Maximum number of items to store in the cache.
|
|
320
|
+
* When exceeded, oldest items are removed first. Defaults to 1000.
|
|
321
|
+
* @returns An object with cache methods
|
|
322
|
+
*/
|
|
323
|
+
function fastCache({ maxCacheSize = 1e3 } = {}) {
|
|
324
|
+
const cache = /* @__PURE__ */ new Map();
|
|
325
|
+
function trimCache() {
|
|
326
|
+
const cacheSize = cache.size;
|
|
327
|
+
if (cacheSize > maxCacheSize) {
|
|
328
|
+
const keys = Array.from(cache.keys());
|
|
329
|
+
for (let i = 0; i < cacheSize - maxCacheSize; i++) cache.delete(keys[i]);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Gets a value from the cache or computes and stores it if not present.
|
|
334
|
+
*
|
|
335
|
+
* @param cacheKey - The key to store/retrieve the value under
|
|
336
|
+
* @param val - Function that computes the value if not cached
|
|
337
|
+
* @returns The cached or newly computed value
|
|
338
|
+
*/
|
|
339
|
+
function getOrInsert(cacheKey, val) {
|
|
340
|
+
if (!cache.has(cacheKey)) {
|
|
341
|
+
const value = val();
|
|
342
|
+
cache.set(cacheKey, value);
|
|
343
|
+
trimCache();
|
|
344
|
+
return cache.get(cacheKey) ?? value;
|
|
345
|
+
}
|
|
346
|
+
return cache.get(cacheKey);
|
|
347
|
+
}
|
|
348
|
+
return {
|
|
349
|
+
getOrInsert,
|
|
350
|
+
clear: () => cache.clear()
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
//#endregion
|
|
355
|
+
export { SkipCaching, WithExpiration, cachedGetter, createCache, fastCache };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/castValues.ts
|
|
2
|
+
function castToString(value) {
|
|
3
|
+
const valueType = typeof value;
|
|
4
|
+
return valueType === "string" || valueType === "number" || valueType === "boolean" || valueType === "bigint" ? String(value) : null;
|
|
5
|
+
}
|
|
6
|
+
function castToNumber(value) {
|
|
7
|
+
return isFiniteNumeric(value) ? Number(value) : null;
|
|
8
|
+
}
|
|
9
|
+
function isFiniteNumeric(num) {
|
|
10
|
+
switch (typeof num) {
|
|
11
|
+
case "number": return num - num === 0;
|
|
12
|
+
case "string": return num.trim() !== "" && Number.isFinite(+num);
|
|
13
|
+
case "bigint": return Number.isFinite(Number(num));
|
|
14
|
+
default: return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { castToString as n, castToNumber as t };
|