Spaces:
Running
Running
File size: 4,944 Bytes
cc2caf9 22b1735 cc2caf9 22b1735 1904e4c 22b1735 cc2caf9 22b1735 cc2caf9 22b1735 cc2caf9 22b1735 cc2caf9 22b1735 1904e4c 22b1735 1904e4c 22b1735 1904e4c 22b1735 1904e4c 22b1735 cc2caf9 22b1735 cc2caf9 22b1735 cc2caf9 22b1735 cc2caf9 22b1735 cc2caf9 22b1735 cc2caf9 22b1735 cc2caf9 22b1735 cc2caf9 22b1735 cc2caf9 22b1735 cc2caf9 1904e4c 22b1735 cc2caf9 22b1735 1904e4c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
/**
* Storage Library for Financial Insight System
* Provides a unified interface for data storage with potential for external storage integration
*/
// Define storage keys for better type safety and avoid string duplication
export const STORAGE_KEYS = {
CHATS: 'fis-chats',
SETTINGS: 'fis-settings',
API_ENDPOINT: 'apiEndpoint',
THEME: 'fis-theme',
SOURCES: 'fis-sources',
PROFILE_STORAGE_KEY: 'fis-profile'
} as const;
// Types for our storage
export interface StorageOptions {
ttl?: number; // Time to live in milliseconds
}
export type StorageValue = string | object | number | boolean | null | undefined;
/**
* Storage service that provides unified interface for storing and retrieving data
* Currently uses localStorage, but can be extended to use external storage in the future
*/
class StorageService {
private defaults: Partial<Record<string, StorageValue>> = {};
// Set default values for storage keys
setDefaults(defaults: Partial<Record<string, StorageValue>>) {
this.defaults = defaults;
}
// Get item from storage with automatic parsing and default fallback
get<T = any>(key: string): T | null {
try {
const item = localStorage.getItem(key);
if (!item) {
// Return default if available
if (key in this.defaults) {
return this.defaults[key] as T;
}
return null;
}
const { value, expires } = JSON.parse(item);
if (expires && expires < Date.now()) {
this.remove(key);
// Return default if available
if (key in this.defaults) {
return this.defaults[key] as T;
}
return null;
}
return value as T;
} catch (error) {
console.error(`Error getting item from storage: ${key}`, error);
// Return default if available
if (key in this.defaults) {
return this.defaults[key] as T;
}
return null;
}
}
// Set item in storage with optional TTL
set(key: string, value: StorageValue, options: StorageOptions = {}): boolean {
try {
const storageItem = {
value,
expires: options.ttl ? Date.now() + options.ttl : null
};
localStorage.setItem(key, JSON.stringify(storageItem));
return true;
} catch (error) {
console.error(`Error setting item in storage: ${key}`, error);
return false;
}
}
// Remove item from storage
remove(key: string): boolean {
try {
localStorage.removeItem(key);
return true;
} catch (error) {
console.error(`Error removing item from storage: ${key}`, error);
return false;
}
}
// Check if key exists in storage
has(key: string): boolean {
return localStorage.getItem(key) !== null;
}
// Clear all storage for the application
clear(): boolean {
try {
// Only clear keys that start with our application prefix (fis-)
Object.keys(localStorage).forEach(key => {
if (key.startsWith('fis-')) {
localStorage.removeItem(key);
}
});
return true;
} catch (error) {
console.error('Error clearing storage', error);
return false;
}
}
/**
* Export all application data for keys defined in STORAGE_KEYS as a JSON object.
* Returns an object with key-value pairs.
*/
export(): Record<string, any> {
const exported: Record<string, any> = {};
Object.values(STORAGE_KEYS).forEach(key => {
try {
const item = localStorage.getItem(key);
if (item) {
exported[key] = JSON.parse(item);
}
} catch (error) {
console.error(`Error exporting key: ${key}`, error);
}
});
return exported;
}
/**
* Import data from an external source into local storage.
* Accepts an object with key-value pairs (as produced by export()).
* Overwrites existing keys, but only those defined in STORAGE_KEYS.
*/
import(data: Record<string, any>): boolean {
try {
Object.entries(data).forEach(([key, value]) => {
if (Object.values(STORAGE_KEYS).includes(key as any)) {
localStorage.setItem(key, JSON.stringify(value));
}
});
return true;
} catch (error) {
console.error('Error importing data into storage', error);
return false;
}
}
// Reset all keys to their default values
resetToDefaults(): boolean {
try {
Object.entries(this.defaults).forEach(([key, value]) => {
this.set(key, value);
});
return true;
} catch (error) {
console.error('Error resetting storage to defaults', error);
return false;
}
}
}
// Create and export a singleton instance
export const storage = new StorageService();
storage.setDefaults({
[STORAGE_KEYS.CHATS]: [],
[STORAGE_KEYS.SETTINGS]: {},
[STORAGE_KEYS.API_ENDPOINT]: "https://insight-ai-api.hf.space",
[STORAGE_KEYS.THEME]: "dark",
[STORAGE_KEYS.SOURCES]: [],
}); |