Files
oranguru/src/GlobalStateStore/GlobalStateStore.utils.ts

135 lines
3.4 KiB
TypeScript

import { get, set } from 'idb-keyval';
import type { GlobalState } from './GlobalStateStore.types';
const STORAGE_KEY = 'APP_GLO';
const SKIP_PATHS = new Set([
'app.controls',
'initialized',
'session.connected',
'session.error',
'session.loading',
]);
const shouldSkipPath = (path: string): boolean => {
return SKIP_PATHS.has(path);
};
const filterState = (state: unknown, prefix = ''): unknown => {
if (typeof state === 'function') {
return undefined;
}
if (state === null || typeof state !== 'object') {
return state;
}
if (Array.isArray(state)) {
return state.map((item, idx) => filterState(item, `${prefix}[${idx}]`));
}
const filtered: Record<string, unknown> = {};
for (const [key, value] of Object.entries(state)) {
const path = prefix ? `${prefix}.${key}` : key;
if (shouldSkipPath(path) || typeof value === 'function') {
continue;
}
filtered[key] = filterState(value, path);
}
return filtered;
};
async function loadStorage(): Promise<Partial<GlobalState>> {
const result: Partial<GlobalState> = {};
const keys: (keyof GlobalState)[] = ['layout', 'navigation', 'owner', 'program', 'session', 'user'];
for (const key of keys) {
const storageKey = `${STORAGE_KEY}:${key}`;
// Always use localStorage for session
if (key === 'session') {
try {
if (typeof localStorage !== 'undefined') {
const data = localStorage.getItem(storageKey);
if (data) {
result[key] = JSON.parse(data);
}
}
} catch (e) {
console.error(`Failed to load ${key} from localStorage:`, e);
}
continue;
}
try {
if (typeof indexedDB !== 'undefined') {
const data = await get(storageKey);
if (data) {
result[key] = JSON.parse(data);
continue;
}
}
} catch (e) {
console.error(`Failed to load ${key} from IndexedDB, falling back to localStorage:`, e);
}
try {
if (typeof localStorage !== 'undefined') {
const data = localStorage.getItem(storageKey);
if (data) {
result[key] = JSON.parse(data);
}
}
} catch (e) {
console.error(`Failed to load ${key} from localStorage:`, e);
}
}
return result;
}
async function saveStorage(state: GlobalState): Promise<void> {
const keys: (keyof GlobalState)[] = ['layout', 'navigation', 'owner', 'program', 'session', 'user'];
for (const key of keys) {
const storageKey = `${STORAGE_KEY}:${key}`;
const filtered = filterState(state[key], key);
const serialized = JSON.stringify(filtered);
// Always use localStorage for session
if (key === 'session') {
try {
if (typeof localStorage !== 'undefined') {
localStorage.setItem(storageKey, serialized);
}
} catch (e) {
console.error(`Failed to save ${key} to localStorage:`, e);
}
continue;
}
try {
if (typeof indexedDB !== 'undefined') {
await set(storageKey, serialized);
continue;
}
} catch (e) {
console.error(`Failed to save ${key} to IndexedDB, falling back to localStorage:`, e);
}
try {
if (typeof localStorage !== 'undefined') {
localStorage.setItem(storageKey, serialized);
}
} catch (e) {
console.error(`Failed to save ${key} to localStorage:`, e);
}
}
}
export { loadStorage, saveStorage };