feat(store): load/save and target accessors with validation

This commit is contained in:
dev
2026-06-01 16:08:42 -05:00
parent 48e51054ca
commit 231890a9e0
3 changed files with 138 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
import { parseTarget } from './pure.js';
const KEY_TARGETS = 'tat.targets';
const KEY_HISTORY = 'tat.history';
const KEY_PREFS = 'tat.prefs';
const DEFAULT_PREFS = { version: 1, mode: 'free', pos: { x: 0, y: 0 } };
export class Store {
constructor({ storage, onWarn = (m) => console.warn(m) } = {}) {
if (!storage) throw new Error('Store requires a storage object');
this.storage = storage;
this.onWarn = onWarn;
this.targets = this._loadJson(KEY_TARGETS, {});
this.history = this._loadJson(KEY_HISTORY, {});
this.prefs = this._mergePrefs(this._loadJson(KEY_PREFS, null));
}
_loadJson(key, fallback) {
let raw;
try {
raw = this.storage.getItem(key);
} catch {
return fallback;
}
if (raw == null) return fallback;
try {
return JSON.parse(raw);
} catch {
this.onWarn(`[tat] discarding corrupted ${key}`);
try { this.storage.removeItem(key); } catch { /* noop */ }
return fallback;
}
}
_saveJson(key, value) {
try {
this.storage.setItem(key, JSON.stringify(value));
return true;
} catch (e) {
this.onWarn(`[tat] failed to persist ${key}: ${e.message}`);
return false;
}
}
_mergePrefs(loaded) {
if (!loaded || loaded.version !== 1) return { ...DEFAULT_PREFS };
return { ...DEFAULT_PREFS, ...loaded };
}
getTarget(attr) {
const v = this.targets[attr];
return typeof v === 'number' && v > 0 ? v : null;
}
setTarget(attr, value) {
const parsed = parseTarget(value);
if (parsed === null) return false;
this.targets[attr] = parsed;
return this._saveJson(KEY_TARGETS, this.targets);
}
getPrefs() {
return { ...this.prefs };
}
setMode(mode) {
if (mode !== 'free' && mode !== 'anchored') return false;
this.prefs.mode = mode;
return this._saveJson(KEY_PREFS, this.prefs);
}
setPos(pos) {
if (!pos || typeof pos.x !== 'number' || typeof pos.y !== 'number') return false;
this.prefs.pos = { x: pos.x, y: pos.y };
return this._saveJson(KEY_PREFS, this.prefs);
}
}