with-simple-caching
Version:
A wrapper that makes it simple to add caching to any function
93 lines • 6.03 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.withExtendableCachingAsync = exports.hasForInputProperty = exports.WithExtendableCachingTrigger = void 0;
const type_fns_1 = require("type-fns");
const getCacheFromCacheOptionOrFromForKeyArgs_1 = require("../options/getCacheFromCacheOptionOrFromForKeyArgs");
const defaults_1 = require("../serde/defaults");
const withSimpleCachingAsync_1 = require("./withSimpleCachingAsync");
/**
* enumerates the extendable methods which can trigger cache operations
*/
var WithExtendableCachingTrigger;
(function (WithExtendableCachingTrigger) {
WithExtendableCachingTrigger["EXECUTE"] = "EXECUTE";
WithExtendableCachingTrigger["INVALIDATE"] = "INVALIDATE";
WithExtendableCachingTrigger["UPDATE"] = "UPDATE";
})(WithExtendableCachingTrigger = exports.WithExtendableCachingTrigger || (exports.WithExtendableCachingTrigger = {}));
/**
* a simple typeguard which checks if an object has a property named `forInput`
*/
const hasForInputProperty = (obj) => !!obj.forInput;
exports.hasForInputProperty = hasForInputProperty;
/**
* exposes the cache-wrapped method along with some primitives which enable extending the caching logic
*
* specifically
* - exposes a way to `invalidate` the cache, for a given input (e.g., to support external triggers for invalidation)
* - exposes a way to `update` the cache, for a given input (e.g., to support write-through caching and optimistic caching)
*
* relevance
* - when wrapping logic to cache the user is able to specify several caching options (e.g., key serialization method, value serialization method, etc)
* - in order to define their own `invalidation` and `update` methods, without this function, the user would need to access these caching options per function elsewhere
* - this function makes it easy to utilize and extend cache invalidation + update commands for the wrapped logic, by managing the references to the caching options on behalf of the user
*/
const withExtendableCachingAsync = (logic, options) => {
const execute = (0, withSimpleCachingAsync_1.withSimpleCachingAsync)(logic, options);
const invalidate = (args) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b;
// define how to get the cache, with support for `forKey` input instead of full input
const cache = (0, getCacheFromCacheOptionOrFromForKeyArgs_1.getCacheFromCacheOptionOrFromForKeyArgs)({
args,
options: { cache: (0, withSimpleCachingAsync_1.getOutputCacheOptionFromCacheInput)(options.cache) },
trigger: WithExtendableCachingTrigger.INVALIDATE,
});
// define the key, with support for `forKey` input instead of `forInput`
const serializeKey = (_b = (_a = options.serialize) === null || _a === void 0 ? void 0 : _a.key) !== null && _b !== void 0 ? _b : defaults_1.defaultKeySerializationMethod;
const key = (0, exports.hasForInputProperty)(args)
? serializeKey({ forInput: args.forInput })
: args.forKey;
// set undefined into the cache for this key, to invalidate the cached value
yield cache.set(key, undefined);
});
const update = (args) => __awaiter(void 0, void 0, void 0, function* () {
var _c, _d, _e, _f, _g, _h;
// define how to get the cache, with support for `forKey` input instead of full input
const cache = (0, getCacheFromCacheOptionOrFromForKeyArgs_1.getCacheFromCacheOptionOrFromForKeyArgs)({
args,
options: { cache: (0, withSimpleCachingAsync_1.getOutputCacheOptionFromCacheInput)(options.cache) },
trigger: WithExtendableCachingTrigger.UPDATE,
});
// define the key, with support for `forKey` input instead of `forInput`
const serializeKey = (_d = (_c = options.serialize) === null || _c === void 0 ? void 0 : _c.key) !== null && _d !== void 0 ? _d : defaults_1.defaultKeySerializationMethod;
const key = (0, exports.hasForInputProperty)(args)
? serializeKey({ forInput: args.forInput })
: args.forKey;
// deserialize the cached value
const cachedValue = yield cache.get(key);
const deserializeValue = (_f = (_e = options.deserialize) === null || _e === void 0 ? void 0 : _e.value) !== null && _f !== void 0 ? _f : defaults_1.defaultValueDeserializationMethod;
const deserializedCachedOutput = cachedValue !== undefined ? deserializeValue(cachedValue) : undefined;
// compute the new value
const newValue = (0, type_fns_1.isAFunction)(args.toValue)
? yield args.toValue({ fromCachedOutput: deserializedCachedOutput })
: yield args.toValue;
// define the serialized new value
const serializeValue = (_h = (_g = options.serialize) === null || _g === void 0 ? void 0 : _g.value) !== null && _h !== void 0 ? _h : defaults_1.defaultValueSerializationMethod;
const serializedNewValue = serializeValue(newValue);
// set the new value for this key
yield cache.set(key, serializedNewValue, {
expiration: options.expiration,
});
});
return { execute, invalidate, update };
};
exports.withExtendableCachingAsync = withExtendableCachingAsync;
//# sourceMappingURL=withExtendableCachingAsync.js.map