first commit
This commit is contained in:
132
node_modules/micro-memoize/mjs/index.d.mts
generated
vendored
Normal file
132
node_modules/micro-memoize/mjs/index.d.mts
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
export interface Dictionary<Type> {
|
||||
[key: string]: Type;
|
||||
[index: number]: Type;
|
||||
}
|
||||
|
||||
export type AnyFn = (...args: any[]) => any;
|
||||
|
||||
export type Key = any[];
|
||||
export type RawKey = Key | IArguments;
|
||||
export type Value = any;
|
||||
|
||||
export interface CacheSnapshot {
|
||||
keys: Key[];
|
||||
size: number;
|
||||
values: Value[];
|
||||
}
|
||||
|
||||
export class Cache<Fn extends AnyFn> {
|
||||
readonly canTransformKey: boolean;
|
||||
readonly getKeyIndex: KeyIndexGetter;
|
||||
readonly options: NormalizedOptions<Fn>;
|
||||
readonly shouldCloneArguments: boolean;
|
||||
readonly shouldUpdateOnAdd: boolean;
|
||||
readonly shouldUpdateOnChange: boolean;
|
||||
readonly shouldUpdateOnHit: boolean;
|
||||
|
||||
/**
|
||||
* The prevents call arguments which have cached results.
|
||||
*/
|
||||
keys: Key[];
|
||||
/**
|
||||
* The results of previous cached calls.
|
||||
*/
|
||||
values: Value[];
|
||||
|
||||
constructor(options: NormalizedOptions<Fn>);
|
||||
|
||||
/**
|
||||
* The number of cached [key,value] results.
|
||||
*/
|
||||
get size(): number;
|
||||
|
||||
/**
|
||||
* A copy of the cache at a moment in time. This is useful
|
||||
* to compare changes over time, since the cache mutates
|
||||
* internally for performance reasons.
|
||||
*/
|
||||
get snapshot(): CacheSnapshot;
|
||||
|
||||
/**
|
||||
* Order the array based on a Least-Recently-Used basis.
|
||||
*/
|
||||
orderByLru(key: Key, value: Value, startingIndex: number): void;
|
||||
|
||||
/**
|
||||
* Update the promise method to auto-remove from cache if rejected, and
|
||||
* if resolved then fire cache hit / changed.
|
||||
*/
|
||||
updateAsyncCache(memoized: Memoized<Fn>): void;
|
||||
}
|
||||
|
||||
export type EqualityComparator = (object1: any, object2: any) => boolean;
|
||||
|
||||
export type MatchingKeyComparator = (key1: Key, key2: RawKey) => boolean;
|
||||
|
||||
export type CacheModifiedHandler<Fn extends AnyFn> = (
|
||||
cache: Cache<Fn>,
|
||||
options: NormalizedOptions<Fn>,
|
||||
memoized: Memoized<Fn>,
|
||||
) => void;
|
||||
|
||||
export type KeyTransformer = (args: Key) => Key;
|
||||
|
||||
export type KeyIndexGetter = (keyToMatch: RawKey) => number;
|
||||
|
||||
export interface StandardOptions<Fn extends AnyFn> {
|
||||
isEqual?: EqualityComparator;
|
||||
isMatchingKey?: MatchingKeyComparator;
|
||||
isPromise?: boolean;
|
||||
maxSize?: number;
|
||||
onCacheAdd?: CacheModifiedHandler<Fn>;
|
||||
onCacheChange?: CacheModifiedHandler<Fn>;
|
||||
onCacheHit?: CacheModifiedHandler<Fn>;
|
||||
transformKey?: KeyTransformer;
|
||||
}
|
||||
|
||||
export interface Options<Fn extends AnyFn>
|
||||
extends StandardOptions<Fn>,
|
||||
Dictionary<any> {}
|
||||
|
||||
export interface NormalizedOptions<Fn extends AnyFn> extends Options<Fn> {
|
||||
isEqual: EqualityComparator;
|
||||
isPromise: boolean;
|
||||
maxSize: number;
|
||||
}
|
||||
|
||||
export type Memoized<Fn extends AnyFn> = Fn &
|
||||
Dictionary<any> & {
|
||||
cache: Cache<Fn>;
|
||||
fn: Fn;
|
||||
isMemoized: true;
|
||||
options: NormalizedOptions<Fn>;
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* All types declared on this namespace are available for direct import
|
||||
* from the package. In a future release, this namespace will be removed
|
||||
* in favor of those direct imports.
|
||||
*/
|
||||
export declare namespace MicroMemoize {
|
||||
export type {
|
||||
Cache,
|
||||
CacheModifiedHandler,
|
||||
EqualityComparator,
|
||||
Key,
|
||||
KeyIndexGetter,
|
||||
KeyTransformer,
|
||||
MatchingKeyComparator,
|
||||
Memoized,
|
||||
NormalizedOptions,
|
||||
Options,
|
||||
StandardOptions,
|
||||
RawKey,
|
||||
Value,
|
||||
};
|
||||
}
|
||||
|
||||
export default function memoize<Fn extends AnyFn>(
|
||||
fn: Fn | Memoized<Fn>,
|
||||
options?: Options<Fn>,
|
||||
): Memoized<Fn>;
|
||||
370
node_modules/micro-memoize/mjs/index.mjs
generated
vendored
Normal file
370
node_modules/micro-memoize/mjs/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,370 @@
|
||||
/**
|
||||
* @constant DEFAULT_OPTIONS_KEYS the default options keys
|
||||
*/
|
||||
var DEFAULT_OPTIONS_KEYS = {
|
||||
isEqual: true,
|
||||
isMatchingKey: true,
|
||||
isPromise: true,
|
||||
maxSize: true,
|
||||
onCacheAdd: true,
|
||||
onCacheChange: true,
|
||||
onCacheHit: true,
|
||||
transformKey: true,
|
||||
};
|
||||
/**
|
||||
* @function slice
|
||||
*
|
||||
* @description
|
||||
* slice.call() pre-bound
|
||||
*/
|
||||
var slice = Array.prototype.slice;
|
||||
/**
|
||||
* @function cloneArray
|
||||
*
|
||||
* @description
|
||||
* clone the array-like object and return the new array
|
||||
*
|
||||
* @param arrayLike the array-like object to clone
|
||||
* @returns the clone as an array
|
||||
*/
|
||||
function cloneArray(arrayLike) {
|
||||
var length = arrayLike.length;
|
||||
if (!length) {
|
||||
return [];
|
||||
}
|
||||
if (length === 1) {
|
||||
return [arrayLike[0]];
|
||||
}
|
||||
if (length === 2) {
|
||||
return [arrayLike[0], arrayLike[1]];
|
||||
}
|
||||
if (length === 3) {
|
||||
return [arrayLike[0], arrayLike[1], arrayLike[2]];
|
||||
}
|
||||
return slice.call(arrayLike, 0);
|
||||
}
|
||||
/**
|
||||
* @function getCustomOptions
|
||||
*
|
||||
* @description
|
||||
* get the custom options on the object passed
|
||||
*
|
||||
* @param options the memoization options passed
|
||||
* @returns the custom options passed
|
||||
*/
|
||||
function getCustomOptions(options) {
|
||||
var customOptions = {};
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
for (var key in options) {
|
||||
if (!DEFAULT_OPTIONS_KEYS[key]) {
|
||||
customOptions[key] = options[key];
|
||||
}
|
||||
}
|
||||
/* eslint-enable */
|
||||
return customOptions;
|
||||
}
|
||||
/**
|
||||
* @function isMemoized
|
||||
*
|
||||
* @description
|
||||
* is the function passed already memoized
|
||||
*
|
||||
* @param fn the function to test
|
||||
* @returns is the function already memoized
|
||||
*/
|
||||
function isMemoized(fn) {
|
||||
return typeof fn === 'function' && fn.isMemoized;
|
||||
}
|
||||
/**
|
||||
* @function isSameValueZero
|
||||
*
|
||||
* @description
|
||||
* are the objects equal based on SameValueZero equality
|
||||
*
|
||||
* @param object1 the first object to compare
|
||||
* @param object2 the second object to compare
|
||||
* @returns are the two objects equal
|
||||
*/
|
||||
function isSameValueZero(object1, object2) {
|
||||
// eslint-disable-next-line no-self-compare
|
||||
return object1 === object2 || (object1 !== object1 && object2 !== object2);
|
||||
}
|
||||
/**
|
||||
* @function mergeOptions
|
||||
*
|
||||
* @description
|
||||
* merge the options into the target
|
||||
*
|
||||
* @param existingOptions the options provided
|
||||
* @param newOptions the options to include
|
||||
* @returns the merged options
|
||||
*/
|
||||
function mergeOptions(existingOptions, newOptions) {
|
||||
var target = {};
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
for (var key in existingOptions) {
|
||||
target[key] = existingOptions[key];
|
||||
}
|
||||
for (var key in newOptions) {
|
||||
target[key] = newOptions[key];
|
||||
}
|
||||
/* eslint-enable */
|
||||
return target;
|
||||
}
|
||||
|
||||
// utils
|
||||
var Cache = /** @class */ (function () {
|
||||
function Cache(options) {
|
||||
this.keys = [];
|
||||
this.values = [];
|
||||
this.options = options;
|
||||
var isMatchingKeyFunction = typeof options.isMatchingKey === 'function';
|
||||
if (isMatchingKeyFunction) {
|
||||
this.getKeyIndex = this._getKeyIndexFromMatchingKey;
|
||||
}
|
||||
else if (options.maxSize > 1) {
|
||||
this.getKeyIndex = this._getKeyIndexForMany;
|
||||
}
|
||||
else {
|
||||
this.getKeyIndex = this._getKeyIndexForSingle;
|
||||
}
|
||||
this.canTransformKey = typeof options.transformKey === 'function';
|
||||
this.shouldCloneArguments = this.canTransformKey || isMatchingKeyFunction;
|
||||
this.shouldUpdateOnAdd = typeof options.onCacheAdd === 'function';
|
||||
this.shouldUpdateOnChange = typeof options.onCacheChange === 'function';
|
||||
this.shouldUpdateOnHit = typeof options.onCacheHit === 'function';
|
||||
}
|
||||
Object.defineProperty(Cache.prototype, "size", {
|
||||
/**
|
||||
* The number of cached [key,value] results.
|
||||
*/
|
||||
get: function () {
|
||||
return this.keys.length;
|
||||
},
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(Cache.prototype, "snapshot", {
|
||||
/**
|
||||
* A copy of the cache at a moment in time. This is useful
|
||||
* to compare changes over time, since the cache mutates
|
||||
* internally for performance reasons.
|
||||
*/
|
||||
get: function () {
|
||||
return {
|
||||
keys: cloneArray(this.keys),
|
||||
size: this.size,
|
||||
values: cloneArray(this.values),
|
||||
};
|
||||
},
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
/**
|
||||
* Gets the matching key index when a custom key matcher is used.
|
||||
*/
|
||||
Cache.prototype._getKeyIndexFromMatchingKey = function (keyToMatch) {
|
||||
var _a = this.options, isMatchingKey = _a.isMatchingKey, maxSize = _a.maxSize;
|
||||
var keys = this.keys;
|
||||
var keysLength = keys.length;
|
||||
if (!keysLength) {
|
||||
return -1;
|
||||
}
|
||||
if (isMatchingKey(keys[0], keyToMatch)) {
|
||||
return 0;
|
||||
}
|
||||
if (maxSize > 1) {
|
||||
for (var index = 1; index < keysLength; index++) {
|
||||
if (isMatchingKey(keys[index], keyToMatch)) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
/**
|
||||
* Gets the matching key index when multiple keys are used.
|
||||
*/
|
||||
Cache.prototype._getKeyIndexForMany = function (keyToMatch) {
|
||||
var isEqual = this.options.isEqual;
|
||||
var keys = this.keys;
|
||||
var keysLength = keys.length;
|
||||
if (!keysLength) {
|
||||
return -1;
|
||||
}
|
||||
if (keysLength === 1) {
|
||||
return this._getKeyIndexForSingle(keyToMatch);
|
||||
}
|
||||
var keyLength = keyToMatch.length;
|
||||
var existingKey;
|
||||
var argIndex;
|
||||
if (keyLength > 1) {
|
||||
for (var index = 0; index < keysLength; index++) {
|
||||
existingKey = keys[index];
|
||||
if (existingKey.length === keyLength) {
|
||||
argIndex = 0;
|
||||
for (; argIndex < keyLength; argIndex++) {
|
||||
if (!isEqual(existingKey[argIndex], keyToMatch[argIndex])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (argIndex === keyLength) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (var index = 0; index < keysLength; index++) {
|
||||
existingKey = keys[index];
|
||||
if (existingKey.length === keyLength &&
|
||||
isEqual(existingKey[0], keyToMatch[0])) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
/**
|
||||
* Gets the matching key index when a single key is used.
|
||||
*/
|
||||
Cache.prototype._getKeyIndexForSingle = function (keyToMatch) {
|
||||
var keys = this.keys;
|
||||
if (!keys.length) {
|
||||
return -1;
|
||||
}
|
||||
var existingKey = keys[0];
|
||||
var length = existingKey.length;
|
||||
if (keyToMatch.length !== length) {
|
||||
return -1;
|
||||
}
|
||||
var isEqual = this.options.isEqual;
|
||||
if (length > 1) {
|
||||
for (var index = 0; index < length; index++) {
|
||||
if (!isEqual(existingKey[index], keyToMatch[index])) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return isEqual(existingKey[0], keyToMatch[0]) ? 0 : -1;
|
||||
};
|
||||
/**
|
||||
* Order the array based on a Least-Recently-Used basis.
|
||||
*/
|
||||
Cache.prototype.orderByLru = function (key, value, startingIndex) {
|
||||
var keys = this.keys;
|
||||
var values = this.values;
|
||||
var currentLength = keys.length;
|
||||
var index = startingIndex;
|
||||
while (index--) {
|
||||
keys[index + 1] = keys[index];
|
||||
values[index + 1] = values[index];
|
||||
}
|
||||
keys[0] = key;
|
||||
values[0] = value;
|
||||
var maxSize = this.options.maxSize;
|
||||
if (currentLength === maxSize && startingIndex === currentLength) {
|
||||
keys.pop();
|
||||
values.pop();
|
||||
}
|
||||
else if (startingIndex >= maxSize) {
|
||||
// eslint-disable-next-line no-multi-assign
|
||||
keys.length = values.length = maxSize;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Update the promise method to auto-remove from cache if rejected, and
|
||||
* if resolved then fire cache hit / changed.
|
||||
*/
|
||||
Cache.prototype.updateAsyncCache = function (memoized) {
|
||||
var _this = this;
|
||||
var _a = this.options, onCacheChange = _a.onCacheChange, onCacheHit = _a.onCacheHit;
|
||||
var firstKey = this.keys[0];
|
||||
var firstValue = this.values[0];
|
||||
this.values[0] = firstValue.then(function (value) {
|
||||
if (_this.shouldUpdateOnHit) {
|
||||
onCacheHit(_this, _this.options, memoized);
|
||||
}
|
||||
if (_this.shouldUpdateOnChange) {
|
||||
onCacheChange(_this, _this.options, memoized);
|
||||
}
|
||||
return value;
|
||||
}, function (error) {
|
||||
var keyIndex = _this.getKeyIndex(firstKey);
|
||||
if (keyIndex !== -1) {
|
||||
_this.keys.splice(keyIndex, 1);
|
||||
_this.values.splice(keyIndex, 1);
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
return Cache;
|
||||
}());
|
||||
|
||||
function createMemoizedFunction(fn, options) {
|
||||
if (options === void 0) { options = {}; }
|
||||
if (isMemoized(fn)) {
|
||||
return createMemoizedFunction(fn.fn, mergeOptions(fn.options, options));
|
||||
}
|
||||
if (typeof fn !== 'function') {
|
||||
throw new TypeError('You must pass a function to `memoize`.');
|
||||
}
|
||||
var _a = options.isEqual, isEqual = _a === void 0 ? isSameValueZero : _a, isMatchingKey = options.isMatchingKey, _b = options.isPromise, isPromise = _b === void 0 ? false : _b, _c = options.maxSize, maxSize = _c === void 0 ? 1 : _c, onCacheAdd = options.onCacheAdd, onCacheChange = options.onCacheChange, onCacheHit = options.onCacheHit, transformKey = options.transformKey;
|
||||
var normalizedOptions = mergeOptions({
|
||||
isEqual: isEqual,
|
||||
isMatchingKey: isMatchingKey,
|
||||
isPromise: isPromise,
|
||||
maxSize: maxSize,
|
||||
onCacheAdd: onCacheAdd,
|
||||
onCacheChange: onCacheChange,
|
||||
onCacheHit: onCacheHit,
|
||||
transformKey: transformKey,
|
||||
}, getCustomOptions(options));
|
||||
var cache = new Cache(normalizedOptions);
|
||||
var keys = cache.keys, values = cache.values, canTransformKey = cache.canTransformKey, shouldCloneArguments = cache.shouldCloneArguments, shouldUpdateOnAdd = cache.shouldUpdateOnAdd, shouldUpdateOnChange = cache.shouldUpdateOnChange, shouldUpdateOnHit = cache.shouldUpdateOnHit;
|
||||
var memoized = function () {
|
||||
var key = shouldCloneArguments
|
||||
? cloneArray(arguments)
|
||||
: arguments;
|
||||
if (canTransformKey) {
|
||||
key = transformKey(key);
|
||||
}
|
||||
var keyIndex = keys.length ? cache.getKeyIndex(key) : -1;
|
||||
if (keyIndex !== -1) {
|
||||
if (shouldUpdateOnHit) {
|
||||
onCacheHit(cache, normalizedOptions, memoized);
|
||||
}
|
||||
if (keyIndex) {
|
||||
cache.orderByLru(keys[keyIndex], values[keyIndex], keyIndex);
|
||||
if (shouldUpdateOnChange) {
|
||||
onCacheChange(cache, normalizedOptions, memoized);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var newValue = fn.apply(this, arguments);
|
||||
var newKey = shouldCloneArguments
|
||||
? key
|
||||
: cloneArray(arguments);
|
||||
cache.orderByLru(newKey, newValue, keys.length);
|
||||
if (isPromise) {
|
||||
cache.updateAsyncCache(memoized);
|
||||
}
|
||||
if (shouldUpdateOnAdd) {
|
||||
onCacheAdd(cache, normalizedOptions, memoized);
|
||||
}
|
||||
if (shouldUpdateOnChange) {
|
||||
onCacheChange(cache, normalizedOptions, memoized);
|
||||
}
|
||||
}
|
||||
return values[0];
|
||||
};
|
||||
memoized.cache = cache;
|
||||
memoized.fn = fn;
|
||||
memoized.isMemoized = true;
|
||||
memoized.options = normalizedOptions;
|
||||
return memoized;
|
||||
}
|
||||
|
||||
export { createMemoizedFunction as default };
|
||||
Reference in New Issue
Block a user