Adds check_and_clear_idb_tables() helper in core__idb_dexie.ts that clears
Dexie tables when their content version changes. Version numbers live in
IDB_CONTENT_VERSIONS (store_versions.ts); state tracked in localStorage
(ae_idb_ver__{module}__{table}) so each table clears exactly once per bump.
Wired into db_journals.ts (pilot): journal_entry at v3 clears stale
content_md_html/history_md_html data cached before the properties_to_save fix.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
138 lines
5.7 KiB
TypeScript
138 lines
5.7 KiB
TypeScript
/**
|
|
* 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 = 2; // Bumped 2026-03-30: force-clear stale site_cfg_json (novi_idaa_api_key missing bug)
|
|
export const AE_EVENTS_LOC_VERSION = 1;
|
|
export const AE_IDAA_LOC_VERSION = 1; // Added 2026-03-30: was missing, no wipe mechanism existed
|
|
export const AE_PRES_MGMT_LOC_VERSION = 1; // Added 2026-04-02: new standalone PersistedState store
|
|
export const AE_BADGES_LOC_VERSION = 1; // Added 2026-04-02: promoted from events_loc.badges
|
|
export const AE_LEADS_LOC_VERSION = 1; // Added 2026-04-03: promoted from events_loc.leads
|
|
|
|
/**
|
|
* IDB_CONTENT_VERSIONS — per-table Dexie content version tracking.
|
|
*
|
|
* NOT YET ACTIVE. Wiring task tracked in TODO__Agents.md (post June 10).
|
|
*
|
|
* HOW IT WILL WORK (when wired):
|
|
* Each db_*.ts will call a helper (core__idb_dexie.ts) on open that checks a
|
|
* lightweight `_meta` table. If the stored version for a table doesn't match
|
|
* the constant here, the table is cleared and the version record is updated.
|
|
* The SWR pattern then repopulates from the API on next access.
|
|
*
|
|
* HOW TO USE (once active):
|
|
* Bump a table's version here when properties_to_save changes in a way that
|
|
* makes existing cached records stale (e.g. adding/removing stored fields,
|
|
* changing computed field behavior). Do NOT bump for schema-only changes
|
|
* (new indexes, new tables) — those belong in db.version() Dexie migrations.
|
|
*
|
|
* IDAA NOTES:
|
|
* IDAA tables (posts, archives) are already cleared aggressively via
|
|
* indexedDB.deleteDatabase() on sign-out and on auth failure in (idaa)/+layout.svelte.
|
|
* The content version check is a complementary mechanism for deploy-time resets,
|
|
* NOT a replacement for the auth-driven wipe. When wiring, ensure IDAA tables are
|
|
* only cleared on IDB open (not mid-session), and that the _meta table itself is
|
|
* also cleared when deleteDatabase() is called.
|
|
*/
|
|
export const IDB_CONTENT_VERSIONS = {
|
|
journals: {
|
|
journal: 3,
|
|
journal_entry: 3 // 2026-05-14: removed content_md_html + history_md_html from properties_to_save
|
|
},
|
|
events: {
|
|
event: 1,
|
|
event_session: 1,
|
|
event_presenter: 1,
|
|
event_badge: 1,
|
|
event_device: 1,
|
|
event_location: 1,
|
|
event_file: 1
|
|
},
|
|
core: {
|
|
site_domain: 1,
|
|
person: 1,
|
|
user: 1
|
|
},
|
|
// IDAA modules — see IDAA NOTES above before wiring these
|
|
posts: {
|
|
post: 1,
|
|
post_comment: 1
|
|
},
|
|
archives: {
|
|
archive: 1,
|
|
archive_content: 1
|
|
}
|
|
};
|
|
|
|
// Version check side-effect: runs on import, before any persisted() call.
|
|
// Guard presence of `localStorage` and its functions for safety (SSR, Node flags).
|
|
if (
|
|
typeof localStorage !== 'undefined' &&
|
|
typeof (localStorage as any).getItem === 'function' &&
|
|
typeof (localStorage as any).removeItem === 'function'
|
|
) {
|
|
_check_and_wipe('ae_loc', AE_LOC_VERSION);
|
|
_check_and_wipe('ae_events_loc', AE_EVENTS_LOC_VERSION);
|
|
_check_and_wipe('ae_idaa_loc', AE_IDAA_LOC_VERSION);
|
|
_check_and_wipe('ae_leads_loc', AE_LEADS_LOC_VERSION);
|
|
// ae_pres_mgmt_loc uses PersistedState (runed) which stores raw JSON without a __version
|
|
// field. The _check_and_wipe mechanism requires __version in the stored data — do NOT
|
|
// add it here until pres_mgmt_loc_defaults includes __version. For now the key is new
|
|
// (no stale data exists) so no wipe is needed.
|
|
}
|
|
|
|
function _check_and_wipe(key: string, expected_version: number): void {
|
|
try {
|
|
// Defensive: ensure methods still exist at call time.
|
|
if (typeof (localStorage as any).getItem !== 'function') return;
|
|
const raw = localStorage.getItem(key);
|
|
if (!raw) return; // No stored value — nothing to wipe.
|
|
|
|
const parsed = JSON.parse(raw);
|
|
if (parsed?.__version !== expected_version) {
|
|
if (typeof (localStorage as any).removeItem === 'function') {
|
|
localStorage.removeItem(key);
|
|
}
|
|
console.info(
|
|
`[store_versions] '${key}' wiped — schema v${parsed?.__version ?? 'none'} → v${expected_version}`
|
|
);
|
|
}
|
|
} catch {
|
|
// Corrupt JSON — wipe unconditionally if possible.
|
|
if (typeof (localStorage as any).removeItem === 'function') {
|
|
localStorage.removeItem(key);
|
|
}
|
|
console.warn(
|
|
`[store_versions] '${key}' wiped — corrupt JSON in localStorage`
|
|
);
|
|
}
|
|
}
|