feat: add store_versions.ts — localStorage schema versioning for ae_loc and ae_events_loc
Persistent stores grow and change over time. svelte-persisted-store deep-merges old localStorage values with new defaults, so stale values (e.g. hash_prefix_length: 1) silently survive schema changes and cause subtle bugs. - src/lib/stores/store_versions.ts: Single source of truth for AE_LOC_VERSION / AE_EVENTS_LOC_VERSION. Side-effect on import: reads raw localStorage and wipes if __version mismatches. Must be imported first in ae_stores.ts and ae_events_stores.ts so the wipe happens before persisted() hydrates from localStorage. - ae_stores.ts + ae_events_stores.ts: Import store_versions as first import; add __version to persisted store defaults. - documentation/TODO__Agents.md: Added stores refactor task — both store files need a cleanup pass. Bump AE_LOC_VERSION or AE_EVENTS_LOC_VERSION by 1 on breaking schema changes. Non-breaking changes (new optional fields, default value tweaks) do not need a bump. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,15 @@
|
||||
|
||||
## 🚧 Upcoming High Priority
|
||||
|
||||
### [Stores] Refactor — ae_stores.ts and ae_events_stores.ts cleanup
|
||||
Both files have grown organically and are messy. Refactor goals:
|
||||
- Split into focused files per domain (core, user/auth, files, module-specific)
|
||||
- Remove dead/commented-out code and stale `ver`/`ver_idb` constants from data structs (replaced by `__version` in store_versions.ts)
|
||||
- Standardize field naming conventions
|
||||
- Move sponsorships/stripe Stripe button IDs out of session store and into config
|
||||
- Keep `ae_stores.ts` and `ae_events_stores.ts` as barrel re-exports for backwards compatibility
|
||||
Related: `src/lib/stores/store_versions.ts` is the new home for version constants.
|
||||
|
||||
### [Launcher] Active features (identified 2026-03-06)
|
||||
|
||||
- [x] **Font size cycler (Launcher sidebar):** Font size cycler and light/dark toggle added to new `menu_launcher_controls.svelte` component; wired into `launcher_menu.svelte`. Visibility toggles (All Files / All Sessions) moved to same component and restyled to `preset-tonal-tertiary`. (2026-03-11)
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// store_versions MUST be first import — its side-effect wipes stale localStorage
|
||||
// before svelte-persisted-store hydrates from it.
|
||||
import { AE_EVENTS_LOC_VERSION } from '$lib/stores/store_versions';
|
||||
|
||||
import { persisted } from 'svelte-persisted-store';
|
||||
import { writable } from 'svelte/store';
|
||||
import type { Writable } from 'svelte/store';
|
||||
@@ -12,6 +16,7 @@ const ver_idb = '2025-10-16_2139';
|
||||
// Longer-term app data. This should be stored to *local* storage.
|
||||
// Updated 2024-03-06
|
||||
const events_local_data_struct: key_val = {
|
||||
__version: AE_EVENTS_LOC_VERSION, // Schema version gate — see store_versions.ts
|
||||
ver: ver,
|
||||
ver_idb: ver_idb,
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// store_versions MUST be first import — its side-effect wipes stale localStorage
|
||||
// before svelte-persisted-store hydrates from it.
|
||||
import { AE_LOC_VERSION } from '$lib/stores/store_versions';
|
||||
|
||||
import { persisted } from 'svelte-persisted-store';
|
||||
|
||||
import { readable, writable } from 'svelte/store';
|
||||
@@ -62,6 +66,7 @@ const ver_idb = '2025-05-01_1445'; // Not currently used
|
||||
|
||||
// *** BEGIN *** Longer-term app data. This should be stored to local storage.
|
||||
const ae_app_local_data_defaults: key_val = {
|
||||
__version: AE_LOC_VERSION, // Schema version gate — see store_versions.ts
|
||||
last_page_reload: null,
|
||||
// last_idb_reload: null,
|
||||
// last_cache_refresh: null, // Date.now()
|
||||
|
||||
60
src/lib/stores/store_versions.ts
Normal file
60
src/lib/stores/store_versions.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* store_versions.ts
|
||||
*
|
||||
* Single source of truth for persisted store schema versions.
|
||||
*
|
||||
* HOW IT WORKS:
|
||||
* This file is imported at the top of ae_stores.ts and ae_events_stores.ts.
|
||||
* ES modules resolve imports before running the importing module's body,
|
||||
* so the version check + localStorage wipe here runs BEFORE persisted() is
|
||||
* called — meaning stale data is cleared before svelte-persisted-store
|
||||
* can hydrate from it.
|
||||
*
|
||||
* HOW TO USE:
|
||||
* When a store schema changes in a breaking way (type change, required
|
||||
* restructure, field rename that code depends on), bump the relevant version
|
||||
* by 1. Any client with an older version will have that store silently wiped
|
||||
* on next page load. They re-initialize from the new defaults.
|
||||
*
|
||||
* WHAT COUNTS AS BREAKING:
|
||||
* - Changing a field's type (e.g. string → object, or null → required object)
|
||||
* - Renaming a field that code reads directly (not just a display label)
|
||||
* - Restructuring a nested object that breaks existing property access
|
||||
* DOES NOT require a bump:
|
||||
* - Adding a new optional field (svelte-persisted-store deep-merges defaults)
|
||||
* - Removing a field (old value is ignored, no error)
|
||||
* - Changing a default value when the stored value being stale is acceptable
|
||||
*
|
||||
* localStorage keys:
|
||||
* 'ae_loc' → AE_LOC_VERSION
|
||||
* 'ae_events_loc' → AE_EVENTS_LOC_VERSION
|
||||
*/
|
||||
|
||||
export const AE_LOC_VERSION = 1;
|
||||
export const AE_EVENTS_LOC_VERSION = 1;
|
||||
|
||||
// Version check side-effect: runs on import, before any persisted() call.
|
||||
// Guards typeof localStorage for safety (SSR environments, test runners).
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
_check_and_wipe('ae_loc', AE_LOC_VERSION);
|
||||
_check_and_wipe('ae_events_loc', AE_EVENTS_LOC_VERSION);
|
||||
}
|
||||
|
||||
function _check_and_wipe(key: string, expected_version: number): void {
|
||||
try {
|
||||
const raw = localStorage.getItem(key);
|
||||
if (!raw) return; // No stored value — nothing to wipe.
|
||||
|
||||
const parsed = JSON.parse(raw);
|
||||
if (parsed?.__version !== expected_version) {
|
||||
localStorage.removeItem(key);
|
||||
console.info(
|
||||
`[store_versions] '${key}' wiped — schema v${parsed?.__version ?? 'none'} → v${expected_version}`
|
||||
);
|
||||
}
|
||||
} catch {
|
||||
// Corrupt JSON — wipe unconditionally.
|
||||
localStorage.removeItem(key);
|
||||
console.warn(`[store_versions] '${key}' wiped — corrupt JSON in localStorage`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user