2021-04-08 15:52:31 +02:00
|
|
|
/*
|
|
|
|
* https://github.com/morethanwords/tweb
|
|
|
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
|
|
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
|
|
|
*
|
|
|
|
* Originally from:
|
|
|
|
* https://github.com/zhukov/webogram
|
|
|
|
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
|
|
|
|
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
|
|
|
*/
|
|
|
|
|
2021-02-13 16:32:10 +01:00
|
|
|
import { DatabaseStore, DatabaseStoreName } from "../config/database";
|
2021-01-18 19:34:41 +01:00
|
|
|
import IDBStorage, { IDBOptions } from "./idb";
|
2020-06-13 10:19:39 +02:00
|
|
|
|
2021-01-18 19:34:41 +01:00
|
|
|
export default class AppStorage<Storage extends Record<string, any>/* Storage extends {[name: string]: any} *//* Storage extends Record<string, any> */> {
|
|
|
|
private storage: IDBStorage;//new CacheStorageController('session');
|
2020-12-08 20:48:44 +01:00
|
|
|
|
2021-01-18 19:34:41 +01:00
|
|
|
//private cache: Partial<{[key: string]: Storage[typeof key]}> = {};
|
|
|
|
private cache: Partial<Storage> = {};
|
|
|
|
private useStorage = true;
|
2020-12-08 20:48:44 +01:00
|
|
|
|
2021-01-18 19:34:41 +01:00
|
|
|
constructor(storageOptions: Omit<IDBOptions, 'storeName' | 'stores'> & {stores?: DatabaseStore[], storeName: DatabaseStoreName}) {
|
|
|
|
this.storage = new IDBStorage(storageOptions);
|
|
|
|
}
|
2020-12-08 20:48:44 +01:00
|
|
|
|
2021-01-18 19:34:41 +01:00
|
|
|
public getCache() {
|
|
|
|
return this.cache;
|
2020-12-08 20:48:44 +01:00
|
|
|
}
|
2020-06-13 10:19:39 +02:00
|
|
|
|
2021-01-18 19:34:41 +01:00
|
|
|
public getFromCache(key: keyof Storage) {
|
|
|
|
return this.cache[key];
|
|
|
|
}
|
2020-06-13 10:19:39 +02:00
|
|
|
|
2021-01-18 19:34:41 +01:00
|
|
|
public setToCache(key: keyof Storage, value: Storage[typeof key]) {
|
|
|
|
return this.cache[key] = value;
|
2020-06-13 10:19:39 +02:00
|
|
|
}
|
|
|
|
|
2021-01-18 19:34:41 +01:00
|
|
|
public async get(key: keyof Storage): Promise<Storage[typeof key]> {
|
|
|
|
if(this.cache.hasOwnProperty(key)) {
|
|
|
|
return this.getFromCache(key);
|
|
|
|
} else if(this.useStorage) {
|
|
|
|
let value: any;
|
|
|
|
try {
|
|
|
|
value = await this.storage.get(key as string);
|
|
|
|
//console.log('[AS]: get result:', key, value);
|
|
|
|
//value = JSON.parse(value);
|
|
|
|
} catch(e) {
|
|
|
|
if(e !== 'NO_ENTRY_FOUND') {
|
|
|
|
this.useStorage = false;
|
|
|
|
console.error('[AS]: get error:', e, key, value);
|
2020-06-13 10:19:39 +02:00
|
|
|
}
|
|
|
|
}
|
2021-01-18 19:34:41 +01:00
|
|
|
|
|
|
|
return this.cache[key] = value;
|
|
|
|
} else {
|
|
|
|
throw 'something went wrong';
|
2020-06-13 10:19:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-22 23:12:57 +01:00
|
|
|
public async set(obj: Partial<Storage>, onlyLocal = false) {
|
2020-06-13 10:19:39 +02:00
|
|
|
//console.log('storageSetValue', obj, callback, arguments);
|
|
|
|
|
2021-01-22 23:12:57 +01:00
|
|
|
for(const key in obj) {
|
2020-06-13 10:19:39 +02:00
|
|
|
if(obj.hasOwnProperty(key)) {
|
2021-01-22 23:12:57 +01:00
|
|
|
const value = obj[key];
|
2021-01-18 19:34:41 +01:00
|
|
|
this.setToCache(key, value);
|
|
|
|
|
|
|
|
// let perf = /* DEBUG */false ? performance.now() : 0;
|
|
|
|
// value = JSON.stringify(value);
|
|
|
|
|
|
|
|
// if(perf) {
|
|
|
|
// let elapsedTime = performance.now() - perf;
|
|
|
|
// if(elapsedTime > 10) {
|
|
|
|
// console.warn('LocalStorage set: stringify time by JSON.stringify:', elapsedTime, key);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
2020-12-21 01:38:21 +01:00
|
|
|
/* perf = performance.now();
|
2020-09-28 02:23:00 +02:00
|
|
|
value = stringify(value);
|
2020-10-17 00:31:58 +02:00
|
|
|
console.log('LocalStorage set: stringify time by own stringify:', performance.now() - perf); */
|
2020-06-13 10:19:39 +02:00
|
|
|
|
2021-01-22 23:12:57 +01:00
|
|
|
if(this.useStorage && !onlyLocal) {
|
2020-06-13 10:19:39 +02:00
|
|
|
try {
|
2020-12-13 00:29:12 +01:00
|
|
|
//console.log('setItem: will set', key/* , value */);
|
2020-12-21 23:38:26 +01:00
|
|
|
//await this.cacheStorage.delete(key); // * try to prevent memory leak in Chrome leading to 'Unexpected internal error.'
|
2021-01-18 19:34:41 +01:00
|
|
|
//await this.storage.save(key, new Response(value, {headers: {'Content-Type': 'application/json'}}));
|
|
|
|
await this.storage.save(key, value);
|
2020-12-13 00:29:12 +01:00
|
|
|
//console.log('setItem: have set', key/* , value */);
|
2020-12-08 20:48:44 +01:00
|
|
|
} catch(e) {
|
|
|
|
//this.useCS = false;
|
2020-12-13 00:29:12 +01:00
|
|
|
console.error('[AS]: set error:', e, key/* , value */);
|
2020-06-13 10:19:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-22 23:12:57 +01:00
|
|
|
public async remove(key: keyof Storage, saveLocal = false) {
|
|
|
|
/* if(!this.cache.hasOwnProperty(key)) {
|
|
|
|
return;
|
|
|
|
} */
|
|
|
|
|
|
|
|
if(!saveLocal) {
|
|
|
|
delete this.cache[key];
|
|
|
|
}
|
|
|
|
|
2021-01-18 19:34:41 +01:00
|
|
|
if(this.useStorage) {
|
|
|
|
try {
|
|
|
|
await this.storage.delete(key as string);
|
|
|
|
} catch(e) {
|
|
|
|
this.useStorage = false;
|
|
|
|
console.error('[AS]: remove error:', e);
|
2020-06-13 10:19:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-29 04:03:26 +02:00
|
|
|
public clear() {
|
2021-01-18 19:34:41 +01:00
|
|
|
return this.storage.deleteAll();
|
2020-06-13 10:19:39 +02:00
|
|
|
}
|
|
|
|
}
|