%PDF- %PDF-
Direktori : /www/specpages-backup/node_modules/moize/src/ |
Current File : //www/specpages-backup/node_modules/moize/src/index.ts |
import memoize from 'micro-memoize'; import { createMoizedComponent } from './component'; import { DEFAULT_OPTIONS } from './constants'; import { createMoizeInstance } from './instance'; import { getMaxAgeOptions } from './maxAge'; import { createOnCacheOperation, getIsEqual, getIsMatchingKey, getTransformKey, } from './options'; import { clearStats, collectStats, getDefaultProfileName, getStats, getStatsOptions, statsCache, } from './stats'; import { createRefreshableMoized } from './updateCacheForKey'; import { combine, compose, isMoized, mergeOptions, setName } from './utils'; import type { Expiration, IsEqual, IsMatchingKey, MicroMemoizeOptions, Moize, Moizeable, Moized, OnExpire, Options, Serialize, TransformKey, UpdateCacheForKey, } from '../index.d'; /** * @module moize */ /** * @description * memoize a function based its arguments passed, potentially improving runtime performance * * @example * import moize from 'moize'; * * // standard implementation * const fn = (foo, bar) => `${foo} ${bar}`; * const memoizedFn = moize(fn); * * // implementation with options * const fn = async (id) => get(`http://foo.com/${id}`); * const memoizedFn = moize(fn, {isPromise: true, maxSize: 5}); * * // implementation with convenience methods * const Foo = ({foo}) => <div>{foo}</div>; * const MemoizedFoo = moize.react(Foo); * * @param fn the function to memoized, or a list of options when currying * @param [options=DEFAULT_OPTIONS] the options to apply * @returns the memoized function */ const moize: Moize = function < MoizeableFn extends Moizeable, PassedOptions extends Options<MoizeableFn> >(fn: MoizeableFn | PassedOptions, passedOptions?: PassedOptions) { type CombinedOptions = Omit<Options<MoizeableFn>, keyof PassedOptions> & PassedOptions; const options: Options<MoizeableFn> = passedOptions || DEFAULT_OPTIONS; if (isMoized(fn)) { const moizeable = fn.originalFunction as MoizeableFn; const mergedOptions = mergeOptions( fn.options, options ) as CombinedOptions; return moize<MoizeableFn, CombinedOptions>(moizeable, mergedOptions); } if (typeof fn === 'object') { return function < CurriedFn extends Moizeable, CurriedOptions extends Options<CurriedFn> >( curriedFn: CurriedFn | CurriedOptions, curriedOptions: CurriedOptions ) { type CombinedCurriedOptions = Omit< CombinedOptions, keyof CurriedOptions > & CurriedOptions; if (typeof curriedFn === 'function') { const mergedOptions = mergeOptions( fn as CombinedOptions, curriedOptions ) as CombinedCurriedOptions; return moize(curriedFn, mergedOptions); } const mergedOptions = mergeOptions( fn as CombinedOptions, curriedFn as CurriedOptions ); return moize(mergedOptions); }; } if (options.isReact) { return createMoizedComponent(moize, fn, options); } const coalescedOptions: Options<MoizeableFn> = { ...DEFAULT_OPTIONS, ...options, maxAge: typeof options.maxAge === 'number' && options.maxAge >= 0 ? options.maxAge : DEFAULT_OPTIONS.maxAge, maxArgs: typeof options.maxArgs === 'number' && options.maxArgs >= 0 ? options.maxArgs : DEFAULT_OPTIONS.maxArgs, maxSize: typeof options.maxSize === 'number' && options.maxSize >= 0 ? options.maxSize : DEFAULT_OPTIONS.maxSize, profileName: options.profileName || getDefaultProfileName(fn), }; const expirations: Array<Expiration> = []; const { matchesArg: equalsIgnored, isDeepEqual: isDeepEqualIgnored, isPromise, isReact: isReactIgnored, isSerialized: isSerialzedIgnored, isShallowEqual: isShallowEqualIgnored, matchesKey: matchesKeyIgnored, maxAge: maxAgeIgnored, maxArgs: maxArgsIgnored, maxSize, onCacheAdd, onCacheChange, onCacheHit, onExpire: onExpireIgnored, profileName: profileNameIgnored, serializer: serializerIgnored, updateCacheForKey, transformArgs: transformArgsIgnored, updateExpire: updateExpireIgnored, ...customOptions } = coalescedOptions; const isEqual = getIsEqual(coalescedOptions); const isMatchingKey = getIsMatchingKey(coalescedOptions); const maxAgeOptions = getMaxAgeOptions( expirations, coalescedOptions, isEqual, isMatchingKey ); const statsOptions = getStatsOptions(coalescedOptions); const transformKey = getTransformKey(coalescedOptions); const microMemoizeOptions: MicroMemoizeOptions<MoizeableFn> = { ...customOptions, isEqual, isMatchingKey, isPromise, maxSize, onCacheAdd: createOnCacheOperation( combine( onCacheAdd, maxAgeOptions.onCacheAdd, statsOptions.onCacheAdd ) ), onCacheChange: createOnCacheOperation(onCacheChange), onCacheHit: createOnCacheOperation( combine( onCacheHit, maxAgeOptions.onCacheHit, statsOptions.onCacheHit ) ), transformKey, }; const memoized = memoize(fn, microMemoizeOptions); let moized = createMoizeInstance<MoizeableFn, CombinedOptions>(memoized, { expirations, options: coalescedOptions, originalFunction: fn, }); if (updateCacheForKey) { moized = createRefreshableMoized<typeof moized>(moized); } setName(moized, (fn as Moizeable).name, options.profileName); return moized; }; /** * @function * @name clearStats * @memberof module:moize * @alias moize.clearStats * * @description * clear all existing stats stored */ moize.clearStats = clearStats; /** * @function * @name collectStats * @memberof module:moize * @alias moize.collectStats * * @description * start collecting statistics */ moize.collectStats = collectStats; /** * @function * @name compose * @memberof module:moize * @alias moize.compose * * @description * method to compose moized methods and return a single moized function * * @param moized the functions to compose * @returns the composed function */ moize.compose = function (...moized: Moize[]) { return compose<Moize>(...moized) || moize; }; /** * @function * @name deep * @memberof module:moize * @alias moize.deep * * @description * should deep equality check be used * * @returns the moizer function */ moize.deep = moize({ isDeepEqual: true }); /** * @function * @name getStats * @memberof module:moize * @alias moize.getStats * * @description * get the statistics of a given profile, or overall usage * * @returns statistics for a given profile or overall usage */ moize.getStats = getStats; /** * @function * @name infinite * @memberof module:moize * @alias moize.infinite * * @description * a moized method that will remove all limits from the cache size * * @returns the moizer function */ moize.infinite = moize({ maxSize: Infinity }); /** * @function * @name isCollectingStats * @memberof module:moize * @alias moize.isCollectingStats * * @description * are stats being collected * * @returns are stats being collected */ moize.isCollectingStats = function isCollectingStats(): boolean { return statsCache.isCollectingStats; }; /** * @function * @name isMoized * @memberof module:moize * @alias moize.isMoized * * @description * is the fn passed a moized function * * @param fn the object to test * @returns is fn a moized function */ moize.isMoized = function isMoized(fn: any): fn is Moized { return typeof fn === 'function' && !!fn.isMoized; }; /** * @function * @name matchesArg * @memberof module:moize * @alias moize.matchesArg * * @description * a moized method where the arg matching method is the custom one passed * * @param keyMatcher the method to compare against those in cache * @returns the moizer function */ moize.matchesArg = function (argMatcher: IsEqual) { return moize({ matchesArg: argMatcher }); }; /** * @function * @name matchesKey * @memberof module:moize * @alias moize.matchesKey * * @description * a moized method where the key matching method is the custom one passed * * @param keyMatcher the method to compare against those in cache * @returns the moizer function */ moize.matchesKey = function (keyMatcher: IsMatchingKey) { return moize({ matchesKey: keyMatcher }); }; function maxAge<MaxAge extends number>( maxAge: MaxAge ): Moize<{ maxAge: MaxAge }>; function maxAge<MaxAge extends number, UpdateExpire extends boolean>( maxAge: MaxAge, expireOptions: UpdateExpire ): Moize<{ maxAge: MaxAge; updateExpire: UpdateExpire }>; function maxAge<MaxAge extends number, ExpireHandler extends OnExpire>( maxAge: MaxAge, expireOptions: ExpireHandler ): Moize<{ maxAge: MaxAge; onExpire: ExpireHandler }>; function maxAge< MaxAge extends number, ExpireHandler extends OnExpire, ExpireOptions extends { onExpire: ExpireHandler; } >( maxAge: MaxAge, expireOptions: ExpireOptions ): Moize<{ maxAge: MaxAge; onExpire: ExpireOptions['onExpire'] }>; function maxAge< MaxAge extends number, UpdateExpire extends boolean, ExpireOptions extends { updateExpire: UpdateExpire; } >( maxAge: MaxAge, expireOptions: ExpireOptions ): Moize<{ maxAge: MaxAge; updateExpire: UpdateExpire }>; function maxAge< MaxAge extends number, ExpireHandler extends OnExpire, UpdateExpire extends boolean, ExpireOptions extends { onExpire: ExpireHandler; updateExpire: UpdateExpire; } >( maxAge: MaxAge, expireOptions: ExpireOptions ): Moize<{ maxAge: MaxAge; onExpire: ExpireHandler; updateExpire: UpdateExpire; }>; function maxAge< MaxAge extends number, ExpireHandler extends OnExpire, UpdateExpire extends boolean, ExpireOptions extends { onExpire?: ExpireHandler; updateExpire?: UpdateExpire; } >( maxAge: MaxAge, expireOptions?: ExpireHandler | UpdateExpire | ExpireOptions ) { if (expireOptions === true) { return moize({ maxAge, updateExpire: expireOptions, }); } if (typeof expireOptions === 'object') { const { onExpire, updateExpire } = expireOptions; return moize({ maxAge, onExpire, updateExpire, }); } if (typeof expireOptions === 'function') { return moize({ maxAge, onExpire: expireOptions, updateExpire: true, }); } return moize({ maxAge }); } /** * @function * @name maxAge * @memberof module:moize * @alias moize.maxAge * * @description * a moized method where the age of the cache is limited to the number of milliseconds passed * * @param maxAge the TTL of the value in cache * @returns the moizer function */ moize.maxAge = maxAge; /** * @function * @name maxArgs * @memberof module:moize * @alias moize.maxArgs * * @description * a moized method where the number of arguments used for determining cache is limited to the value passed * * @param maxArgs the number of args to base the key on * @returns the moizer function */ moize.maxArgs = function maxArgs(maxArgs: number) { return moize({ maxArgs }); }; /** * @function * @name maxSize * @memberof module:moize * @alias moize.maxSize * * @description * a moized method where the total size of the cache is limited to the value passed * * @param maxSize the maximum size of the cache * @returns the moizer function */ moize.maxSize = function maxSize(maxSize: number) { return moize({ maxSize }); }; /** * @function * @name profile * @memberof module:moize * @alias moize.profile * * @description * a moized method with a profile name * * @returns the moizer function */ moize.profile = function (profileName: string) { return moize({ profileName }); }; /** * @function * @name promise * @memberof module:moize * @alias moize.promise * * @description * a moized method specific to caching resolved promise / async values * * @returns the moizer function */ moize.promise = moize({ isPromise: true, updateExpire: true, }); /** * @function * @name react * @memberof module:moize * @alias moize.react * * @description * a moized method specific to caching React element values * * @returns the moizer function */ moize.react = moize({ isReact: true }); /** * @function * @name serialize * @memberof module:moize * @alias moize.serialize * * @description * a moized method that will serialize the arguments passed to use as the cache key * * @returns the moizer function */ moize.serialize = moize({ isSerialized: true }); /** * @function * @name serializeWith * @memberof module:moize * @alias moize.serializeWith * * @description * a moized method that will serialize the arguments passed to use as the cache key * based on the serializer passed * * @returns the moizer function */ moize.serializeWith = function (serializer: Serialize) { return moize({ isSerialized: true, serializer }); }; /** * @function * @name shallow * @memberof module:moize * @alias moize.shallow * * @description * should shallow equality check be used * * @returns the moizer function */ moize.shallow = moize({ isShallowEqual: true }); /** * @function * @name transformArgs * @memberof module:moize * @alias moize.transformArgs * * @description * transform the args to allow for specific cache key comparison * * @param transformArgs the args transformer * @returns the moizer function */ moize.transformArgs = <Transformer extends TransformKey>( transformArgs: Transformer ) => moize({ transformArgs }); /** * @function * @name updateCacheForKey * @memberof module:moize * @alias moize.updateCacheForKey * * @description * update the cache for a given key when the method passed returns truthy * * @param updateCacheForKey the method to determine when to update cache * @returns the moizer function */ moize.updateCacheForKey = <UpdateWhen extends UpdateCacheForKey>( updateCacheForKey: UpdateWhen ) => moize({ updateCacheForKey }); // Add self-referring `default` property for edge-case cross-compatibility of mixed ESM/CommonJS usage. // This property is frozen and non-enumerable to avoid visibility on iteration or accidental overrides. Object.defineProperty(moize, 'default', { configurable: false, enumerable: false, value: moize, writable: false, }); export default moize;