Spaces:
Running
Running
/** | |
* 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]: [], | |
}); |