import type { QueryClient } from '@tanstack/react-query' import type { ApiContact } from '@/lib/api/types' import { contactApiPath } from '@/lib/contacts/contact-api-path' import type { FullContact } from '@/lib/contacts/types' function contactMatchesPath(api: ApiContact, apiPath: string): boolean { const normalizedPath = apiPath.replace(/^\/+/, '') const contactPath = api.path?.replace(/^\/+/, '') return ( contactPath === normalizedPath || api.uid === normalizedPath || contactPath?.endsWith(`/${normalizedPath}`) === true || contactPath?.endsWith(`/${normalizedPath}.vcf`) === true ) } /** Merge selection snapshot with latest React Query cache (etag, path). */ export function resolveContactForUpdate( queryClient: QueryClient, contact: FullContact, ): FullContact { const api = findApiContactInCaches(queryClient, contact) if (!api) return contact const etag = contact.etag ?? api.etag const path = contact.path ?? api.path if (etag === contact.etag && path === contact.path) return contact return { ...contact, etag, path } } export function findApiContactInCaches( queryClient: QueryClient, contact: Pick, ): ApiContact | undefined { const apiPath = contactApiPath(contact) for (const [, list] of queryClient.getQueriesData({ queryKey: ['contacts'], })) { if (!list) continue const hit = list.find( (c) => c.uid === contact.id || contactMatchesPath(c, apiPath), ) if (hit) return hit } return undefined } export function appendContactToBookCache( queryClient: QueryClient, bookId: string, contact: ApiContact, ) { if (!contact.uid && !contact.path) return queryClient.setQueryData(['contacts', bookId], (old) => { const list = old ?? [] const uid = contact.uid if (uid && list.some((item) => item.uid === uid)) return list return [...list, contact] }) } export function replaceContactInBookCaches( queryClient: QueryClient, apiPath: string, patch: Partial, ) { for (const [key, list] of queryClient.getQueriesData({ queryKey: ['contacts'], })) { if (!list) continue let changed = false const next = list.map((item) => { if (!contactMatchesPath(item, apiPath)) return item changed = true return { ...item, ...patch } }) if (changed) { queryClient.setQueryData(key, next) } } }