feat(#9): export/import состояния — backup в JSON и восстановление
This commit is contained in:
@@ -504,3 +504,56 @@ export function setGameEnabled(id: GameId, enabled: boolean): void {
|
||||
state.gamesEnabled = { ...state.gamesEnabled, [id]: enabled }
|
||||
scheduleWrite()
|
||||
}
|
||||
|
||||
// ----- Export / Import -----
|
||||
|
||||
/**
|
||||
* Полный snapshot persisted-state (включая историю и schema-version).
|
||||
* Используется для backup'а или переноса на другую машину.
|
||||
*/
|
||||
export function exportState(): string {
|
||||
const state = getState()
|
||||
return JSON.stringify(
|
||||
{
|
||||
__schemaVersion: CURRENT_SCHEMA_VERSION,
|
||||
__exportedAt: new Date().toISOString(),
|
||||
__appVersion: app.getVersion(),
|
||||
...state
|
||||
},
|
||||
null,
|
||||
2
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Импорт snapshot'а. Перезаписывает текущий state. Возвращает true при
|
||||
* успехе. Идёт через тот же coerce + runMigrations что и load() — это
|
||||
* валидирует тип/диапазоны.
|
||||
*
|
||||
* НЕ объединяет с текущим state (merge сложен: дубликаты id, конфликты
|
||||
* settings) — простое replace. Перед импортом UI должен спросить
|
||||
* подтверждение.
|
||||
*/
|
||||
export function importState(raw: string): boolean {
|
||||
let parsed: unknown
|
||||
try {
|
||||
parsed = JSON.parse(raw)
|
||||
} catch (e) {
|
||||
log.warn('[store] import: invalid JSON', e)
|
||||
return false
|
||||
}
|
||||
if (!isValidParsed(parsed)) {
|
||||
log.warn('[store] import: expected object')
|
||||
return false
|
||||
}
|
||||
try {
|
||||
const migrated = runMigrations(parsed)
|
||||
const coerced = coerce(migrated)
|
||||
cache = coerced
|
||||
flushSync()
|
||||
return true
|
||||
} catch (e) {
|
||||
log.error('[store] import: coerce/migrate failed', e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user