diff --git a/packages/chess/src/app/App.tsx b/packages/chess/src/app/App.tsx
index 862417f..6ee56c1 100644
--- a/packages/chess/src/app/App.tsx
+++ b/packages/chess/src/app/App.tsx
@@ -1,3 +1,4 @@
+import { useEffect } from 'react'
import { Routes, Route, useNavigate } from 'react-router-dom'
import { GameView } from '../ui/GameView'
import { RulesView } from '../ui/RulesView'
@@ -5,11 +6,23 @@ import { SavePanel } from '../ui/SavePanel'
import { ImportExport } from '../ui/ImportExport'
import { useChessEngine } from '../hooks/useChessEngine'
import { ChessEngine } from '../engine'
+import { loadAutoSave } from '../persist/autosave.js'
import type { AttrKey, FactValue, EntityId } from '@paratype/rete'
export function App() {
const chessState = useChessEngine()
-
+
+ // Restore autosave on mount — [] deps is intentional (run once, avoid infinite loop)
+ useEffect(() => {
+ const saved = loadAutoSave();
+ if (!saved) return;
+ const newEngine = new ChessEngine();
+ const oldFacts = newEngine.session.allFacts();
+ for (const f of oldFacts) newEngine.session.retract(f.id, f.attr as AttrKey);
+ for (const f of saved) newEngine.session.insert(f.id as EntityId, f.attr as AttrKey, f.value as FactValue);
+ chessState.loadEngine(newEngine);
+ }, []); // intentional: run once on mount, chessState ref is stable
+
return (
diff --git a/packages/chess/src/hooks/useChessEngine.ts b/packages/chess/src/hooks/useChessEngine.ts
index 056f3b1..2e3c4b9 100644
--- a/packages/chess/src/hooks/useChessEngine.ts
+++ b/packages/chess/src/hooks/useChessEngine.ts
@@ -1,6 +1,7 @@
import { useState, useRef, useCallback } from 'react';
import { ChessEngine, type GameResult } from '../engine';
import type { PieceType } from '../schema';
+import { saveAutoSave } from '../persist/autosave.js';
export function useChessEngine() {
const engineRef = useRef(null);
@@ -19,6 +20,7 @@ export function useChessEngine() {
const loadEngine = useCallback((newEngine: ChessEngine) => {
engineRef.current = newEngine;
moveHistoryRef.current = [];
+ saveAutoSave(newEngine.session.allFacts());
setTick(t => t + 1);
}, []);
@@ -43,6 +45,7 @@ export function useChessEngine() {
if (move) {
moveHistoryRef.current.push({ from, to, promoteTo });
const result = engine.applyMove(move, promoteTo);
+ saveAutoSave(engine.session.allFacts());
setTick(t => t + 1); // trigger re-render
return result;
}
@@ -60,6 +63,7 @@ export function useChessEngine() {
}
}
engineRef.current = newEngine;
+ saveAutoSave(newEngine.session.allFacts());
setTick(t => t + 1);
}
}, []);
diff --git a/packages/chess/src/persist/autosave.ts b/packages/chess/src/persist/autosave.ts
new file mode 100644
index 0000000..eaeeb49
--- /dev/null
+++ b/packages/chess/src/persist/autosave.ts
@@ -0,0 +1,23 @@
+import { exportGame, importGame } from './io.js';
+
+const AUTOSAVE_KEY = 'paratype-chess:v1:autosave';
+
+export function saveAutoSave(facts: Array<{ id: number; attr: string; value: unknown }>): void {
+ try {
+ localStorage.setItem(AUTOSAVE_KEY, exportGame(facts));
+ } catch { /* ignore quota errors */ }
+}
+
+export function loadAutoSave(): Array<{ id: number; attr: string; value: unknown }> | null {
+ try {
+ const raw = localStorage.getItem(AUTOSAVE_KEY);
+ if (!raw) return null;
+ return importGame(raw);
+ } catch {
+ return null; // silently discard invalid/stale/version-mismatched data
+ }
+}
+
+export function clearAutoSave(): void {
+ localStorage.removeItem(AUTOSAVE_KEY);
+}
diff --git a/packages/rete/tsconfig.json b/packages/rete/tsconfig.json
index dbe5244..c49dd21 100644
--- a/packages/rete/tsconfig.json
+++ b/packages/rete/tsconfig.json
@@ -2,7 +2,8 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
+ "rootDir": "src",
"composite": true
},
- "include": ["src/**/*", "tests/**/*"]
+ "include": ["src/**/*"]
}