UNPKG

with-simple-caching

Version:

A wrapper that makes it simple to add caching to any function

62 lines 3.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.withSimpleCaching = void 0; const type_fns_1 = require("type-fns"); const getCacheFromCacheOption_1 = require("../options/getCacheFromCacheOption"); const defaults_1 = require("../serde/defaults"); /** * a wrapper which uses a synchronous cache to cache the result of the wrapped logic * * for example: * ```ts * const getApiResult = withSimpleCaching(({ name, number }) => axios.get(URL, { name, number })); * const result1 = getApiResult({ name: 'casey', number: 821 }); // calls the api, puts promise of results into cache, returns that promise * const result2 = getApiResult({ name: 'casey', number: 821 }); // returns the same promise from above, because it was found in cache - since same input as request above was used * expect(result1).toBe(result2); // same exact object - the promise * expect(await result1).toBe(await result2); // same exact object - the result of the promise * ``` */ const withSimpleCaching = (logic, { cache: cacheOption, serialize: { key: serializeKey = defaults_1.defaultKeySerializationMethod, // default serialize key to JSON.stringify value: serializeValue = defaults_1.defaultValueSerializationMethod, // default serialize value to noOp } = {}, deserialize: { value: deserializeValue = defaults_1.noOp, // default deserialize value to noOp } = {}, expiration, bypass = { get: defaults_1.defaultShouldBypassGetMethod, set: defaults_1.defaultShouldBypassSetMethod, }, }) => { return ((...args) => { var _a, _b; // define key based on args the function was invoked with const key = serializeKey({ forInput: args }); // define cache based on options const cache = (0, getCacheFromCacheOption_1.getCacheFromCacheOption)({ forInput: args, cacheOption }); // see if its already cached const cachedValue = ((_a = bypass.get) === null || _a === void 0 ? void 0 : _a.call(bypass, args)) ? undefined : cache.get(key); if ((0, type_fns_1.isNotUndefined)(cachedValue)) return deserializeValue(cachedValue); // if already cached, return it immediately // if its not, grab the output from the logic const output = logic(...args); // if was asked to bypass cache.set, we can return the output now if ((_b = bypass.set) === null || _b === void 0 ? void 0 : _b.call(bypass, args)) return output; // set the output to the cache const serializedOutput = serializeValue(output); cache.set(key, serializedOutput, { expiration }); // if the output was undefined, we can just return here - no deserialization needed if (output === undefined) return output; // and now re-get from the cache, to ensure that output on first response === output on second response const cachedValueNow = cache.get(key); if ((0, type_fns_1.isNotUndefined)(cachedValueNow)) return deserializeValue(cachedValueNow); // otherwise, somehow, get-after-set returned undefined. warn about this and return output // eslint-disable-next-line no-console console.warn( // warn about this because it should never occur 'withSimpleCaching encountered a situation which should not occur: cache.get returned undefined immediately after having been set. returning the output directly to prevent irrecoverable failure.', { key }); return output; }); }; exports.withSimpleCaching = withSimpleCaching; //# sourceMappingURL=withSimpleCaching.js.map