import { Board, type BoardJson } from '@scrabble-solver/types'; import store2 from 'store2'; import type { Rack } from '@/types'; import type { SettingsState } from './settings/types'; const BOARD = 'board'; const RACK = 'rack'; const SETTINGS = 'settings'; const LEGACY_KEYS: Record = { autoGroupTiles: 'auto-group-tiles', game: 'config-id', highlightUnreachableCells: 'highlight-unreachable-cells', inputMode: 'input-mode', locale: 'locale', removeCellFilters: 'remove-cell-filters', showCoordinates: 'show-coordinates', }; const store = store2.namespace('scrabble-solver'); /** * Introduced in 2.15.26 on 2026/04/27. * Life expectancy: 1y. */ const migrateLegacySettings = (): Partial => { const settings: Partial = {}; let hasLegacy = false; for (const [setting, legacyKey] of Object.entries(LEGACY_KEYS) as [keyof SettingsState, string][]) { if (store.has(legacyKey)) { settings[setting] = store.get(legacyKey); store.remove(legacyKey); hasLegacy = true; } } if (hasLegacy) { store.set(SETTINGS, settings, true); } return settings; }; export const localStorage = { getBoard(): Board | undefined { const serialized = store.get(BOARD) as string | undefined; return serialized ? Board.fromJson(JSON.parse(serialized) as BoardJson) : undefined; }, setBoard(board: Board | undefined): void { const serialized = board ? JSON.stringify(board.toJson()) : board; store.set(BOARD, serialized, true); }, getRack(): Rack | undefined { return store.get(RACK) as Rack | undefined; }, setRack(rack: Rack | undefined): void { store.set(RACK, rack, true); }, getSettings(): Partial { const stored = store.get(SETTINGS) as Partial | undefined; return stored ?? migrateLegacySettings(); }, setSettings(settings: SettingsState): void { store.set(SETTINGS, settings, true); }, };