@beenotung/tslib
Version:
utils library in Typescript
108 lines (107 loc) • 4.55 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CachedObjectStore = exports.maxCacheSizeSymbol = exports.asyncStoreSymbol = exports.storeSymbol = exports.cacheSizeSymbol = exports.objectCacheSymbol = void 0;
const async_store_1 = require("./async-store");
const compare_1 = require("./compare");
const counted_cache_1 = require("./counted-cache");
const store_1 = require("./store");
exports.objectCacheSymbol = Symbol.for('objectCache');
exports.cacheSizeSymbol = Symbol.for('cacheSize');
exports.storeSymbol = Symbol.for('store');
exports.asyncStoreSymbol = Symbol.for('asyncStore');
exports.maxCacheSizeSymbol = Symbol.for('maxCacheSize');
/**
* only cache object
* raw string item are not cached
* */
class CachedObjectStore {
[exports.objectCacheSymbol] = new counted_cache_1.CountedCache();
[exports.cacheSizeSymbol] = 0;
[exports.storeSymbol];
[exports.asyncStoreSymbol];
[exports.maxCacheSizeSymbol];
constructor(dirpath, maxCacheSize = Number.MAX_SAFE_INTEGER, maxStorageSize = Number.MAX_SAFE_INTEGER) {
this[exports.storeSymbol] = store_1.Store.create((0, store_1.getLocalStorage)(dirpath, maxStorageSize));
this[exports.asyncStoreSymbol] = async_store_1.AsyncStore.create(dirpath);
this[exports.maxCacheSizeSymbol] = maxCacheSize;
}
get [store_1.storageSymbol]() {
return this[exports.storeSymbol][store_1.storageSymbol];
}
set storage(storage) {
const dirpath = storage._location;
if (typeof dirpath !== 'string') {
throw new Error('cannot swap storage instance without storage._location');
}
this[exports.storeSymbol][store_1.storageSymbol] = storage;
this[exports.asyncStoreSymbol][async_store_1.dirpathSymbol] = dirpath;
}
// cannot be cached, require too much effort to monitor every setItem and removeItem
get length() {
return this[exports.storeSymbol].length;
}
clear() {
this[exports.asyncStoreSymbol].clear();
this[exports.objectCacheSymbol].clear();
this[exports.cacheSizeSymbol] = 0;
}
clearCache() {
this[exports.objectCacheSymbol].clear();
this[exports.cacheSizeSymbol] = 0;
}
// do not cache to reduce memory load
getItem(key) {
return this[exports.storeSymbol].getItem(key);
}
getObject(key) {
if (this[exports.objectCacheSymbol].has(key)) {
const data = this[exports.objectCacheSymbol].get(key);
if (data !== null) {
return data.value;
}
}
const s = this.getItem(key);
if (s === null) {
return null;
}
const value = JSON.parse(s);
this[exports.objectCacheSymbol].set(key, { size: s.length, value });
return value;
}
// cannot be cached, require too much effort to monitor every setItem and removeItem
key(index) {
return this[exports.storeSymbol].key(index);
}
// cannot be cached, require too much effort to monitor every setItem and removeItem
keys() {
return this[exports.storeSymbol].keys();
}
removeItem(key) {
this[exports.objectCacheSymbol].remove(key);
this[exports.asyncStoreSymbol].removeItem(key);
}
setItem(key, value) {
this[exports.objectCacheSymbol].remove(key);
this[exports.asyncStoreSymbol].setItem(key, value);
}
setObject(key, value) {
const s = JSON.stringify(value);
this[exports.cacheSizeSymbol] += s.length;
if (this[exports.cacheSizeSymbol] > this[exports.maxCacheSizeSymbol]) {
const caches = this[exports.objectCacheSymbol].getAll();
caches.sort((a, b) => (0, compare_1.compare)(a[1].count, b[1].count));
for (; this[exports.cacheSizeSymbol] > this[exports.maxCacheSizeSymbol] && caches.length > 0;) {
const [key, cache] = caches.pop();
this[exports.cacheSizeSymbol] -= cache.data.size;
this[exports.objectCacheSymbol].remove(key);
}
}
this[exports.objectCacheSymbol].set(key, { size: s.length, value });
this[exports.asyncStoreSymbol].setItem(key, s);
}
static create(dirpath, maxCacheSize = Number.MAX_SAFE_INTEGER, maxStorageSize = Number.MAX_SAFE_INTEGER) {
const store = new CachedObjectStore(dirpath, maxCacheSize, maxStorageSize);
return (0, store_1.proxyStore)(store);
}
}
exports.CachedObjectStore = CachedObjectStore;