refactor: complete error handling standardization (issue #101)
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:
2026-05-22 09:19:20 +02:00
parent 8a7ddaae27
commit 49f8de01ca
21 changed files with 542 additions and 547 deletions
+17
View File
@@ -13,6 +13,9 @@ import { useUIStore } from './uiStore';
import * as ApplicationActions from '../crafting-actions/application-actions';
import * as PreparationActions from '../crafting-actions/preparation-actions';
import * as CraftingEquipment from '../crafting-equipment';
import { ErrorCode } from '../utils/result';
import { createSafeStorage } from '../utils/safe-persist';
import type { Result } from '../utils/result';
export const useCraftingStore = create<CraftingStore>()(
persist(
@@ -217,6 +220,19 @@ export const useCraftingStore = create<CraftingStore>()(
);
if (result) {
useCombatStore.setState({ currentAction: 'prepare' });
set({ lastError: null });
} else {
const state = get();
const instance = state.equipmentInstances[equipmentInstanceId];
let message = 'Cannot start preparation';
if (!instance) {
message = `Equipment instance not found: ${equipmentInstanceId}`;
} else if (instance.tags?.includes('Ready for Enchantment')) {
message = 'Equipment is already prepared';
} else {
message = 'Insufficient mana for preparation';
}
set({ lastError: { code: ErrorCode.INVALID_INPUT, message, timestamp: Date.now() } });
}
return result;
},
@@ -363,6 +379,7 @@ export const useCraftingStore = create<CraftingStore>()(
};
},
{
storage: createSafeStorage(),
name: 'mana-loop-crafting',
partialize: (state) => ({
designProgress: state.designProgress,