@ls-stack/utils 3.46.0 → 3.48.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/cache.cjs +82 -4
- package/dist/cache.d.cts +143 -0
- package/dist/cache.d.ts +143 -0
- package/dist/cache.js +1 -1
- package/dist/{chunk-OIAGLRII.js → chunk-AULH7VMS.js} +82 -4
- package/dist/chunk-PUKVXYYL.js +52 -0
- package/dist/deepReplaceValues.cjs +87 -0
- package/dist/deepReplaceValues.d.cts +27 -0
- package/dist/deepReplaceValues.d.ts +27 -0
- package/dist/deepReplaceValues.js +7 -0
- package/dist/matchPath.cjs +8 -2
- package/dist/matchPath.js +1 -1
- package/dist/partialEqual.cjs +432 -1
- package/dist/partialEqual.d.cts +9 -0
- package/dist/partialEqual.d.ts +9 -0
- package/dist/partialEqual.js +432 -1
- package/dist/testUtils.cjs +46 -41
- package/dist/testUtils.js +6 -43
- package/package.json +5 -1
package/dist/cache.cjs
CHANGED
|
@@ -139,7 +139,26 @@ function createCache({
|
|
|
139
139
|
return new WithExpiration(value, expiration);
|
|
140
140
|
}
|
|
141
141
|
};
|
|
142
|
+
function refreshEntry(key, now) {
|
|
143
|
+
const entry = cache.get(key);
|
|
144
|
+
if (entry && !isExpired(entry, now)) {
|
|
145
|
+
cache.delete(key);
|
|
146
|
+
cache.set(key, entry);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
142
149
|
return {
|
|
150
|
+
/**
|
|
151
|
+
* Gets a value from the cache or computes and stores it if not present.
|
|
152
|
+
* This is the primary method for synchronous caching operations.
|
|
153
|
+
*
|
|
154
|
+
* @param cacheKey - Unique key to identify the cached value
|
|
155
|
+
* @param val - Function that computes the value if not cached. Receives
|
|
156
|
+
* utility functions for advanced features.
|
|
157
|
+
* @param options - Optional configuration for this specific get operation
|
|
158
|
+
* @returns The cached or newly computed value
|
|
159
|
+
* @throws Error if the cached value is a promise (use getOrInsertAsync
|
|
160
|
+
* instead)
|
|
161
|
+
*/
|
|
143
162
|
getOrInsert(cacheKey, val, options) {
|
|
144
163
|
const now = Date.now();
|
|
145
164
|
const entry = cache.get(cacheKey);
|
|
@@ -162,8 +181,20 @@ function createCache({
|
|
|
162
181
|
"Cache value is a promise, use getOrInsertAsync instead"
|
|
163
182
|
);
|
|
164
183
|
}
|
|
184
|
+
refreshEntry(cacheKey, now);
|
|
165
185
|
return entry.value;
|
|
166
186
|
},
|
|
187
|
+
/**
|
|
188
|
+
* Gets a value from the cache or computes and stores it asynchronously.
|
|
189
|
+
* Provides promise deduplication - concurrent calls with the same key will
|
|
190
|
+
* share the same promise.
|
|
191
|
+
*
|
|
192
|
+
* @param cacheKey - Unique key to identify the cached value
|
|
193
|
+
* @param val - Async function that computes the value if not cached.
|
|
194
|
+
* Receives utility functions for advanced features.
|
|
195
|
+
* @param options - Optional configuration for this specific get operation
|
|
196
|
+
* @returns Promise that resolves to the cached or newly computed value
|
|
197
|
+
*/
|
|
167
198
|
async getOrInsertAsync(cacheKey, val, options) {
|
|
168
199
|
const entry = cache.get(cacheKey);
|
|
169
200
|
if (entry && isPromise2(entry.value)) {
|
|
@@ -171,6 +202,7 @@ function createCache({
|
|
|
171
202
|
}
|
|
172
203
|
const now = Date.now();
|
|
173
204
|
if (entry && !isExpired(entry, now)) {
|
|
205
|
+
refreshEntry(cacheKey, now);
|
|
174
206
|
return entry.value;
|
|
175
207
|
}
|
|
176
208
|
const promise = val(utils).then((result) => {
|
|
@@ -204,31 +236,67 @@ function createCache({
|
|
|
204
236
|
cleanExpiredItems();
|
|
205
237
|
return promise;
|
|
206
238
|
},
|
|
239
|
+
/** Removes all items from the cache. */
|
|
207
240
|
clear() {
|
|
208
241
|
cache.clear();
|
|
209
242
|
},
|
|
243
|
+
/**
|
|
244
|
+
* Gets a value from the cache without computing it if missing. Returns
|
|
245
|
+
* undefined if the key doesn't exist or has expired.
|
|
246
|
+
*
|
|
247
|
+
* @param cacheKey - Key to look up in the cache
|
|
248
|
+
* @returns The cached value or undefined if not found/expired
|
|
249
|
+
* @throws Error if the cached value is a promise (use getAsync instead)
|
|
250
|
+
*/
|
|
210
251
|
get(cacheKey) {
|
|
211
252
|
const entry = cache.get(cacheKey);
|
|
212
|
-
|
|
253
|
+
const now = Date.now();
|
|
254
|
+
if (!entry || isExpired(entry, now)) {
|
|
213
255
|
return void 0;
|
|
214
256
|
}
|
|
215
257
|
if (isPromise2(entry.value)) {
|
|
216
258
|
throw new Error("Cache value is a promise, use getAsync instead");
|
|
217
259
|
}
|
|
260
|
+
refreshEntry(cacheKey, now);
|
|
218
261
|
return entry.value;
|
|
219
262
|
},
|
|
263
|
+
/**
|
|
264
|
+
* Manually sets a value in the cache.
|
|
265
|
+
*
|
|
266
|
+
* @param cacheKey - Key to store the value under
|
|
267
|
+
* @param value - Value to store, or WithExpiration wrapper for custom
|
|
268
|
+
* expiration
|
|
269
|
+
*/
|
|
220
270
|
set(cacheKey, value) {
|
|
221
271
|
cache.set(cacheKey, unwrapValue(value, Date.now()));
|
|
222
272
|
trimToSize();
|
|
223
273
|
cleanExpiredItems();
|
|
224
274
|
},
|
|
275
|
+
/**
|
|
276
|
+
* Gets a value from the cache without computing it if missing. Works with
|
|
277
|
+
* both sync and async cached values.
|
|
278
|
+
*
|
|
279
|
+
* @param cacheKey - Key to look up in the cache
|
|
280
|
+
* @returns Promise that resolves to the cached value or undefined if not
|
|
281
|
+
* found/expired
|
|
282
|
+
*/
|
|
225
283
|
async getAsync(cacheKey) {
|
|
226
284
|
const entry = cache.get(cacheKey);
|
|
227
|
-
|
|
285
|
+
const now = Date.now();
|
|
286
|
+
if (!entry || isExpired(entry, now)) {
|
|
228
287
|
return void 0;
|
|
229
288
|
}
|
|
289
|
+
refreshEntry(cacheKey, now);
|
|
230
290
|
return entry.value;
|
|
231
291
|
},
|
|
292
|
+
/**
|
|
293
|
+
* Manually sets an async value in the cache. The promise will be stored
|
|
294
|
+
* immediately and shared with concurrent requests.
|
|
295
|
+
*
|
|
296
|
+
* @param cacheKey - Key to store the value under
|
|
297
|
+
* @param value - Async function that returns the value to cache
|
|
298
|
+
* @returns Promise that resolves to the computed value
|
|
299
|
+
*/
|
|
232
300
|
async setAsync(cacheKey, value) {
|
|
233
301
|
const promise = value(utils).then((result) => {
|
|
234
302
|
if (result instanceof SkipCaching) {
|
|
@@ -254,6 +322,10 @@ function createCache({
|
|
|
254
322
|
cleanExpiredItems();
|
|
255
323
|
return promise;
|
|
256
324
|
},
|
|
325
|
+
/**
|
|
326
|
+
* Manually triggers cleanup of expired items. Normally this happens
|
|
327
|
+
* automatically during cache operations.
|
|
328
|
+
*/
|
|
257
329
|
cleanExpiredItems,
|
|
258
330
|
/** @internal */
|
|
259
331
|
" cache": { map: cache }
|
|
@@ -272,12 +344,18 @@ function fastCache({ maxCacheSize = 1e3 } = {}) {
|
|
|
272
344
|
}
|
|
273
345
|
function getOrInsert(cacheKey, val) {
|
|
274
346
|
if (!cache.has(cacheKey)) {
|
|
275
|
-
|
|
347
|
+
const value = val();
|
|
348
|
+
cache.set(cacheKey, value);
|
|
276
349
|
trimCache();
|
|
350
|
+
return cache.get(cacheKey) ?? value;
|
|
277
351
|
}
|
|
278
352
|
return cache.get(cacheKey);
|
|
279
353
|
}
|
|
280
|
-
return {
|
|
354
|
+
return {
|
|
355
|
+
getOrInsert,
|
|
356
|
+
/** Clears all cached values */
|
|
357
|
+
clear: () => cache.clear()
|
|
358
|
+
};
|
|
281
359
|
}
|
|
282
360
|
// Annotate the CommonJS export names for ESM import in node:
|
|
283
361
|
0 && (module.exports = {
|
package/dist/cache.d.cts
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import { DurationObj } from './time.cjs';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Creates a cached getter that only calls the provided function once. The first
|
|
5
|
+
* access computes and caches the value; subsequent accesses return the cached
|
|
6
|
+
* result. This is useful for lazy initialization of expensive computations.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const expensive = cachedGetter(() => {
|
|
10
|
+
* console.log('Computing...');
|
|
11
|
+
* return heavyComputation();
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* console.log(expensive.value); // Logs "Computing..." and returns result
|
|
15
|
+
* console.log(expensive.value); // Returns cached result without logging
|
|
16
|
+
* console.log(expensive.value); // Returns cached result without logging
|
|
17
|
+
*
|
|
18
|
+
* @param getter - Function that computes the value to cache
|
|
19
|
+
* @returns Object with a `value` property that caches the result
|
|
20
|
+
*/
|
|
3
21
|
declare function cachedGetter<T>(getter: () => T): {
|
|
4
22
|
value: T;
|
|
5
23
|
};
|
|
@@ -20,10 +38,44 @@ type Options = {
|
|
|
20
38
|
*/
|
|
21
39
|
expirationThrottle?: number;
|
|
22
40
|
};
|
|
41
|
+
/**
|
|
42
|
+
* Wrapper class that prevents a value from being cached. When returned from a
|
|
43
|
+
* cache computation function, the value will be returned to the caller but not
|
|
44
|
+
* stored in the cache.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* const cache = createCache<string>();
|
|
48
|
+
* const result = cache.getOrInsert('dynamic', ({ skipCaching }) => {
|
|
49
|
+
* const data = generateData();
|
|
50
|
+
* if (data.isTemporary) {
|
|
51
|
+
* return skipCaching(data); // Won't be cached
|
|
52
|
+
* }
|
|
53
|
+
* return data; // Will be cached
|
|
54
|
+
* });
|
|
55
|
+
*/
|
|
23
56
|
declare class SkipCaching<T> {
|
|
24
57
|
value: T;
|
|
25
58
|
constructor(value: T);
|
|
26
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Wrapper class that sets a custom expiration time for a cached value. Allows
|
|
62
|
+
* individual cache entries to have different expiration times than the default
|
|
63
|
+
* cache expiration.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* const cache = createCache<string>({ maxItemAge: { hours: 1 } }); // Default 1 hour
|
|
67
|
+
*
|
|
68
|
+
* const result = cache.getOrInsert('short-lived', ({ withExpiration }) => {
|
|
69
|
+
* return withExpiration('temporary data', { minutes: 5 }); // Expires in 5 minutes
|
|
70
|
+
* });
|
|
71
|
+
*
|
|
72
|
+
* const longLived = cache.getOrInsert(
|
|
73
|
+
* 'long-lived',
|
|
74
|
+
* ({ withExpiration }) => {
|
|
75
|
+
* return withExpiration('persistent data', { days: 1 }); // Expires in 1 day
|
|
76
|
+
* },
|
|
77
|
+
* );
|
|
78
|
+
*/
|
|
27
79
|
declare class WithExpiration<T> {
|
|
28
80
|
value: T;
|
|
29
81
|
expiration: number;
|
|
@@ -73,12 +125,103 @@ type Cache<T> = {
|
|
|
73
125
|
}>;
|
|
74
126
|
};
|
|
75
127
|
};
|
|
128
|
+
/**
|
|
129
|
+
* Creates a full-featured cache with time-based expiration, async support, and
|
|
130
|
+
* advanced features. This is a more powerful alternative to `fastCache` when
|
|
131
|
+
* you need expiration, async operations, or advanced caching strategies.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* // Basic usage with expiration
|
|
135
|
+
* const cache = createCache<string>({
|
|
136
|
+
* maxCacheSize: 100,
|
|
137
|
+
* maxItemAge: { minutes: 5 },
|
|
138
|
+
* });
|
|
139
|
+
*
|
|
140
|
+
* // Simple caching
|
|
141
|
+
* const result = cache.getOrInsert('user:123', () => {
|
|
142
|
+
* return fetchUserFromDatabase('123');
|
|
143
|
+
* });
|
|
144
|
+
*
|
|
145
|
+
* // Async caching with promise deduplication
|
|
146
|
+
* const asyncResult = await cache.getOrInsertAsync(
|
|
147
|
+
* 'api:data',
|
|
148
|
+
* async () => {
|
|
149
|
+
* return await fetchFromApi('/data');
|
|
150
|
+
* },
|
|
151
|
+
* );
|
|
152
|
+
*
|
|
153
|
+
* // Skip caching for certain values
|
|
154
|
+
* const value = cache.getOrInsert('dynamic', ({ skipCaching }) => {
|
|
155
|
+
* const data = generateDynamicData();
|
|
156
|
+
* if (data.shouldNotCache) {
|
|
157
|
+
* return skipCaching(data); // Won't be cached
|
|
158
|
+
* }
|
|
159
|
+
* return data;
|
|
160
|
+
* });
|
|
161
|
+
*
|
|
162
|
+
* // Custom expiration per item
|
|
163
|
+
* const shortLivedValue = cache.getOrInsert(
|
|
164
|
+
* 'temp',
|
|
165
|
+
* ({ withExpiration }) => {
|
|
166
|
+
* return withExpiration('temporary data', { seconds: 30 });
|
|
167
|
+
* },
|
|
168
|
+
* );
|
|
169
|
+
*
|
|
170
|
+
* // Conditional caching based on the computed value
|
|
171
|
+
* const result = cache.getOrInsert(
|
|
172
|
+
* 'conditional',
|
|
173
|
+
* () => {
|
|
174
|
+
* return computeValue();
|
|
175
|
+
* },
|
|
176
|
+
* {
|
|
177
|
+
* skipCachingWhen: (value) => value === null || value.error,
|
|
178
|
+
* },
|
|
179
|
+
* );
|
|
180
|
+
*
|
|
181
|
+
* @param options - Configuration options for the cache
|
|
182
|
+
* @param options.maxCacheSize - Maximum number of items to store. When
|
|
183
|
+
* exceeded, oldest items are removed first. Defaults to 1000.
|
|
184
|
+
* @param options.maxItemAge - Default expiration time for all cached items.
|
|
185
|
+
* Items older than this will be automatically removed.
|
|
186
|
+
* @param options.expirationThrottle - Minimum time in milliseconds between
|
|
187
|
+
* expiration cleanup runs. Prevents excessive cleanup operations. Defaults to
|
|
188
|
+
* 10,000ms.
|
|
189
|
+
* @returns A cache instance with various methods for storing and retrieving
|
|
190
|
+
* values
|
|
191
|
+
*/
|
|
76
192
|
declare function createCache<T>({ maxCacheSize, maxItemAge, expirationThrottle, }?: Options): Cache<T>;
|
|
77
193
|
type FastCacheOptions = {
|
|
78
194
|
maxCacheSize?: number;
|
|
79
195
|
};
|
|
196
|
+
/**
|
|
197
|
+
* Creates a simple, fast cache with FIFO (First In, First Out) eviction policy.
|
|
198
|
+
* This is a lightweight alternative to `createCache` for basic caching needs
|
|
199
|
+
* without expiration, async support, or advanced features.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* const cache = fastCache<string>({ maxCacheSize: 100 });
|
|
203
|
+
*
|
|
204
|
+
* // Cache expensive computation
|
|
205
|
+
* const result = cache.getOrInsert('user:123', () => {
|
|
206
|
+
* return fetchUserFromDatabase('123');
|
|
207
|
+
* });
|
|
208
|
+
*
|
|
209
|
+
* // Subsequent calls return cached value without re-computation
|
|
210
|
+
* const cachedResult = cache.getOrInsert('user:123', () => {
|
|
211
|
+
* return fetchUserFromDatabase('123'); // Won't be called
|
|
212
|
+
* });
|
|
213
|
+
*
|
|
214
|
+
* // Clear all cached values
|
|
215
|
+
* cache.clear();
|
|
216
|
+
*
|
|
217
|
+
* @param options - Configuration options for the cache
|
|
218
|
+
* @param options.maxCacheSize - Maximum number of items to store in the cache.
|
|
219
|
+
* When exceeded, oldest items are removed first. Defaults to 1000.
|
|
220
|
+
* @returns An object with cache methods
|
|
221
|
+
*/
|
|
80
222
|
declare function fastCache<T>({ maxCacheSize }?: FastCacheOptions): {
|
|
81
223
|
getOrInsert: (cacheKey: string, val: () => T) => T;
|
|
224
|
+
/** Clears all cached values */
|
|
82
225
|
clear: () => void;
|
|
83
226
|
};
|
|
84
227
|
|
package/dist/cache.d.ts
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import { DurationObj } from './time.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Creates a cached getter that only calls the provided function once. The first
|
|
5
|
+
* access computes and caches the value; subsequent accesses return the cached
|
|
6
|
+
* result. This is useful for lazy initialization of expensive computations.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const expensive = cachedGetter(() => {
|
|
10
|
+
* console.log('Computing...');
|
|
11
|
+
* return heavyComputation();
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* console.log(expensive.value); // Logs "Computing..." and returns result
|
|
15
|
+
* console.log(expensive.value); // Returns cached result without logging
|
|
16
|
+
* console.log(expensive.value); // Returns cached result without logging
|
|
17
|
+
*
|
|
18
|
+
* @param getter - Function that computes the value to cache
|
|
19
|
+
* @returns Object with a `value` property that caches the result
|
|
20
|
+
*/
|
|
3
21
|
declare function cachedGetter<T>(getter: () => T): {
|
|
4
22
|
value: T;
|
|
5
23
|
};
|
|
@@ -20,10 +38,44 @@ type Options = {
|
|
|
20
38
|
*/
|
|
21
39
|
expirationThrottle?: number;
|
|
22
40
|
};
|
|
41
|
+
/**
|
|
42
|
+
* Wrapper class that prevents a value from being cached. When returned from a
|
|
43
|
+
* cache computation function, the value will be returned to the caller but not
|
|
44
|
+
* stored in the cache.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* const cache = createCache<string>();
|
|
48
|
+
* const result = cache.getOrInsert('dynamic', ({ skipCaching }) => {
|
|
49
|
+
* const data = generateData();
|
|
50
|
+
* if (data.isTemporary) {
|
|
51
|
+
* return skipCaching(data); // Won't be cached
|
|
52
|
+
* }
|
|
53
|
+
* return data; // Will be cached
|
|
54
|
+
* });
|
|
55
|
+
*/
|
|
23
56
|
declare class SkipCaching<T> {
|
|
24
57
|
value: T;
|
|
25
58
|
constructor(value: T);
|
|
26
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Wrapper class that sets a custom expiration time for a cached value. Allows
|
|
62
|
+
* individual cache entries to have different expiration times than the default
|
|
63
|
+
* cache expiration.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* const cache = createCache<string>({ maxItemAge: { hours: 1 } }); // Default 1 hour
|
|
67
|
+
*
|
|
68
|
+
* const result = cache.getOrInsert('short-lived', ({ withExpiration }) => {
|
|
69
|
+
* return withExpiration('temporary data', { minutes: 5 }); // Expires in 5 minutes
|
|
70
|
+
* });
|
|
71
|
+
*
|
|
72
|
+
* const longLived = cache.getOrInsert(
|
|
73
|
+
* 'long-lived',
|
|
74
|
+
* ({ withExpiration }) => {
|
|
75
|
+
* return withExpiration('persistent data', { days: 1 }); // Expires in 1 day
|
|
76
|
+
* },
|
|
77
|
+
* );
|
|
78
|
+
*/
|
|
27
79
|
declare class WithExpiration<T> {
|
|
28
80
|
value: T;
|
|
29
81
|
expiration: number;
|
|
@@ -73,12 +125,103 @@ type Cache<T> = {
|
|
|
73
125
|
}>;
|
|
74
126
|
};
|
|
75
127
|
};
|
|
128
|
+
/**
|
|
129
|
+
* Creates a full-featured cache with time-based expiration, async support, and
|
|
130
|
+
* advanced features. This is a more powerful alternative to `fastCache` when
|
|
131
|
+
* you need expiration, async operations, or advanced caching strategies.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* // Basic usage with expiration
|
|
135
|
+
* const cache = createCache<string>({
|
|
136
|
+
* maxCacheSize: 100,
|
|
137
|
+
* maxItemAge: { minutes: 5 },
|
|
138
|
+
* });
|
|
139
|
+
*
|
|
140
|
+
* // Simple caching
|
|
141
|
+
* const result = cache.getOrInsert('user:123', () => {
|
|
142
|
+
* return fetchUserFromDatabase('123');
|
|
143
|
+
* });
|
|
144
|
+
*
|
|
145
|
+
* // Async caching with promise deduplication
|
|
146
|
+
* const asyncResult = await cache.getOrInsertAsync(
|
|
147
|
+
* 'api:data',
|
|
148
|
+
* async () => {
|
|
149
|
+
* return await fetchFromApi('/data');
|
|
150
|
+
* },
|
|
151
|
+
* );
|
|
152
|
+
*
|
|
153
|
+
* // Skip caching for certain values
|
|
154
|
+
* const value = cache.getOrInsert('dynamic', ({ skipCaching }) => {
|
|
155
|
+
* const data = generateDynamicData();
|
|
156
|
+
* if (data.shouldNotCache) {
|
|
157
|
+
* return skipCaching(data); // Won't be cached
|
|
158
|
+
* }
|
|
159
|
+
* return data;
|
|
160
|
+
* });
|
|
161
|
+
*
|
|
162
|
+
* // Custom expiration per item
|
|
163
|
+
* const shortLivedValue = cache.getOrInsert(
|
|
164
|
+
* 'temp',
|
|
165
|
+
* ({ withExpiration }) => {
|
|
166
|
+
* return withExpiration('temporary data', { seconds: 30 });
|
|
167
|
+
* },
|
|
168
|
+
* );
|
|
169
|
+
*
|
|
170
|
+
* // Conditional caching based on the computed value
|
|
171
|
+
* const result = cache.getOrInsert(
|
|
172
|
+
* 'conditional',
|
|
173
|
+
* () => {
|
|
174
|
+
* return computeValue();
|
|
175
|
+
* },
|
|
176
|
+
* {
|
|
177
|
+
* skipCachingWhen: (value) => value === null || value.error,
|
|
178
|
+
* },
|
|
179
|
+
* );
|
|
180
|
+
*
|
|
181
|
+
* @param options - Configuration options for the cache
|
|
182
|
+
* @param options.maxCacheSize - Maximum number of items to store. When
|
|
183
|
+
* exceeded, oldest items are removed first. Defaults to 1000.
|
|
184
|
+
* @param options.maxItemAge - Default expiration time for all cached items.
|
|
185
|
+
* Items older than this will be automatically removed.
|
|
186
|
+
* @param options.expirationThrottle - Minimum time in milliseconds between
|
|
187
|
+
* expiration cleanup runs. Prevents excessive cleanup operations. Defaults to
|
|
188
|
+
* 10,000ms.
|
|
189
|
+
* @returns A cache instance with various methods for storing and retrieving
|
|
190
|
+
* values
|
|
191
|
+
*/
|
|
76
192
|
declare function createCache<T>({ maxCacheSize, maxItemAge, expirationThrottle, }?: Options): Cache<T>;
|
|
77
193
|
type FastCacheOptions = {
|
|
78
194
|
maxCacheSize?: number;
|
|
79
195
|
};
|
|
196
|
+
/**
|
|
197
|
+
* Creates a simple, fast cache with FIFO (First In, First Out) eviction policy.
|
|
198
|
+
* This is a lightweight alternative to `createCache` for basic caching needs
|
|
199
|
+
* without expiration, async support, or advanced features.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* const cache = fastCache<string>({ maxCacheSize: 100 });
|
|
203
|
+
*
|
|
204
|
+
* // Cache expensive computation
|
|
205
|
+
* const result = cache.getOrInsert('user:123', () => {
|
|
206
|
+
* return fetchUserFromDatabase('123');
|
|
207
|
+
* });
|
|
208
|
+
*
|
|
209
|
+
* // Subsequent calls return cached value without re-computation
|
|
210
|
+
* const cachedResult = cache.getOrInsert('user:123', () => {
|
|
211
|
+
* return fetchUserFromDatabase('123'); // Won't be called
|
|
212
|
+
* });
|
|
213
|
+
*
|
|
214
|
+
* // Clear all cached values
|
|
215
|
+
* cache.clear();
|
|
216
|
+
*
|
|
217
|
+
* @param options - Configuration options for the cache
|
|
218
|
+
* @param options.maxCacheSize - Maximum number of items to store in the cache.
|
|
219
|
+
* When exceeded, oldest items are removed first. Defaults to 1000.
|
|
220
|
+
* @returns An object with cache methods
|
|
221
|
+
*/
|
|
80
222
|
declare function fastCache<T>({ maxCacheSize }?: FastCacheOptions): {
|
|
81
223
|
getOrInsert: (cacheKey: string, val: () => T) => T;
|
|
224
|
+
/** Clears all cached values */
|
|
82
225
|
clear: () => void;
|
|
83
226
|
};
|
|
84
227
|
|
package/dist/cache.js
CHANGED
|
@@ -86,7 +86,26 @@ function createCache({
|
|
|
86
86
|
return new WithExpiration(value, expiration);
|
|
87
87
|
}
|
|
88
88
|
};
|
|
89
|
+
function refreshEntry(key, now) {
|
|
90
|
+
const entry = cache.get(key);
|
|
91
|
+
if (entry && !isExpired(entry, now)) {
|
|
92
|
+
cache.delete(key);
|
|
93
|
+
cache.set(key, entry);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
89
96
|
return {
|
|
97
|
+
/**
|
|
98
|
+
* Gets a value from the cache or computes and stores it if not present.
|
|
99
|
+
* This is the primary method for synchronous caching operations.
|
|
100
|
+
*
|
|
101
|
+
* @param cacheKey - Unique key to identify the cached value
|
|
102
|
+
* @param val - Function that computes the value if not cached. Receives
|
|
103
|
+
* utility functions for advanced features.
|
|
104
|
+
* @param options - Optional configuration for this specific get operation
|
|
105
|
+
* @returns The cached or newly computed value
|
|
106
|
+
* @throws Error if the cached value is a promise (use getOrInsertAsync
|
|
107
|
+
* instead)
|
|
108
|
+
*/
|
|
90
109
|
getOrInsert(cacheKey, val, options) {
|
|
91
110
|
const now = Date.now();
|
|
92
111
|
const entry = cache.get(cacheKey);
|
|
@@ -109,8 +128,20 @@ function createCache({
|
|
|
109
128
|
"Cache value is a promise, use getOrInsertAsync instead"
|
|
110
129
|
);
|
|
111
130
|
}
|
|
131
|
+
refreshEntry(cacheKey, now);
|
|
112
132
|
return entry.value;
|
|
113
133
|
},
|
|
134
|
+
/**
|
|
135
|
+
* Gets a value from the cache or computes and stores it asynchronously.
|
|
136
|
+
* Provides promise deduplication - concurrent calls with the same key will
|
|
137
|
+
* share the same promise.
|
|
138
|
+
*
|
|
139
|
+
* @param cacheKey - Unique key to identify the cached value
|
|
140
|
+
* @param val - Async function that computes the value if not cached.
|
|
141
|
+
* Receives utility functions for advanced features.
|
|
142
|
+
* @param options - Optional configuration for this specific get operation
|
|
143
|
+
* @returns Promise that resolves to the cached or newly computed value
|
|
144
|
+
*/
|
|
114
145
|
async getOrInsertAsync(cacheKey, val, options) {
|
|
115
146
|
const entry = cache.get(cacheKey);
|
|
116
147
|
if (entry && isPromise(entry.value)) {
|
|
@@ -118,6 +149,7 @@ function createCache({
|
|
|
118
149
|
}
|
|
119
150
|
const now = Date.now();
|
|
120
151
|
if (entry && !isExpired(entry, now)) {
|
|
152
|
+
refreshEntry(cacheKey, now);
|
|
121
153
|
return entry.value;
|
|
122
154
|
}
|
|
123
155
|
const promise = val(utils).then((result) => {
|
|
@@ -151,31 +183,67 @@ function createCache({
|
|
|
151
183
|
cleanExpiredItems();
|
|
152
184
|
return promise;
|
|
153
185
|
},
|
|
186
|
+
/** Removes all items from the cache. */
|
|
154
187
|
clear() {
|
|
155
188
|
cache.clear();
|
|
156
189
|
},
|
|
190
|
+
/**
|
|
191
|
+
* Gets a value from the cache without computing it if missing. Returns
|
|
192
|
+
* undefined if the key doesn't exist or has expired.
|
|
193
|
+
*
|
|
194
|
+
* @param cacheKey - Key to look up in the cache
|
|
195
|
+
* @returns The cached value or undefined if not found/expired
|
|
196
|
+
* @throws Error if the cached value is a promise (use getAsync instead)
|
|
197
|
+
*/
|
|
157
198
|
get(cacheKey) {
|
|
158
199
|
const entry = cache.get(cacheKey);
|
|
159
|
-
|
|
200
|
+
const now = Date.now();
|
|
201
|
+
if (!entry || isExpired(entry, now)) {
|
|
160
202
|
return void 0;
|
|
161
203
|
}
|
|
162
204
|
if (isPromise(entry.value)) {
|
|
163
205
|
throw new Error("Cache value is a promise, use getAsync instead");
|
|
164
206
|
}
|
|
207
|
+
refreshEntry(cacheKey, now);
|
|
165
208
|
return entry.value;
|
|
166
209
|
},
|
|
210
|
+
/**
|
|
211
|
+
* Manually sets a value in the cache.
|
|
212
|
+
*
|
|
213
|
+
* @param cacheKey - Key to store the value under
|
|
214
|
+
* @param value - Value to store, or WithExpiration wrapper for custom
|
|
215
|
+
* expiration
|
|
216
|
+
*/
|
|
167
217
|
set(cacheKey, value) {
|
|
168
218
|
cache.set(cacheKey, unwrapValue(value, Date.now()));
|
|
169
219
|
trimToSize();
|
|
170
220
|
cleanExpiredItems();
|
|
171
221
|
},
|
|
222
|
+
/**
|
|
223
|
+
* Gets a value from the cache without computing it if missing. Works with
|
|
224
|
+
* both sync and async cached values.
|
|
225
|
+
*
|
|
226
|
+
* @param cacheKey - Key to look up in the cache
|
|
227
|
+
* @returns Promise that resolves to the cached value or undefined if not
|
|
228
|
+
* found/expired
|
|
229
|
+
*/
|
|
172
230
|
async getAsync(cacheKey) {
|
|
173
231
|
const entry = cache.get(cacheKey);
|
|
174
|
-
|
|
232
|
+
const now = Date.now();
|
|
233
|
+
if (!entry || isExpired(entry, now)) {
|
|
175
234
|
return void 0;
|
|
176
235
|
}
|
|
236
|
+
refreshEntry(cacheKey, now);
|
|
177
237
|
return entry.value;
|
|
178
238
|
},
|
|
239
|
+
/**
|
|
240
|
+
* Manually sets an async value in the cache. The promise will be stored
|
|
241
|
+
* immediately and shared with concurrent requests.
|
|
242
|
+
*
|
|
243
|
+
* @param cacheKey - Key to store the value under
|
|
244
|
+
* @param value - Async function that returns the value to cache
|
|
245
|
+
* @returns Promise that resolves to the computed value
|
|
246
|
+
*/
|
|
179
247
|
async setAsync(cacheKey, value) {
|
|
180
248
|
const promise = value(utils).then((result) => {
|
|
181
249
|
if (result instanceof SkipCaching) {
|
|
@@ -201,6 +269,10 @@ function createCache({
|
|
|
201
269
|
cleanExpiredItems();
|
|
202
270
|
return promise;
|
|
203
271
|
},
|
|
272
|
+
/**
|
|
273
|
+
* Manually triggers cleanup of expired items. Normally this happens
|
|
274
|
+
* automatically during cache operations.
|
|
275
|
+
*/
|
|
204
276
|
cleanExpiredItems,
|
|
205
277
|
/** @internal */
|
|
206
278
|
" cache": { map: cache }
|
|
@@ -219,12 +291,18 @@ function fastCache({ maxCacheSize = 1e3 } = {}) {
|
|
|
219
291
|
}
|
|
220
292
|
function getOrInsert(cacheKey, val) {
|
|
221
293
|
if (!cache.has(cacheKey)) {
|
|
222
|
-
|
|
294
|
+
const value = val();
|
|
295
|
+
cache.set(cacheKey, value);
|
|
223
296
|
trimCache();
|
|
297
|
+
return cache.get(cacheKey) ?? value;
|
|
224
298
|
}
|
|
225
299
|
return cache.get(cacheKey);
|
|
226
300
|
}
|
|
227
|
-
return {
|
|
301
|
+
return {
|
|
302
|
+
getOrInsert,
|
|
303
|
+
/** Clears all cached values */
|
|
304
|
+
clear: () => cache.clear()
|
|
305
|
+
};
|
|
228
306
|
}
|
|
229
307
|
|
|
230
308
|
export {
|