From 3fd6b33d6ff59b43dfe9d8148c84e1ef1cf4c295 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Wed, 22 Apr 2026 10:02:40 -0400 Subject: [PATCH] fix(events): prune stale event_file records from Dexie after list refresh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bulkPut only upserts — files deleted on the server stayed in Dexie forever, showing in the Launcher and Manage Files UI until the browser cache was cleared. After each _refresh_file_li_background call, deleted records are now pruned from Dexie. Scope-guarded so we only remove records that would have appeared in the query (e.g. hidden files are not pruned after a hidden='not_hidden' fetch). Also covers the disable (enable=false) case the same way. Co-Authored-By: Claude Sonnet 4.6 --- src/lib/ae_events/ae_events__event_file.ts | 44 ++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/lib/ae_events/ae_events__event_file.ts b/src/lib/ae_events/ae_events__event_file.ts index 93ae0ac0..164768e4 100644 --- a/src/lib/ae_events/ae_events__event_file.ts +++ b/src/lib/ae_events/ae_events__event_file.ts @@ -269,6 +269,50 @@ async function _refresh_file_li_background({ properties_to_save, log_lvl }); + + // Prune stale Dexie records that no longer exist on the server. + // WHY: bulkPut only upserts — it never removes records deleted on + // the server. Without this, deleted files remain visible in the UI + // indefinitely (the liveQuery sees them in Dexie forever). + // + // Scope guard: only delete records that WOULD have been included in + // this query. Records outside the query scope (e.g. a hidden file + // when hidden='not_hidden') are intentionally left in Dexie so + // that a later 'all' query can still find them. + // We prune on any valid API response, including an empty list — + // an empty array from the API is authoritative ("no files here"). + const returned_ids = new Set( + processed.map((f: any) => f.id).filter(Boolean) + ); + const dexie_all = await db_events.file + .where('for_id') + .equals(for_obj_id) + .toArray(); + const stale_ids = dexie_all + .filter((f) => { + if (!f.id || returned_ids.has(f.id)) return false; + // Would this record have appeared in our query? + const is_enabled = !!f.enable; + const is_hidden = !!f.hide; + const within_enabled_scope = + enabled === 'all' || + (enabled === 'enabled' && is_enabled) || + (enabled === 'not_enabled' && !is_enabled); + const within_hidden_scope = + hidden === 'all' || + (hidden === 'not_hidden' && !is_hidden) || + (hidden === 'hidden' && is_hidden); + return within_enabled_scope && within_hidden_scope; + }) + .map((f) => f.id as string); + if (stale_ids.length > 0) { + if (log_lvl) + console.log( + `🗑️ [DEBUG] Pruning ${stale_ids.length} stale file records from Dexie`, + stale_ids + ); + await db_events.file.bulkDelete(stale_ids); + } } return processed; }