Spaces:
Sleeping
Sleeping
| /** | |
| * Frontend Storage Utility | |
| * | |
| * Provides a centralized API for storing and retrieving data in browser storage. | |
| * Supports both sessionStorage and localStorage with type-safe operations. | |
| * | |
| * Features: | |
| * - Type-safe storage operations | |
| * - Automatic JSON serialization/deserialization | |
| * - Error handling with fallback values | |
| * - Namespaced keys to avoid collisions | |
| * - Support for both session and local storage | |
| */ | |
| /** | |
| * Storage type enum | |
| */ | |
| export enum StorageType { | |
| SESSION = "session", | |
| LOCAL = "local" | |
| } | |
| /** | |
| * Storage keys enum - Add new keys here | |
| */ | |
| export enum StorageKey { | |
| // Game state | |
| GAME_STATE = "trigoGameState", | |
| // AI settings | |
| AI_PLAYER_COLOR = "trigoAIPlayerColor", | |
| // User preferences (examples for future use) | |
| // THEME = "trigoTheme", | |
| // LANGUAGE = "trigoLanguage", | |
| // BOARD_SHAPE = "trigoBoardShape", | |
| // CAMERA_POSITION = "trigoCameraPosition", | |
| } | |
| /** | |
| * Storage configuration | |
| */ | |
| interface StorageConfig { | |
| type: StorageType; | |
| prefix?: string; // Optional namespace prefix for all keys | |
| } | |
| /** | |
| * Default configuration | |
| */ | |
| const DEFAULT_CONFIG: StorageConfig = { | |
| type: StorageType.SESSION, | |
| prefix: "" // No prefix by default, keys already have 'trigo' prefix | |
| }; | |
| /** | |
| * Get the appropriate storage instance | |
| */ | |
| function getStorage(type: StorageType): Storage { | |
| return type === StorageType.SESSION ? sessionStorage : localStorage; | |
| } | |
| /** | |
| * Build full storage key with optional prefix | |
| */ | |
| function buildKey(key: StorageKey, prefix?: string): string { | |
| return prefix ? `${prefix}${key}` : key; | |
| } | |
| /** | |
| * Storage Manager Class | |
| */ | |
| export class StorageManager { | |
| private config: StorageConfig; | |
| constructor(config: Partial<StorageConfig> = {}) { | |
| this.config = { ...DEFAULT_CONFIG, ...config }; | |
| } | |
| /** | |
| * Get storage instance based on configuration | |
| */ | |
| private getStorageInstance(): Storage { | |
| return getStorage(this.config.type); | |
| } | |
| /** | |
| * Set a value in storage | |
| * @param key - Storage key | |
| * @param value - Value to store (will be JSON stringified) | |
| * @returns true if successful, false otherwise | |
| */ | |
| set<T>(key: StorageKey, value: T): boolean { | |
| try { | |
| const storage = this.getStorageInstance(); | |
| const fullKey = buildKey(key, this.config.prefix); | |
| const serialized = JSON.stringify(value); | |
| storage.setItem(fullKey, serialized); | |
| return true; | |
| } catch (error) { | |
| console.warn(`[Storage] Failed to set ${key}:`, error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Get a value from storage | |
| * @param key - Storage key | |
| * @param defaultValue - Default value if key doesn't exist or parsing fails | |
| * @returns Stored value or default value | |
| */ | |
| get<T>(key: StorageKey, defaultValue: T): T { | |
| try { | |
| const storage = this.getStorageInstance(); | |
| const fullKey = buildKey(key, this.config.prefix); | |
| const item = storage.getItem(fullKey); | |
| if (item === null) { | |
| return defaultValue; | |
| } | |
| return JSON.parse(item) as T; | |
| } catch (error) { | |
| console.warn(`[Storage] Failed to get ${key}:`, error); | |
| return defaultValue; | |
| } | |
| } | |
| /** | |
| * Get a string value directly (no JSON parsing) | |
| * Useful for simple string values | |
| */ | |
| getString(key: StorageKey, defaultValue: string = ""): string { | |
| try { | |
| const storage = this.getStorageInstance(); | |
| const fullKey = buildKey(key, this.config.prefix); | |
| return storage.getItem(fullKey) ?? defaultValue; | |
| } catch (error) { | |
| console.warn(`[Storage] Failed to get string ${key}:`, error); | |
| return defaultValue; | |
| } | |
| } | |
| /** | |
| * Set a string value directly (no JSON stringification) | |
| * Useful for simple string values | |
| */ | |
| setString(key: StorageKey, value: string): boolean { | |
| try { | |
| const storage = this.getStorageInstance(); | |
| const fullKey = buildKey(key, this.config.prefix); | |
| storage.setItem(fullKey, value); | |
| return true; | |
| } catch (error) { | |
| console.warn(`[Storage] Failed to set string ${key}:`, error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Remove a value from storage | |
| * @param key - Storage key | |
| * @returns true if successful, false otherwise | |
| */ | |
| remove(key: StorageKey): boolean { | |
| try { | |
| const storage = this.getStorageInstance(); | |
| const fullKey = buildKey(key, this.config.prefix); | |
| storage.removeItem(fullKey); | |
| return true; | |
| } catch (error) { | |
| console.warn(`[Storage] Failed to remove ${key}:`, error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Check if a key exists in storage | |
| */ | |
| has(key: StorageKey): boolean { | |
| try { | |
| const storage = this.getStorageInstance(); | |
| const fullKey = buildKey(key, this.config.prefix); | |
| return storage.getItem(fullKey) !== null; | |
| } catch (error) { | |
| console.warn(`[Storage] Failed to check ${key}:`, error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Clear all items from storage | |
| * WARNING: This clears ALL items in the storage, not just trigo-related ones | |
| */ | |
| clear(): boolean { | |
| try { | |
| const storage = this.getStorageInstance(); | |
| storage.clear(); | |
| return true; | |
| } catch (error) { | |
| console.warn("[Storage] Failed to clear storage:", error); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Get the current storage type | |
| */ | |
| getStorageType(): StorageType { | |
| return this.config.type; | |
| } | |
| /** | |
| * Switch storage type | |
| */ | |
| setStorageType(type: StorageType): void { | |
| this.config.type = type; | |
| } | |
| } | |
| /** | |
| * Default storage manager instance (sessionStorage) | |
| */ | |
| export const storage = new StorageManager(); | |
| /** | |
| * Local storage manager instance | |
| * Note: Named localStorageManager to avoid conflict with built-in localStorage | |
| */ | |
| export const localStorageManager = new StorageManager({ type: StorageType.LOCAL }); | |
| /** | |
| * Example helper functions for future use: | |
| * | |
| * export function saveTheme(theme: "light" | "dark"): boolean { | |
| * return localStorageManager.setString(StorageKey.THEME, theme); | |
| * } | |
| * | |
| * export function loadTheme(): "light" | "dark" { | |
| * const stored = localStorageManager.getString(StorageKey.THEME); | |
| * return stored === "dark" ? "dark" : "light"; | |
| * } | |
| * | |
| * export function saveBoardShape(shape: { x: number; y: number; z: number }): boolean { | |
| * return storage.set(StorageKey.BOARD_SHAPE, shape); | |
| * } | |
| * | |
| * export function loadBoardShape(): { x: number; y: number; z: number } | null { | |
| * return storage.get(StorageKey.BOARD_SHAPE, null); | |
| * } | |
| */ | |