qznt 2.0.1 → 2.2.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/README.md +1 -0
- package/dist/index.cjs +56 -2
- package/dist/index.d.cts +36 -4
- package/dist/index.d.ts +36 -4
- package/dist/index.js +55 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -55,6 +55,7 @@ import { Cache, Storage } from "qznt";
|
|
|
55
55
|
// Cache with a 1-minute global TTL
|
|
56
56
|
const userCache = new Cache<UserData>(60000);
|
|
57
57
|
userCache.set("user_1", data);
|
|
58
|
+
userCache.delete("user_1");
|
|
58
59
|
|
|
59
60
|
// Persistent storage (Browser or NodeJS based)
|
|
60
61
|
const settings = new Storage("app_settings");
|
package/dist/index.cjs
CHANGED
|
@@ -63,6 +63,7 @@ __export(index_exports, {
|
|
|
63
63
|
isSortedArray: () => isSortedArray,
|
|
64
64
|
isString: () => isString,
|
|
65
65
|
isToday: () => isToday,
|
|
66
|
+
keyedQueue: () => keyedQueue,
|
|
66
67
|
lerp: () => lerp,
|
|
67
68
|
memoize: () => memoize,
|
|
68
69
|
merge: () => merge,
|
|
@@ -128,6 +129,14 @@ var Cache = class {
|
|
|
128
129
|
}
|
|
129
130
|
return data.value;
|
|
130
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Removes a single entry from the cache.
|
|
134
|
+
* @param key The key to remove
|
|
135
|
+
* @returns Whether an entry existed and was removed
|
|
136
|
+
*/
|
|
137
|
+
delete(key) {
|
|
138
|
+
return this.cache.delete(key);
|
|
139
|
+
}
|
|
131
140
|
cleanup() {
|
|
132
141
|
if (this.cache.size === 0) return;
|
|
133
142
|
const now = Date.now();
|
|
@@ -596,6 +605,24 @@ function unique(array, key) {
|
|
|
596
605
|
}
|
|
597
606
|
|
|
598
607
|
// src/async.ts
|
|
608
|
+
function keyedQueue() {
|
|
609
|
+
const queues = /* @__PURE__ */ new Map();
|
|
610
|
+
return {
|
|
611
|
+
run(key, work) {
|
|
612
|
+
const previous = queues.get(key) ?? Promise.resolve();
|
|
613
|
+
const result = previous.then(work);
|
|
614
|
+
const release = () => {
|
|
615
|
+
if (queues.get(key) === tail) queues.delete(key);
|
|
616
|
+
};
|
|
617
|
+
const tail = result.then(release, release);
|
|
618
|
+
queues.set(key, tail);
|
|
619
|
+
return result;
|
|
620
|
+
},
|
|
621
|
+
get size() {
|
|
622
|
+
return queues.size;
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
}
|
|
599
626
|
async function retryPromise(fn, options = {}) {
|
|
600
627
|
const { attempts = 3, delay = 500, timeout, signal } = options;
|
|
601
628
|
if (signal?.aborted) throw new Error("Operation aborted");
|
|
@@ -711,9 +738,28 @@ function throttle(fn, limit) {
|
|
|
711
738
|
function memoize(fn, options = {}) {
|
|
712
739
|
const cache = /* @__PURE__ */ new Map();
|
|
713
740
|
const { resolver, maxAge } = options;
|
|
741
|
+
let lastSweep = Date.now();
|
|
742
|
+
const getKey = (...args) => resolver ? resolver(...args) : JSON.stringify(args);
|
|
743
|
+
const sweep = (now) => {
|
|
744
|
+
if (!maxAge || now - lastSweep < maxAge) return;
|
|
745
|
+
lastSweep = now;
|
|
746
|
+
for (const [key, entry] of cache) {
|
|
747
|
+
if (now - entry.timestamp >= maxAge) cache.delete(key);
|
|
748
|
+
}
|
|
749
|
+
};
|
|
750
|
+
const cacheValue = (key, value, timestamp) => {
|
|
751
|
+
const entry = { value, timestamp };
|
|
752
|
+
cache.set(key, entry);
|
|
753
|
+
if (value !== null && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function") {
|
|
754
|
+
void Promise.resolve(value).catch(() => {
|
|
755
|
+
if (cache.get(key) === entry) cache.delete(key);
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
};
|
|
714
759
|
const memoized = function(...args) {
|
|
715
|
-
const key =
|
|
760
|
+
const key = getKey(...args);
|
|
716
761
|
const now = Date.now();
|
|
762
|
+
sweep(now);
|
|
717
763
|
const entry = cache.get(key);
|
|
718
764
|
if (entry) {
|
|
719
765
|
if (!maxAge || now - entry.timestamp < maxAge) {
|
|
@@ -722,10 +768,17 @@ function memoize(fn, options = {}) {
|
|
|
722
768
|
cache.delete(key);
|
|
723
769
|
}
|
|
724
770
|
const result = fn.apply(this, args);
|
|
725
|
-
|
|
771
|
+
cacheValue(key, result, now);
|
|
726
772
|
return result;
|
|
727
773
|
};
|
|
728
774
|
memoized.clear = () => cache.clear();
|
|
775
|
+
memoized.delete = (...args) => cache.delete(getKey(...args));
|
|
776
|
+
memoized.set = (value, ...args) => {
|
|
777
|
+
const key = getKey(...args);
|
|
778
|
+
const now = Date.now();
|
|
779
|
+
sweep(now);
|
|
780
|
+
cacheValue(key, value, now);
|
|
781
|
+
};
|
|
729
782
|
return memoized;
|
|
730
783
|
}
|
|
731
784
|
|
|
@@ -1072,6 +1125,7 @@ function toTitleCase(str, smart = true) {
|
|
|
1072
1125
|
isSortedArray,
|
|
1073
1126
|
isString,
|
|
1074
1127
|
isToday,
|
|
1128
|
+
keyedQueue,
|
|
1075
1129
|
lerp,
|
|
1076
1130
|
memoize,
|
|
1077
1131
|
merge,
|
package/dist/index.d.cts
CHANGED
|
@@ -9,6 +9,12 @@ declare class Cache<T> {
|
|
|
9
9
|
constructor(cleanupMs?: number);
|
|
10
10
|
set(key: string | number, value: T, ttlMs?: number): void;
|
|
11
11
|
get(key: string | number): T | null;
|
|
12
|
+
/**
|
|
13
|
+
* Removes a single entry from the cache.
|
|
14
|
+
* @param key The key to remove
|
|
15
|
+
* @returns Whether an entry existed and was removed
|
|
16
|
+
*/
|
|
17
|
+
delete(key: string | number): boolean;
|
|
12
18
|
private cleanup;
|
|
13
19
|
clear(): void;
|
|
14
20
|
}
|
|
@@ -202,6 +208,20 @@ interface RetryOptions {
|
|
|
202
208
|
/** An AbortSignal to cancel the entire operation. */
|
|
203
209
|
signal?: AbortSignal;
|
|
204
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Creates a queue that runs tasks in call order for each key, while different keys run concurrently.
|
|
213
|
+
* Task errors reach their callers without blocking later tasks. Drained keys are removed automatically.
|
|
214
|
+
* @example
|
|
215
|
+
* const queue = keyedQueue();
|
|
216
|
+
* const first = queue.run("user-1", () => saveInventory("user-1"));
|
|
217
|
+
* const second = queue.run("user-1", () => readInventory("user-1"));
|
|
218
|
+
* await Promise.all([first, second]); // The read runs after the save finishes
|
|
219
|
+
* console.log(queue.size); // 0 active keys
|
|
220
|
+
*/
|
|
221
|
+
declare function keyedQueue(): {
|
|
222
|
+
run<T>(key: string | number, work: () => T | Promise<T>): Promise<T>;
|
|
223
|
+
readonly size: number;
|
|
224
|
+
};
|
|
205
225
|
/**
|
|
206
226
|
* Retries an async function until the maximum number of attempts is reached.
|
|
207
227
|
*
|
|
@@ -269,17 +289,23 @@ declare function debounce<T extends (...args: unknown[]) => unknown>(fn: T, wait
|
|
|
269
289
|
*/
|
|
270
290
|
declare function throttle<T extends (...args: unknown[]) => unknown>(fn: T, limit: number): (...args: Parameters<T>) => void;
|
|
271
291
|
|
|
272
|
-
interface MemoizedFunction<T extends (...args:
|
|
292
|
+
interface MemoizedFunction<T extends (...args: never[]) => unknown> {
|
|
273
293
|
(...args: Parameters<T>): ReturnType<T>;
|
|
274
294
|
/** Clears the cache. */
|
|
275
295
|
clear: () => void;
|
|
296
|
+
/** Removes the entry for these arguments, returning whether it existed. */
|
|
297
|
+
delete: (...args: Parameters<T>) => boolean;
|
|
298
|
+
/** Caches a value for these arguments, starting a fresh TTL. */
|
|
299
|
+
set: (value: ReturnType<T>, ...args: Parameters<T>) => void;
|
|
276
300
|
}
|
|
277
301
|
/**
|
|
278
302
|
* Memoizes a function by caching its results based on the input arguments.
|
|
279
303
|
* A resolver function can be provided to customize the key generation.
|
|
280
304
|
* If no resolver is provided, the key will be generated by JSON stringify-ing the input arguments.
|
|
305
|
+
* Rejected promises are evicted. Expired entries are swept lazily on calls and writes,
|
|
306
|
+
* at most once per maxAge interval; no cleanup timers are created.
|
|
281
307
|
* @param fn The function to memoize
|
|
282
|
-
* @param
|
|
308
|
+
* @param options Optional key resolver and cache lifetime in milliseconds
|
|
283
309
|
* @example
|
|
284
310
|
* // 1. Basic usage
|
|
285
311
|
* const heavyCalc = memoize((n: number) => {
|
|
@@ -300,8 +326,14 @@ interface MemoizedFunction<T extends (...args: any[]) => any> {
|
|
|
300
326
|
* @example
|
|
301
327
|
* // 4. Manual cache clearing
|
|
302
328
|
* heavyCalc.clear();
|
|
329
|
+
* @example
|
|
330
|
+
* // 5. Seed or invalidate one entry using the original arguments
|
|
331
|
+
* const getFlag = memoize(async (id: string) => readFlag(id));
|
|
332
|
+
* await writeFlag("drops", true);
|
|
333
|
+
* getFlag.set(Promise.resolve(true), "drops");
|
|
334
|
+
* getFlag.delete("drops");
|
|
303
335
|
*/
|
|
304
|
-
declare function memoize<T extends (...args:
|
|
336
|
+
declare function memoize<T extends (...args: never[]) => unknown>(fn: T, options?: {
|
|
305
337
|
/** Function to generate a cache key from the input arguments. */
|
|
306
338
|
resolver?: (...args: Parameters<T>) => string;
|
|
307
339
|
/** The time to wait in milliseconds before expiring a cache entry. */
|
|
@@ -667,4 +699,4 @@ declare function pluralize(count: number, singular: string, plural?: string): st
|
|
|
667
699
|
*/
|
|
668
700
|
declare function toTitleCase(str: string, smart?: boolean): string;
|
|
669
701
|
|
|
670
|
-
export { type AlphaCasing, type AnyFunc, Cache, type DebouncedFunction, type DeepPartial, type FormatDurationOptions, FormatNumberCompact, Loop, type LoopEvents, type MemoizedFunction, type ParseTimeOptions, Pipe, type ReadDirOptions, type RetryOptions, type RndArrayOptions, type RndStrOptions, type SequentialMapContext, Storage, type TypedEmitter, chunk, chunkAdj, clampNumber, cluster, compactArray, createSampler, debounce, escapeRegex, forceArray, formatCurrency, formatDuration, formatETA, formatMemory, formatNumber, formatOrdinal, getAge, getFlag, getProp, hasFlag, hasProp, inverseLerp, isDefined, isEmpty, isInRange, isObject, isSortedArray, isString, isToday, lerp, memoize, merge, msToSecs, omit, parseTime, percent, pick, pluralize, prng, readDir, remap, retryPromise, rndChance, rndChoice, rndFloat, rndIndex, rndInt, rndString, searchSorted, secsToMs, seqMap, setProp, shuffle, sortBy, sum, throttle, toTitleCase, unique, wait, weightedRnd, wrap };
|
|
702
|
+
export { type AlphaCasing, type AnyFunc, Cache, type DebouncedFunction, type DeepPartial, type FormatDurationOptions, FormatNumberCompact, Loop, type LoopEvents, type MemoizedFunction, type ParseTimeOptions, Pipe, type ReadDirOptions, type RetryOptions, type RndArrayOptions, type RndStrOptions, type SequentialMapContext, Storage, type TypedEmitter, chunk, chunkAdj, clampNumber, cluster, compactArray, createSampler, debounce, escapeRegex, forceArray, formatCurrency, formatDuration, formatETA, formatMemory, formatNumber, formatOrdinal, getAge, getFlag, getProp, hasFlag, hasProp, inverseLerp, isDefined, isEmpty, isInRange, isObject, isSortedArray, isString, isToday, keyedQueue, lerp, memoize, merge, msToSecs, omit, parseTime, percent, pick, pluralize, prng, readDir, remap, retryPromise, rndChance, rndChoice, rndFloat, rndIndex, rndInt, rndString, searchSorted, secsToMs, seqMap, setProp, shuffle, sortBy, sum, throttle, toTitleCase, unique, wait, weightedRnd, wrap };
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,12 @@ declare class Cache<T> {
|
|
|
9
9
|
constructor(cleanupMs?: number);
|
|
10
10
|
set(key: string | number, value: T, ttlMs?: number): void;
|
|
11
11
|
get(key: string | number): T | null;
|
|
12
|
+
/**
|
|
13
|
+
* Removes a single entry from the cache.
|
|
14
|
+
* @param key The key to remove
|
|
15
|
+
* @returns Whether an entry existed and was removed
|
|
16
|
+
*/
|
|
17
|
+
delete(key: string | number): boolean;
|
|
12
18
|
private cleanup;
|
|
13
19
|
clear(): void;
|
|
14
20
|
}
|
|
@@ -202,6 +208,20 @@ interface RetryOptions {
|
|
|
202
208
|
/** An AbortSignal to cancel the entire operation. */
|
|
203
209
|
signal?: AbortSignal;
|
|
204
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Creates a queue that runs tasks in call order for each key, while different keys run concurrently.
|
|
213
|
+
* Task errors reach their callers without blocking later tasks. Drained keys are removed automatically.
|
|
214
|
+
* @example
|
|
215
|
+
* const queue = keyedQueue();
|
|
216
|
+
* const first = queue.run("user-1", () => saveInventory("user-1"));
|
|
217
|
+
* const second = queue.run("user-1", () => readInventory("user-1"));
|
|
218
|
+
* await Promise.all([first, second]); // The read runs after the save finishes
|
|
219
|
+
* console.log(queue.size); // 0 active keys
|
|
220
|
+
*/
|
|
221
|
+
declare function keyedQueue(): {
|
|
222
|
+
run<T>(key: string | number, work: () => T | Promise<T>): Promise<T>;
|
|
223
|
+
readonly size: number;
|
|
224
|
+
};
|
|
205
225
|
/**
|
|
206
226
|
* Retries an async function until the maximum number of attempts is reached.
|
|
207
227
|
*
|
|
@@ -269,17 +289,23 @@ declare function debounce<T extends (...args: unknown[]) => unknown>(fn: T, wait
|
|
|
269
289
|
*/
|
|
270
290
|
declare function throttle<T extends (...args: unknown[]) => unknown>(fn: T, limit: number): (...args: Parameters<T>) => void;
|
|
271
291
|
|
|
272
|
-
interface MemoizedFunction<T extends (...args:
|
|
292
|
+
interface MemoizedFunction<T extends (...args: never[]) => unknown> {
|
|
273
293
|
(...args: Parameters<T>): ReturnType<T>;
|
|
274
294
|
/** Clears the cache. */
|
|
275
295
|
clear: () => void;
|
|
296
|
+
/** Removes the entry for these arguments, returning whether it existed. */
|
|
297
|
+
delete: (...args: Parameters<T>) => boolean;
|
|
298
|
+
/** Caches a value for these arguments, starting a fresh TTL. */
|
|
299
|
+
set: (value: ReturnType<T>, ...args: Parameters<T>) => void;
|
|
276
300
|
}
|
|
277
301
|
/**
|
|
278
302
|
* Memoizes a function by caching its results based on the input arguments.
|
|
279
303
|
* A resolver function can be provided to customize the key generation.
|
|
280
304
|
* If no resolver is provided, the key will be generated by JSON stringify-ing the input arguments.
|
|
305
|
+
* Rejected promises are evicted. Expired entries are swept lazily on calls and writes,
|
|
306
|
+
* at most once per maxAge interval; no cleanup timers are created.
|
|
281
307
|
* @param fn The function to memoize
|
|
282
|
-
* @param
|
|
308
|
+
* @param options Optional key resolver and cache lifetime in milliseconds
|
|
283
309
|
* @example
|
|
284
310
|
* // 1. Basic usage
|
|
285
311
|
* const heavyCalc = memoize((n: number) => {
|
|
@@ -300,8 +326,14 @@ interface MemoizedFunction<T extends (...args: any[]) => any> {
|
|
|
300
326
|
* @example
|
|
301
327
|
* // 4. Manual cache clearing
|
|
302
328
|
* heavyCalc.clear();
|
|
329
|
+
* @example
|
|
330
|
+
* // 5. Seed or invalidate one entry using the original arguments
|
|
331
|
+
* const getFlag = memoize(async (id: string) => readFlag(id));
|
|
332
|
+
* await writeFlag("drops", true);
|
|
333
|
+
* getFlag.set(Promise.resolve(true), "drops");
|
|
334
|
+
* getFlag.delete("drops");
|
|
303
335
|
*/
|
|
304
|
-
declare function memoize<T extends (...args:
|
|
336
|
+
declare function memoize<T extends (...args: never[]) => unknown>(fn: T, options?: {
|
|
305
337
|
/** Function to generate a cache key from the input arguments. */
|
|
306
338
|
resolver?: (...args: Parameters<T>) => string;
|
|
307
339
|
/** The time to wait in milliseconds before expiring a cache entry. */
|
|
@@ -667,4 +699,4 @@ declare function pluralize(count: number, singular: string, plural?: string): st
|
|
|
667
699
|
*/
|
|
668
700
|
declare function toTitleCase(str: string, smart?: boolean): string;
|
|
669
701
|
|
|
670
|
-
export { type AlphaCasing, type AnyFunc, Cache, type DebouncedFunction, type DeepPartial, type FormatDurationOptions, FormatNumberCompact, Loop, type LoopEvents, type MemoizedFunction, type ParseTimeOptions, Pipe, type ReadDirOptions, type RetryOptions, type RndArrayOptions, type RndStrOptions, type SequentialMapContext, Storage, type TypedEmitter, chunk, chunkAdj, clampNumber, cluster, compactArray, createSampler, debounce, escapeRegex, forceArray, formatCurrency, formatDuration, formatETA, formatMemory, formatNumber, formatOrdinal, getAge, getFlag, getProp, hasFlag, hasProp, inverseLerp, isDefined, isEmpty, isInRange, isObject, isSortedArray, isString, isToday, lerp, memoize, merge, msToSecs, omit, parseTime, percent, pick, pluralize, prng, readDir, remap, retryPromise, rndChance, rndChoice, rndFloat, rndIndex, rndInt, rndString, searchSorted, secsToMs, seqMap, setProp, shuffle, sortBy, sum, throttle, toTitleCase, unique, wait, weightedRnd, wrap };
|
|
702
|
+
export { type AlphaCasing, type AnyFunc, Cache, type DebouncedFunction, type DeepPartial, type FormatDurationOptions, FormatNumberCompact, Loop, type LoopEvents, type MemoizedFunction, type ParseTimeOptions, Pipe, type ReadDirOptions, type RetryOptions, type RndArrayOptions, type RndStrOptions, type SequentialMapContext, Storage, type TypedEmitter, chunk, chunkAdj, clampNumber, cluster, compactArray, createSampler, debounce, escapeRegex, forceArray, formatCurrency, formatDuration, formatETA, formatMemory, formatNumber, formatOrdinal, getAge, getFlag, getProp, hasFlag, hasProp, inverseLerp, isDefined, isEmpty, isInRange, isObject, isSortedArray, isString, isToday, keyedQueue, lerp, memoize, merge, msToSecs, omit, parseTime, percent, pick, pluralize, prng, readDir, remap, retryPromise, rndChance, rndChoice, rndFloat, rndIndex, rndInt, rndString, searchSorted, secsToMs, seqMap, setProp, shuffle, sortBy, sum, throttle, toTitleCase, unique, wait, weightedRnd, wrap };
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,14 @@ var Cache = class {
|
|
|
28
28
|
}
|
|
29
29
|
return data.value;
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Removes a single entry from the cache.
|
|
33
|
+
* @param key The key to remove
|
|
34
|
+
* @returns Whether an entry existed and was removed
|
|
35
|
+
*/
|
|
36
|
+
delete(key) {
|
|
37
|
+
return this.cache.delete(key);
|
|
38
|
+
}
|
|
31
39
|
cleanup() {
|
|
32
40
|
if (this.cache.size === 0) return;
|
|
33
41
|
const now = Date.now();
|
|
@@ -496,6 +504,24 @@ function unique(array, key) {
|
|
|
496
504
|
}
|
|
497
505
|
|
|
498
506
|
// src/async.ts
|
|
507
|
+
function keyedQueue() {
|
|
508
|
+
const queues = /* @__PURE__ */ new Map();
|
|
509
|
+
return {
|
|
510
|
+
run(key, work) {
|
|
511
|
+
const previous = queues.get(key) ?? Promise.resolve();
|
|
512
|
+
const result = previous.then(work);
|
|
513
|
+
const release = () => {
|
|
514
|
+
if (queues.get(key) === tail) queues.delete(key);
|
|
515
|
+
};
|
|
516
|
+
const tail = result.then(release, release);
|
|
517
|
+
queues.set(key, tail);
|
|
518
|
+
return result;
|
|
519
|
+
},
|
|
520
|
+
get size() {
|
|
521
|
+
return queues.size;
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
}
|
|
499
525
|
async function retryPromise(fn, options = {}) {
|
|
500
526
|
const { attempts = 3, delay = 500, timeout, signal } = options;
|
|
501
527
|
if (signal?.aborted) throw new Error("Operation aborted");
|
|
@@ -611,9 +637,28 @@ function throttle(fn, limit) {
|
|
|
611
637
|
function memoize(fn, options = {}) {
|
|
612
638
|
const cache = /* @__PURE__ */ new Map();
|
|
613
639
|
const { resolver, maxAge } = options;
|
|
640
|
+
let lastSweep = Date.now();
|
|
641
|
+
const getKey = (...args) => resolver ? resolver(...args) : JSON.stringify(args);
|
|
642
|
+
const sweep = (now) => {
|
|
643
|
+
if (!maxAge || now - lastSweep < maxAge) return;
|
|
644
|
+
lastSweep = now;
|
|
645
|
+
for (const [key, entry] of cache) {
|
|
646
|
+
if (now - entry.timestamp >= maxAge) cache.delete(key);
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
const cacheValue = (key, value, timestamp) => {
|
|
650
|
+
const entry = { value, timestamp };
|
|
651
|
+
cache.set(key, entry);
|
|
652
|
+
if (value !== null && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function") {
|
|
653
|
+
void Promise.resolve(value).catch(() => {
|
|
654
|
+
if (cache.get(key) === entry) cache.delete(key);
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
};
|
|
614
658
|
const memoized = function(...args) {
|
|
615
|
-
const key =
|
|
659
|
+
const key = getKey(...args);
|
|
616
660
|
const now = Date.now();
|
|
661
|
+
sweep(now);
|
|
617
662
|
const entry = cache.get(key);
|
|
618
663
|
if (entry) {
|
|
619
664
|
if (!maxAge || now - entry.timestamp < maxAge) {
|
|
@@ -622,10 +667,17 @@ function memoize(fn, options = {}) {
|
|
|
622
667
|
cache.delete(key);
|
|
623
668
|
}
|
|
624
669
|
const result = fn.apply(this, args);
|
|
625
|
-
|
|
670
|
+
cacheValue(key, result, now);
|
|
626
671
|
return result;
|
|
627
672
|
};
|
|
628
673
|
memoized.clear = () => cache.clear();
|
|
674
|
+
memoized.delete = (...args) => cache.delete(getKey(...args));
|
|
675
|
+
memoized.set = (value, ...args) => {
|
|
676
|
+
const key = getKey(...args);
|
|
677
|
+
const now = Date.now();
|
|
678
|
+
sweep(now);
|
|
679
|
+
cacheValue(key, value, now);
|
|
680
|
+
};
|
|
629
681
|
return memoized;
|
|
630
682
|
}
|
|
631
683
|
|
|
@@ -971,6 +1023,7 @@ export {
|
|
|
971
1023
|
isSortedArray,
|
|
972
1024
|
isString,
|
|
973
1025
|
isToday,
|
|
1026
|
+
keyedQueue,
|
|
974
1027
|
lerp,
|
|
975
1028
|
memoize,
|
|
976
1029
|
merge,
|