@leyyo/cache
Version:
Common cache library
766 lines (765 loc) • 30.8 kB
JavaScript
"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;