From 714fb510abbda451d378bc61899b2ce7732b17c6 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sun, 18 Jan 2026 18:20:53 +0000 Subject: [PATCH] Validate sync keys and reconcile local data --- src/store/slices/syncSlice.ts | 48 +++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/src/store/slices/syncSlice.ts b/src/store/slices/syncSlice.ts index 046bef8..7baaa21 100644 --- a/src/store/slices/syncSlice.ts +++ b/src/store/slices/syncSlice.ts @@ -68,15 +68,47 @@ export const syncFromFlaskBulk = createAsyncThunk( async (_, { rejectWithValue }) => { try { const data = await fetchAllFromFlask() - + const allowedStoreNames = new Set(['files', 'models', 'components', 'workflows']) + const serverIdsByStore = { + files: new Set(), + models: new Set(), + components: new Set(), + workflows: new Set(), + } + for (const [key, value] of Object.entries(data)) { - const [storeName, id] = key.split(':') - - if (storeName === 'files' || - storeName === 'models' || - storeName === 'components' || - storeName === 'workflows') { - await db.put(storeName as any, value) + if (typeof key !== 'string') { + continue + } + + const parts = key.split(':') + if (parts.length !== 2) { + continue + } + + const [storeName, id] = parts + if (!storeName || !id) { + continue + } + + if (!allowedStoreNames.has(storeName)) { + continue + } + + serverIdsByStore[storeName as keyof typeof serverIdsByStore].add(id) + await db.put(storeName as any, value) + } + + // Explicit merge strategy: server is source of truth; delete local records missing from server response. + const storeNames = Array.from(allowedStoreNames) + for (const storeName of storeNames) { + const localRecords = await db.getAll(storeName as any) + for (const record of localRecords) { + const recordId = record?.id + const recordIdString = recordId == null ? '' : String(recordId) + if (!serverIdsByStore[storeName as keyof typeof serverIdsByStore].has(recordIdString)) { + await db.delete(storeName as any, recordId) + } } }