refactor/04 complete. Four families of constants that used to live inline
in store.js are now dedicated modules under frontend/data/ with their
own tests. Consumers still read the same store shape — zero call-site
changes required for the 20+ consumers of userAchievements / ipDBs /
mountingStatus / userPreferences.
New data modules (frontend/data/):
- achievements.js
ACHIEVEMENTS_DEFINITIONS — 21 {name, img} entries
createInitialAchievementsState() — factory, returns fresh keyed map
Bonus fix: IAmHuman.img previously used 'achievements/iamhuman.webp'
(missing leading slash). All 21 entries now uniformly start with
'/achievements/'. No consumer had the legacy path string baked in.
- ip-databases.js
IP_DATABASES — 7 {id, text, url, enabled} entries
createInitialIpDBs()— factory for store.ipDBs
buildDbUrl(db, ip, lang) — pure URL template substitution,
extracted from store.getDbUrl so it can
be tested without instantiating Pinia
- default-preferences.js
DEFAULT_PREFERENCES — Object.freeze'd canonical defaults
createDefaultPreferences() — writable copy factory
- sections.js (new shared source of truth)
SECTION_IDS — ['IPInfo', 'Connectivity', ..., 'AdvancedTools']
DEFAULT_SECTION — 'IPInfo'
createMountingStatus() / createLoadingStatus() — key-set factories
Previously, the same 6 section names were duplicated in three places:
store.mountingStatus keys, store.loadingStatus keys (subset), and a
hardcoded local array inside Patch.vue's checkSectionsAndTrack().
Patch.vue now imports SECTION_IDS from data/.
store.js changes:
- Import factories from data/*, replace 60+ lines of inline literal state
with factory calls
- getDbUrl() delegates URL substitution to buildDbUrl pure function
- loadPreferences() uses createDefaultPreferences()
- currentSection default uses DEFAULT_SECTION
Tests (23 new, brings total 23 → 46, all green):
- tests/achievements.test.js — definitions shape, path format,
factory isolation, runtime shape
- tests/ip-databases.test.js — definitions integrity, factory
isolation, buildDbUrl substitution
/ default lang / missing placeholder
/ null-guard
- tests/default-preferences.test.js — freeze, shape, copy isolation
- tests/sections.test.js — id order, factory isolation
Plan updates:
- refactor/04: status → ✅ done, all checkboxes ticked, audit table
(Phase A "audit results") filled in with line numbers and routing decisions
- refactor/README.md: total status for #04 → ✅
- This also ticks the store / utils sections of refactor/03 indirectly
(the new data/ tests plus existing valid-ip and api-smoke suites).
Verified: npm run check — 46 tests pass, vite build succeeds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>