refactor: complete error handling standardization (issue #101)
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m26s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m26s
Prestige Store: - Convert doPrestige() to return Result<void> with specific error codes (INVALID_PRESTIGE_ID, PRESTIGE_MAX_LEVEL, INSUFFICIENT_INSIGHT) - Convert startPactRitual() to return Result<void> with specific error codes (GUARDIAN_NOT_DEFEATED, PACT_ALREADY_SIGNED, PACT_SLOTS_FULL, INSUFFICIENT_MANA, RITUAL_IN_PROGRESS) Combat Actions: - Add try/catch wrapper inside processCombatTick with safe fallback defaults - Add makeDefaultCombatTickResult helper for error recovery LocalStorage Error Handling: - Create safe-persist.ts utility wrapping localStorage with error handling (corrupted JSON, quota exceeded, unexpected failures) - Update all 8 Zustand stores to use createSafeStorage() in persist middleware UI Updates: - Update GuardianPactsTab to use Result pattern for ritual error messages Tests: - Update store-actions-combat-prestige.test.ts for Result return types - Update store-actions.test.ts ManaStore tests for Result pattern - Remove duplicate Prestige/Discipline sections from store-actions.test.ts - All files under 400 line limit 601 tests pass (3 pre-existing failures in spire-utils.test.ts)
This commit is contained in:
@@ -31,6 +31,7 @@ import { useCraftingStore } from './craftingStore';
|
||||
import { useDisciplineStore } from './discipline-slice';
|
||||
import { ATTUNEMENTS_DEF, getAttunementConversionRate } from '../data/attunements';
|
||||
import { createResetGame, createGatherMana } from './gameActions';
|
||||
import { createSafeStorage } from '../utils/safe-persist';
|
||||
import { createStartNewLoop } from './gameLoopActions';
|
||||
import { buildTickContext, applyTickWrites } from './tick-pipeline';
|
||||
import type { TickContext, TickWrites } from './tick-pipeline';
|
||||
@@ -70,19 +71,20 @@ export const useGameStore = create<GameCoordinatorStore>()(
|
||||
},
|
||||
|
||||
tick: () => {
|
||||
// ── Phase 1: Read — snapshot all store states once ──────────────────
|
||||
const ctx = buildTickContext({
|
||||
game: get(),
|
||||
ui: useUIStore.getState(),
|
||||
prestige: usePrestigeStore.getState(),
|
||||
mana: useManaStore.getState(),
|
||||
combat: useCombatStore.getState(),
|
||||
crafting: useCraftingStore.getState(),
|
||||
attunement: useAttunementStore.getState(),
|
||||
discipline: useDisciplineStore.getState(),
|
||||
});
|
||||
try {
|
||||
// ── Phase 1: Read — snapshot all store states once ──────────────────
|
||||
const ctx = buildTickContext({
|
||||
game: get(),
|
||||
ui: useUIStore.getState(),
|
||||
prestige: usePrestigeStore.getState(),
|
||||
mana: useManaStore.getState(),
|
||||
combat: useCombatStore.getState(),
|
||||
crafting: useCraftingStore.getState(),
|
||||
attunement: useAttunementStore.getState(),
|
||||
discipline: useDisciplineStore.getState(),
|
||||
});
|
||||
|
||||
if (ctx.ui.gameOver || ctx.ui.paused) return;
|
||||
if (ctx.ui.gameOver || ctx.ui.paused) return;
|
||||
|
||||
// ── Phase 2: Compute — derive all updates ───────────────────────────
|
||||
const writes: TickWrites = { logs: [] };
|
||||
@@ -322,6 +324,14 @@ export const useGameStore = create<GameCoordinatorStore>()(
|
||||
setDiscipline: (w) => useDisciplineStore.setState(w),
|
||||
addLogs: (msgs) => msgs.forEach((m) => useUIStore.getState().addLog(m)),
|
||||
});
|
||||
} catch (error) {
|
||||
// Log error to UI store if available, otherwise console error
|
||||
try {
|
||||
useUIStore.getState().addLog(`⚠️ Tick error: ${error.message}`);
|
||||
} catch {
|
||||
console.error('Tick error:', error);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
resetGame: createResetGame(set, initialState),
|
||||
@@ -332,6 +342,7 @@ export const useGameStore = create<GameCoordinatorStore>()(
|
||||
gatherMana: createGatherMana(),
|
||||
}),
|
||||
{
|
||||
storage: createSafeStorage(),
|
||||
name: 'mana-loop-game-storage',
|
||||
partialize: (state) => ({
|
||||
day: state.day,
|
||||
|
||||
Reference in New Issue
Block a user