78 lines
1.7 KiB
TypeScript
78 lines
1.7 KiB
TypeScript
import localforage from 'localforage';
|
|
|
|
// Define the structure of the stored data
|
|
interface StorageItem<T> {
|
|
value: T;
|
|
expire: number | null; // Expiration timestamp, null means valid permanently
|
|
}
|
|
|
|
class Storage {
|
|
constructor() {
|
|
// Default configuration (optional)
|
|
localforage.config({
|
|
name: 'RiskGuard_V1',
|
|
storeName: 'key_value_pairs',
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Set cache (add/update)
|
|
* @param key Key
|
|
* @param value Value
|
|
* @param ttl Expiration time (unit: seconds). If not passed, it will be valid permanently.
|
|
*/
|
|
async set<T>(key: string, value: T, ttl?: number): Promise<T> {
|
|
const expire = ttl ? Date.now() + ttl * 1000 : null;
|
|
const item: StorageItem<T> = {
|
|
value,
|
|
expire,
|
|
};
|
|
await localforage.setItem(key, item);
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Get cache (query)
|
|
* @param key Key
|
|
* @returns Returns the original data if not expired or does not exist, otherwise returns null
|
|
*/
|
|
async get<T>(key: string): Promise<T | null> {
|
|
const item = await localforage.getItem<StorageItem<T>>(key);
|
|
|
|
if (!item) return null;
|
|
|
|
// Check if expired
|
|
if (item.expire !== null && Date.now() > item.expire) {
|
|
await this.remove(key); // Immediately clean up if expired
|
|
return null;
|
|
}
|
|
|
|
return item.value;
|
|
}
|
|
|
|
/**
|
|
* Remove cache (delete)
|
|
* @param key Key
|
|
*/
|
|
async remove(key: string): Promise<void> {
|
|
await localforage.removeItem(key);
|
|
}
|
|
|
|
/**
|
|
* Clear all caches
|
|
*/
|
|
async clear(): Promise<void> {
|
|
await localforage.clear();
|
|
}
|
|
|
|
/**
|
|
* Get all keys
|
|
*/
|
|
async keys(): Promise<string[]> {
|
|
return await localforage.keys();
|
|
}
|
|
}
|
|
|
|
// Export singleton
|
|
export const storage = new Storage();
|