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]: [],
});