UNPKG

@leyyo/cache

Version:
766 lines (765 loc) 30.8 kB
"use strict"; 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.CacheBasicAbstract = void 0; const util_1 = require("../util"); const config_1 = require("../config"); // noinspection DuplicatedCode,JSUnusedGlobalSymbols class CacheBasicAbstract { // endregion properties // region constructor constructor(channel) { this.channel = channel; this.ignoredMap = new Map(); this.disabledMap = new Map(); util_1.cacheUtil.bindAll(this); this._fillInvalidators(); } // endregion constructor // region private _fillInvalidators() { this.disabledMap.set('boolean', this.invalidator.disabledFalse); this.ignoredMap.set('boolean', this.invalidator.ignoreFalse); this.disabledMap.set('number', this.invalidator.disabledNumber); this.ignoredMap.set('number', this.invalidator.ignoreNumber); this.disabledMap.set('string', this.invalidator.disabledText); this.ignoredMap.set('string', this.invalidator.ignoreText); this.disabledMap.set('array', this.invalidator.disabledArray); this.ignoredMap.set('array', this.invalidator.ignoreArray); this.disabledMap.set('object', this.invalidator.disabledRecord); this.ignoredMap.set('object', this.invalidator.ignoreRecord); } _formatRawValue(value) { switch (typeof value) { case "string": const str = value.trim(); return str ? str : null; case "number": case "bigint": return String(value); case "boolean": return value ? 'true' : 'false'; default: return null; } } _afterSetMore(opt, fulls) { if (!opt) { return; } if (!opt.span && !opt.expiry) { return; } let milliseconds; switch (this.check.$saveSpan(opt.span)) { case "persistent": this.$persistMore(fulls).then(); break; case "timestamp": milliseconds = this.check.$timestamp(opt.expiry); if (milliseconds > 0) { this.$setTimestampMore(fulls, milliseconds).then(); } break; case "ttl": milliseconds = this.check.$timestamp(opt.expiry); if (milliseconds > 0) { this.$setTtlMore(fulls, milliseconds).then(); } break; } } _setDocsMore(key, index, value, formatted, keys) { const { full } = this.format.key(key); if (full) { if (!formatted[full]) { formatted[full] = util_1.cacheUtil.jsonOne(value); keys.push(full); } else { console.log(`Duplicated key: ${key}, index: ${index}`); } } else { console.log(`Invalid key: ${key}, index: ${index}`); } } _setRawsMore(key, index, value, formatted, keys) { const { full } = this.format.key(key); if (!formatted[full]) { const str = this._formatRawValue(value); if (!str) { console.log(`Invalid key: ${key}, index: ${index}`); return; } formatted[full] = str; keys.push(full); } console.log(`Duplicated key: ${key}, index: ${index}`); } // endregion private // region delete /** @inheritDoc */ delete(key) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } const { full } = this.format.key(key); if (!full) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY, 'Empty key'); } return this.invalidator.success((yield this.$delete(full)) ? 1 : 0, [full]); }); } /** @inheritDoc */ deleteMore(keys) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } const { fulls } = this.format.keys(keys); if (fulls.length < 1) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY, 'Empty keys'); } return this.invalidator.success(yield this.$deleteMore(fulls), fulls); }); } /** @inheritDoc */ unlink(key) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } const { full } = this.format.key(key); if (!full) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY, 'Empty key'); } return this.invalidator.success((yield this.$unlink(full)) ? 1 : 0, [full]); }); } /** @inheritDoc */ unlinkMore(keys) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } const { fulls } = this.format.keys(keys); if (fulls.length < 1) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY, 'Empty keys'); } return this.invalidator.success(yield this.$unlinkMore(fulls), fulls); }); } // endregion delete // region exists /** @inheritDoc */ exists(key) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } const { full } = this.format.key(key); if (!full) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY, 'Empty key'); } return this.invalidator.success((yield this.$exists(full)) ? 1 : 0, [full]); }); } /** @inheritDoc */ existMore(keys) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } const { fulls } = this.format.keys(keys); if (fulls.length < 1) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY, 'Empty keys'); } return this.invalidator.success(yield this.$existMore(fulls), fulls); }); } // endregion exists // region get /** @inheritDoc */ getDoc(key) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNull(); } const { full } = this.format.key(key); if (!full) { return this.invalidator.ignoreNull('Empty key'); } this.invalidator.success(util_1.cacheUtil.parseOne(yield this.$get(full)), [full]); }); } /** @inheritDoc */ listDocs(keys) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledArray(); } const { fulls } = this.format.keys(keys); if (fulls.length < 1) { return this.invalidator.ignoreArray('Empty keys'); } return this.invalidator.success(util_1.cacheUtil.parseArray(util_1.cacheUtil.asArray(yield this.$getMore(fulls))), fulls); }); } /** @inheritDoc */ getRaw(key) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNull(); } const { full } = this.format.key(key); if (!full) { return this.invalidator.ignoreNull('Empty key'); } this.invalidator.success(yield this.$get(full), [full]); }); } /** @inheritDoc */ listRaws(keys) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledArray(); } const { fulls } = this.format.keys(keys); if (fulls.length < 1) { return this.invalidator.ignoreArray('Empty keys'); } return this.invalidator.success(util_1.cacheUtil.asArray(yield this.$getMore(fulls)), fulls); }); } // endregion get // region set setDoc(p1, p2, p3) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } let key; let value; let opt; // case 1, with key if (['string', 'number'].includes(typeof p1) || Array.isArray(p1)) { key = this.format.key(p1); if (!key.full) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY); } value = p2; opt = p3; if (!opt) { opt = {}; } } // case 2, without key else { value = p1; opt = p2; if (!opt) { opt = {}; } // grab key from object with properties in options, else properties in config let properties = util_1.cacheUtil.parseProperties(opt.property, this.prop.property); if (properties.length < 1) { throw new Error('Key could not be created!'); } const keyParts = properties.map(p => value[p]); key = this.format.key(keyParts); if (!key.full) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY); } } if (!value) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_VALUE); } const result = yield this.$set(key.full, util_1.cacheUtil.jsonOne(value), opt); if (opt.span === 'persistent') { // later this.$persist(key.full).then().catch(e => console.error(e)); } if (opt.returnPrevious !== undefined) { return this.invalidator.success(util_1.cacheUtil.parseOne(result), [key.full]); } return this.invalidator.success(result === 'OK' ? 1 : 0, [key.full]); }); } setRaw(key, value, opt) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } const { full } = this.format.key(key); if (!full) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY); } const formattedValue = this._formatRawValue(value); if (!formattedValue) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_VALUE, 'Invalid type value'); } const result = yield this.$set(full, formattedValue, opt); if (opt.span === 'persistent') { // later this.$persist(full).then().catch(e => console.error(e)); } if (opt.returnPrevious !== undefined) { return this.invalidator.success(result, [full]); } return this.invalidator.success(result === 'OK' ? 1 : 0, [full]); }); } setDocsMore(values, opt) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } if (!values) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_VALUE, 'Empty values'); } if (typeof values !== 'object') { throw new Error('Invalid set data'); } const formatted = {}; const keys = []; // Array<Partial<A>> | Array<[KeyId, Partial<A>]> if (Array.isArray(values)) { if (values.length < 1) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_VALUE, 'Empty array items'); } const first = values[0]; // Array<[KeyId, Partial<A>]> if (Array.isArray(first) && first.length === 2) { const arr = values; arr.forEach((item, index) => { const [key, value] = item; this._setDocsMore(key, index, value, formatted, keys); }); } // Array<Partial<A>> else if (first && typeof first === 'object' && !Array.isArray(first)) { const arr = values; const opt2 = opt; let properties = util_1.cacheUtil.parseProperties(opt2.property, this.prop.property); if (properties.length < 1) { throw new Error('Key could not be created!'); } arr.forEach((value, index) => { const keyParts = properties.map(p => value[p]); this._setDocsMore(keyParts, index, value, formatted, keys); }); } else { throw new Error('Invalid set data'); } } // Map<KeyId, Partial<A>> else if (values instanceof Map) { if (values.size < 1) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_VALUE, 'Empty map items'); } let index = 0; for (const [key, value] of values.entries()) { this._setDocsMore(key, index, value, formatted, keys); index++; } } // Record<KeyId, Partial<A>> else { if (Object.keys(values).length < 1) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_VALUE, 'Empty record value'); } let index = 0; for (const [key, value] of Object.entries(values)) { this._setDocsMore(key, index, value, formatted, keys); index++; } } if (keys.length < 1) { this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY); } const result = yield this.$setMore(formatted); this._afterSetMore(opt, keys); return this.invalidator.success(result === 'OK' ? 1 : 0, keys); }); } setRawsMore(values, opt) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } if (!values) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_VALUE, 'Empty value'); } if (typeof values !== 'object') { throw new Error('Invalid set data'); } const formatted = {}; const keys = []; // Array<Partial<A>> | Array<[KeyId, Partial<A>]> if (Array.isArray(values)) { if (values.length < 1) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_VALUE, 'Empty array items'); } const first = values[0]; // Array<[KeyId, Partial<A>]> if (Array.isArray(first) && first.length === 2) { const arr = values; arr.forEach((item, index) => { const [key, value] = item; this._setRawsMore(key, index, value, formatted, keys); }); } else { throw new Error('Invalid set data'); } } // Map<KeyId, Partial<A>> else if (values instanceof Map) { if (values.size < 1) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_VALUE, 'Empty map items'); } let index = 0; for (const [key, value] of values.entries()) { this._setRawsMore(key, index, value, formatted, keys); index++; } } // Record<KeyId, Partial<A>> else { if (Object.keys(values).length < 1) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_VALUE, 'Empty record value'); } let index = 0; for (const [key, value] of Object.entries(values)) { this._setRawsMore(key, index, value, formatted, keys); index++; } } if (keys.length < 1) { this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY, 'Empty keys'); } const result = yield this.$setMore(formatted); this._afterSetMore(opt, keys); return this.invalidator.success(result === 'OK' ? 1 : 0, keys); }); } // endregion set // region other /** @inheritDoc */ copy(source, destination, opt) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } const sourceKey = this.format.key(source); if (!sourceKey.full) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY, 'Source is empty'); } const destinationKey = this.format.key(destination); if (!destinationKey.full) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_VALUE, 'Destination is empty'); } return this.invalidator.success((yield this.$copy(sourceKey.full, destinationKey.full, opt)) ? 1 : 0, [sourceKey.full, destinationKey.full]); }); } /** @inheritDoc */ getType(key) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledText(); } const { full } = this.format.key(key); if (!full) { return this.invalidator.ignoreText('Empty key'); } return this.invalidator.success(yield this.$type(full), [full]); }); } /** @inheritDoc */ getTypeMore(keys) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledArray(); } const { fulls } = this.format.keys(keys); if (fulls.length < 1) { return this.invalidator.ignoreArray('Empty keys'); } return this.invalidator.success(yield this.$typeMore(fulls), fulls); }); } /** @inheritDoc */ getInfo(key) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return null; } const { full } = this.format.key(key); if (!full) { return null; } return Promise.resolve(undefined); }); } // endregion other // region expiry /** @inheritDoc */ getTimestamp(key, opt) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } const { full } = this.format.key(key); if (!full) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY, 'Empty key'); } const milliseconds = yield this.$getTimestamp(full); if (milliseconds < 1) { return this.invalidator.success(milliseconds, [full]); } if (!opt) { opt = {}; } const unit = this.check.$expiryUnit(opt.unit); switch (unit) { case "milliseconds": return this.invalidator.success(milliseconds, [full]); case 'seconds': return this.invalidator.success(Math.floor(milliseconds / 1000), [full]); case 'minutes': return this.invalidator.success(Math.floor(milliseconds / 60000), [full]); default: return this.invalidator.success(milliseconds, [full]); } }); } /** @inheritDoc */ getTimestampMore(keys, opt) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledArray(); } const { fulls } = this.format.keys(keys); if (fulls.length < 1) { return this.invalidator.ignoreArray('Empty keys'); } const times = yield this.$getTimestampMore(fulls); if (times.length < 1) { return this.invalidator.success(times, fulls); } if (!opt) { opt = {}; } const unit = this.check.$expiryUnit(opt.unit); switch (unit) { case "milliseconds": return this.invalidator.success(times, fulls); case 'seconds': return this.invalidator.success(times.map(ms => ms > 0 ? Math.floor(ms / 1000) : ms), fulls); case 'minutes': return this.invalidator.success(times.map(ms => ms > 0 ? Math.floor(ms / 60000) : ms), fulls); default: return this.invalidator.success(times, fulls); } }); } /** @inheritDoc */ getTtl(key, opt) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } const { full } = this.format.key(key); if (!full) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY, 'Empty key'); } const milliseconds = yield this.$getTtl(full); if (milliseconds < 1) { return this.invalidator.success(milliseconds, [full]); } if (!opt) { opt = {}; } const unit = this.check.$expiryUnit(opt.unit); switch (unit) { case "milliseconds": return this.invalidator.success(milliseconds, [full]); case 'seconds': return this.invalidator.success(Math.floor(milliseconds / 1000), [full]); case 'minutes': return this.invalidator.success(Math.floor(milliseconds / 60000), [full]); default: return this.invalidator.success(milliseconds, [full]); } }); } /** @inheritDoc */ getTtlMore(keys, opt) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledArray(); } const { fulls } = this.format.keys(keys); if (fulls.length < 1) { return this.invalidator.ignoreArray('Empty keys'); } const times = yield this.$getTtlMore(fulls); if (times.length < 1) { return this.invalidator.success(times, fulls); } if (!opt) { opt = {}; } const unit = this.check.$expiryUnit(opt.unit); switch (unit) { case "milliseconds": return this.invalidator.success(times, fulls); case 'seconds': return this.invalidator.success(times.map(ms => ms > 0 ? Math.floor(ms / 1000) : ms), fulls); case 'minutes': return this.invalidator.success(times.map(ms => ms > 0 ? Math.floor(ms / 60000) : ms), fulls); default: return this.invalidator.success(times, fulls); } }); } /** @inheritDoc */ setTimestamp(key, opt) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } const { full } = this.format.key(key); if (!full) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY, 'Empty key'); } if (!opt) { opt = {}; } const milliseconds = this.check.$timestamp(opt.expiry); if (milliseconds < 1) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_VALUE, 'Invalid time value'); } const mode = this.check.$expiryMode(opt.mode); this.invalidator.success(yield this.$setTimestamp(full, milliseconds, mode), [full]); }); } /** @inheritDoc */ setTimestampMore(keys, opt) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledArray(); } const { fulls } = this.format.keys(keys); if (fulls.length < 1) { return this.invalidator.ignoreArray('Empty keys'); } if (!opt) { opt = {}; } const milliseconds = this.check.$timestamp(opt.expiry); if (milliseconds < 1) { return this.invalidator.ignoreArray('Invalid time value'); } const mode = this.check.$expiryMode(opt.mode); this.invalidator.success(yield this.$setTimestampMore(fulls, milliseconds, mode), fulls); }); } /** @inheritDoc */ setTtl(key, opt) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } const { full } = this.format.key(key); if (!full) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY, 'Empty key'); } if (!opt) { opt = {}; } const milliseconds = this.check.$timestamp(opt.expiry); if (milliseconds < 1) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_VALUE, 'Invalid time value'); } const mode = this.check.$expiryMode(opt.mode); this.invalidator.success(yield this.$setTtl(full, milliseconds, mode), [full]); }); } /** @inheritDoc */ setTtlMore(keys, opt) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledArray(); } const { fulls } = this.format.keys(keys); if (fulls.length < 1) { return this.invalidator.ignoreArray('Empty keys'); } if (!opt) { opt = {}; } const milliseconds = this.check.$timestamp(opt.expiry); if (milliseconds < 1) { return this.invalidator.ignoreArray('Invalid time value'); } const mode = this.check.$expiryMode(opt.mode); this.invalidator.success(yield this.$setTtlMore(fulls, milliseconds, mode), fulls); }); } /** @inheritDoc */ persist(key) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledNumber(config_1.CACHE_DISABLED); } const { full } = this.format.key(key); if (!full) { return this.invalidator.ignoreNumber(config_1.CACHE_EMPTY_KEY, 'Empty key'); } return this.invalidator.success(yield this.$persist(full), [full]); }); } /** @inheritDoc */ persistMore(keys) { return __awaiter(this, void 0, void 0, function* () { if (!this.prop.enabled) { return this.invalidator.disabledArray(); } const { fulls } = this.format.keys(keys); if (fulls.length < 1) { return this.invalidator.ignoreArray('Empty keys'); } return this.invalidator.success(yield this.$persistMore(fulls), fulls); }); } // endregion expiry // region secure get $flat() { return this; } get $secure() { return this; } get $back() { return this; } $init() { this.format = this.channel.format; this.invalidator = this.channel.invalidator; this.prop = this.channel.prop; this.check = this.channel.prop.$secure; } } exports.CacheBasicAbstract = CacheBasicAbstract;