{"version":3,"file":"useDataSync.mjs","sources":["../../../../src/lib/data/hooks/useDataSync.ts"],"sourcesContent":["/**\n * @file useDataSync Hook\n * @description React hook for multi-source data synchronization with\n * conflict resolution, optimistic updates, and offline support.\n *\n * Features:\n * - Multi-source sync (API, localStorage, memory)\n * - Conflict resolution with customizable strategies\n * - Optimistic updates with automatic rollback\n * - Offline queue management\n * - Real-time sync status\n *\n * @example\n * ```typescript\n * import { useDataSync } from '@/lib/data';\n *\n * function UserList() {\n *   const {\n *     data,\n *     isLoading,\n *     isSyncing,\n *     sync,\n *     update,\n *     conflicts,\n *     resolveConflict,\n *   } = useDataSync({\n *     entityType: 'users',\n *     sources: [apiSource, localStorageSource],\n *     conflictStrategy: 'latest-wins',\n *   });\n *\n *   return <ul>{data.map(user => <li key={user.id}>{user.name}</li>)}</ul>;\n * }\n * ```\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useLatestRef } from '../../hooks/shared/useLatestRef';\nimport type { SyncConflict, SyncEngine, SyncEvent, SyncOptions, SyncResult, SyncStatus, } from '../sync/sync-engine';\nimport type { ConflictResolutionResult, ConflictStrategy } from '../sync/conflict-resolver';\nimport type { Entity } from '../normalization/normalizer';\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * Sync state for an entity type\n */\nexport interface SyncState<T extends Entity> {\n  /** Current data */\n  data: T[];\n  /** Sync status */\n  status: SyncStatus;\n  /** Is initial load */\n  isLoading: boolean;\n  /** Is syncing */\n  isSyncing: boolean;\n  /** Is offline */\n  isOffline: boolean;\n  /** Last sync timestamp */\n  lastSyncAt: number | null;\n  /** Pending changes count */\n  pendingChanges: number;\n  /** Active conflicts */\n  conflicts: SyncConflict[];\n  /** Last error */\n  error: Error | null;\n}\n\n/**\n * Sync hook options\n */\nexport interface UseDataSyncOptions<T extends Entity> {\n  /** Sync engine instance */\n  engine: SyncEngine;\n  /** Entity type to sync */\n  entityType: string;\n  /** Initial data */\n  initialData?: T[];\n  /** Auto sync on mount */\n  autoSync?: boolean;\n  /** Sync interval in ms (0 = manual only) */\n  syncInterval?: number;\n  /** Conflict resolution strategy */\n  conflictStrategy?: ConflictStrategy;\n  /** Custom conflict resolver */\n  onConflict?: (conflict: SyncConflict) => Promise<ConflictResolutionResult<unknown>>;\n  /** Callback on sync success */\n  onSyncSuccess?: (result: SyncResult) => void;\n  /** Callback on sync error */\n  onSyncError?: (error: Error) => void;\n  /** Callback on data change */\n  onDataChange?: (data: T[]) => void;\n  /** Enable optimistic updates */\n  optimisticUpdates?: boolean;\n  /** Filter function for data */\n  filter?: (item: T) => boolean;\n  /** Sort function for data */\n  sort?: (a: T, b: T) => number;\n}\n\n/**\n * Sync hook return type\n */\nexport interface UseDataSyncReturn<T extends Entity> {\n  /** Current state */\n  state: SyncState<T>;\n  /** Current data */\n  data: T[];\n  /** Is loading */\n  isLoading: boolean;\n  /** Is syncing */\n  isSyncing: boolean;\n  /** Is offline */\n  isOffline: boolean;\n  /** Has conflicts */\n  hasConflicts: boolean;\n  /** Active conflicts */\n  conflicts: SyncConflict[];\n  /** Last error */\n  error: Error | null;\n  /** Trigger sync */\n  sync: (options?: SyncOptions) => Promise<SyncResult>;\n  /** Create entity */\n  create: (data: Omit<T, 'id'>) => Promise<T>;\n  /** Update entity */\n  update: (id: string, data: Partial<T>) => Promise<T>;\n  /** Delete entity */\n  remove: (id: string) => Promise<void>;\n  /** Resolve conflict */\n  resolveConflict: (\n    conflictId: string,\n    resolution: 'local' | 'remote' | 'merge',\n    mergedData?: T\n  ) => Promise<void>;\n  /** Resolve all conflicts */\n  resolveAllConflicts: (strategy: 'local' | 'remote') => Promise<void>;\n  /** Retry failed syncs */\n  retryFailed: () => Promise<void>;\n  /** Clear offline queue */\n  clearOfflineQueue: () => void;\n  /** Get entity by ID */\n  getById: (id: string) => T | undefined;\n  /** Refresh data */\n  refresh: () => Promise<void>;\n}\n\n// =============================================================================\n// HOOK IMPLEMENTATION\n// =============================================================================\n\n/**\n * Hook for data synchronization\n *\n * @param options - Sync options\n * @returns Sync state and methods\n */\nexport function useDataSync<T extends Entity>(\n  options: UseDataSyncOptions<T>\n): UseDataSyncReturn<T> {\n  const {\n    engine,\n    entityType,\n    initialData = [],\n    autoSync = true,\n    syncInterval = 0,\n    onSyncSuccess,\n    onSyncError,\n    onDataChange,\n    optimisticUpdates = true,\n    filter,\n    sort,\n  } = options;\n\n  // State\n  const [state, setState] = useState<SyncState<T>>({\n    data: initialData,\n    status: 'synced',\n    isLoading: autoSync,\n    isSyncing: false,\n    isOffline: !navigator.onLine,\n    lastSyncAt: null,\n    pendingChanges: 0,\n    conflicts: [],\n    error: null,\n  });\n\n  // Refs\n  const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n  const mountedRef = useRef(true);\n  const engineRef = useRef(engine);\n  engineRef.current = engine;\n\n  // Processed data\n  const processedData = useMemo(() => {\n    let result = [...state.data];\n\n    if (filter) {\n      result = result.filter(filter);\n    }\n\n    if (sort) {\n      result.sort(sort);\n    }\n\n    return result;\n  }, [state.data, filter, sort]);\n\n  // Handle sync events\n  useEffect(() => {\n    const unsubscribe = engine.subscribe((event: SyncEvent) => {\n      if (!mountedRef.current) return;\n\n      switch (event.type) {\n        case 'sync:start':\n          setState((prev) => ({\n            ...prev,\n            isSyncing: true,\n            status: 'syncing',\n          }));\n          break;\n\n        case 'sync:complete':\n          setState((prev) => ({\n            ...prev,\n            isSyncing: false,\n            isLoading: false,\n            status: 'synced',\n            lastSyncAt: Date.now(),\n            error: null,\n          }));\n          break;\n\n        case 'sync:error':\n          setState((prev) => ({\n            ...prev,\n            isSyncing: false,\n            isLoading: false,\n            status: 'error',\n            error: event.data as Error,\n          }));\n          break;\n\n        case 'sync:conflict':\n          setState((prev) => ({\n            ...prev,\n            conflicts: [...prev.conflicts, event.data as SyncConflict<T>],\n          }));\n          break;\n\n        case 'offline-queue-change':\n          setState((prev) => ({\n            ...prev,\n            pendingChanges: (event.data as { count: number }).count,\n          }));\n          break;\n      }\n    });\n\n    return () => {\n      unsubscribe();\n    };\n  }, [engine]);\n\n  // Sync function - defined before effects that depend on it\n  const sync = useCallback(\n    async (syncOptions?: SyncOptions): Promise<SyncResult> => {\n      setState((prev) => ({\n        ...prev,\n        isSyncing: true,\n        status: 'syncing',\n      }));\n\n      try {\n        const result = await engineRef.current.syncAll(entityType, syncOptions);\n\n        if (mountedRef.current) {\n          setState((prev) => ({\n            ...prev,\n            data: result.data as T[],\n            isSyncing: false,\n            isLoading: false,\n            status: (result.conflicts?.length ?? 0) > 0 ? 'conflict' : 'synced',\n            lastSyncAt: Date.now(),\n            conflicts: result.conflicts ?? [],\n            error: null,\n          }));\n\n          onDataChange?.(result.data as T[]);\n          onSyncSuccess?.(result);\n        }\n\n        return result;\n      } catch (error) {\n        const err = error instanceof Error ? error : new Error(String(error));\n\n        if (mountedRef.current) {\n          setState((prev) => ({\n            ...prev,\n            isSyncing: false,\n            isLoading: false,\n            status: 'error',\n            error: err,\n          }));\n\n          onSyncError?.(err);\n        }\n\n        throw err;\n      }\n    },\n    [entityType, onDataChange, onSyncSuccess, onSyncError]\n  );\n\n  // Use useLatestRef to avoid stale closures when sync is called from effects\n  // This ensures the effect always calls the latest sync function without\n  // causing effect re-runs when sync's dependencies change\n  const syncRef = useLatestRef(sync);\n\n  // Handle online/offline status\n  // Uses syncRef to avoid stale closure and prevent effect re-runs\n  useEffect(() => {\n    const handleOnline = (): void => {\n      setState((prev) => ({ ...prev, isOffline: false }));\n      // Trigger sync when coming back online - use ref to get latest sync function\n      syncRef.current().catch(console.error);\n    };\n\n    const handleOffline = (): void => {\n      setState((prev) => ({ ...prev, isOffline: true }));\n    };\n\n    window.addEventListener('online', handleOnline);\n    window.addEventListener('offline', handleOffline);\n\n    return () => {\n      window.removeEventListener('online', handleOnline);\n      window.removeEventListener('offline', handleOffline);\n    };\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []); // Empty deps - syncRef.current always has latest sync function\n\n  // Create entity\n  const create = useCallback(\n    async (data: Omit<T, 'id'>): Promise<T> => {\n      const tempId = `temp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n      const newEntity = { ...data, id: tempId } as T;\n\n      // Optimistic update\n      if (optimisticUpdates) {\n        setState((prev) => ({\n          ...prev,\n          data: [...prev.data, newEntity],\n          pendingChanges: prev.pendingChanges + 1,\n        }));\n      }\n\n      try {\n        const created = await engineRef.current.create(entityType, data as Partial<T>);\n\n        if (mountedRef.current) {\n          setState((prev) => ({\n            ...prev,\n            data: prev.data.map((item) => (item.id === tempId ? created : item)),\n            pendingChanges: Math.max(0, prev.pendingChanges - 1),\n          }));\n        }\n\n        return created;\n      } catch (error) {\n        // Rollback on error\n        if (optimisticUpdates && mountedRef.current) {\n          setState((prev) => ({\n            ...prev,\n            data: prev.data.filter((item) => item.id !== tempId),\n            pendingChanges: Math.max(0, prev.pendingChanges - 1),\n            error: error instanceof Error ? error : new Error(String(error)),\n          }));\n        }\n        throw error;\n      }\n    },\n    [entityType, optimisticUpdates]\n  );\n\n  // Update entity\n  const update = useCallback(\n    async (id: string, data: Partial<T>): Promise<T> => {\n      const originalItem = state.data.find((item) => item.id === id);\n\n      // Optimistic update\n      if (optimisticUpdates && originalItem) {\n        setState((prev) => ({\n          ...prev,\n          data: prev.data.map((item) => (item.id === id ? { ...item, ...data } : item)),\n          pendingChanges: prev.pendingChanges + 1,\n        }));\n      }\n\n      try {\n        const updated = await engineRef.current.update(entityType, id, data);\n\n        if (mountedRef.current) {\n          setState((prev) => ({\n            ...prev,\n            data: prev.data.map((item) => (item.id === id ? updated : item)),\n            pendingChanges: Math.max(0, prev.pendingChanges - 1),\n          }));\n        }\n\n        return updated;\n      } catch (error) {\n        // Rollback on error\n        if (optimisticUpdates && originalItem && mountedRef.current) {\n          setState((prev) => ({\n            ...prev,\n            data: prev.data.map((item) => (item.id === id ? originalItem : item)),\n            pendingChanges: Math.max(0, prev.pendingChanges - 1),\n            error: error instanceof Error ? error : new Error(String(error)),\n          }));\n        }\n        throw error;\n      }\n    },\n    [entityType, optimisticUpdates, state.data]\n  );\n\n  // Remove entity\n  const remove = useCallback(\n    async (id: string): Promise<void> => {\n      const originalItem = state.data.find((item) => item.id === id);\n\n      // Optimistic update\n      if (optimisticUpdates) {\n        setState((prev) => ({\n          ...prev,\n          data: prev.data.filter((item) => item.id !== id),\n          pendingChanges: prev.pendingChanges + 1,\n        }));\n      }\n\n      try {\n        await engineRef.current.delete(entityType, id);\n\n        if (mountedRef.current) {\n          setState((prev) => ({\n            ...prev,\n            pendingChanges: Math.max(0, prev.pendingChanges - 1),\n          }));\n        }\n      } catch (error) {\n        // Rollback on error\n        if (optimisticUpdates && originalItem && mountedRef.current) {\n          setState((prev) => ({\n            ...prev,\n            data: [...prev.data, originalItem],\n            pendingChanges: Math.max(0, prev.pendingChanges - 1),\n            error: error instanceof Error ? error : new Error(String(error)),\n          }));\n        }\n        throw error;\n      }\n    },\n    [entityType, optimisticUpdates, state.data]\n  );\n\n  // Resolve conflict\n  const resolveConflict = useCallback(\n    async (\n      conflictId: string,\n      resolution: 'local' | 'remote' | 'merge',\n      mergedData?: T\n    ): Promise<void> => {\n      const conflict = state.conflicts.find((c) => c.id === conflictId);\n      if (!conflict) return;\n\n      let resolvedData: T;\n\n      switch (resolution) {\n        case 'local':\n          resolvedData = conflict.localData as T;\n          break;\n        case 'remote':\n          resolvedData = conflict.remoteData as T;\n          break;\n        case 'merge':\n          if (!mergedData) {\n            throw new Error('Merged data required for merge resolution');\n          }\n          resolvedData = mergedData;\n          break;\n      }\n\n      await engineRef.current.resolveConflict(conflictId, resolvedData);\n\n      if (mountedRef.current) {\n        setState((prev) => ({\n          ...prev,\n          data: prev.data.map((item) => (item.id === conflict.entityId ? resolvedData : item)),\n          conflicts: prev.conflicts.filter((c) => c.id !== conflictId),\n        }));\n      }\n    },\n    [state.conflicts]\n  );\n\n  // Resolve all conflicts\n  const resolveAllConflicts = useCallback(\n    async (strategy: 'local' | 'remote'): Promise<void> => {\n      for (const conflict of state.conflicts) {\n        await resolveConflict(conflict.id, strategy);\n      }\n    },\n    [state.conflicts, resolveConflict]\n  );\n\n  // Retry failed syncs\n  const retryFailed = useCallback(async (): Promise<void> => {\n    await engineRef.current.retryFailed();\n  }, []);\n\n  // Clear offline queue\n  const clearOfflineQueue = useCallback((): void => {\n    engineRef.current.clearOfflineQueue();\n    setState((prev) => ({ ...prev, pendingChanges: 0 }));\n  }, []);\n\n  // Get entity by ID\n  const getById = useCallback(\n    (id: string): T | undefined => {\n      return state.data.find((item) => item.id === id);\n    },\n    [state.data]\n  );\n\n  // Refresh data\n  const refresh = useCallback(async (): Promise<void> => {\n    await sync({ force: true });\n  }, [sync]);\n\n  // Refs for state values used in interval to avoid interval recreation\n  const stateRef = useLatestRef(state);\n\n  // Auto sync on mount\n  useEffect(() => {\n    if (autoSync) {\n      // Use syncRef to get the latest sync function\n      syncRef.current().catch(console.error);\n    }\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [autoSync]); // syncRef always has latest sync, no need to include in deps\n\n  // Sync interval\n  // Uses refs for sync and state to avoid interval recreation on every state change\n  useEffect(() => {\n    if (syncInterval > 0) {\n      intervalRef.current = setInterval(() => {\n        // Use refs to get latest values without causing effect re-runs\n        const currentState = stateRef.current;\n        if (!currentState.isOffline && !currentState.isSyncing) {\n          syncRef.current().catch(console.error);\n        }\n      }, syncInterval);\n    }\n\n    return () => {\n      if (intervalRef.current) {\n        clearInterval(intervalRef.current);\n      }\n    };\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [syncInterval]); // Only re-create interval when syncInterval changes\n\n  // Cleanup\n  useEffect(() => {\n    mountedRef.current = true;\n    return () => {\n      mountedRef.current = false;\n    };\n  }, []);\n\n  return {\n    state,\n    data: processedData,\n    isLoading: state.isLoading,\n    isSyncing: state.isSyncing,\n    isOffline: state.isOffline,\n    hasConflicts: state.conflicts.length > 0,\n    conflicts: state.conflicts,\n    error: state.error,\n    sync,\n    create,\n    update,\n    remove,\n    resolveConflict,\n    resolveAllConflicts,\n    retryFailed,\n    clearOfflineQueue,\n    getById,\n    refresh,\n  };\n}\n\n// =============================================================================\n// SPECIALIZED HOOKS\n// =============================================================================\n\n/**\n * Hook for sync status only\n *\n * @param engine - Sync engine instance\n * @returns Sync status\n */\nexport function useSyncStatus(engine: SyncEngine): {\n  status: SyncStatus;\n  isOnline: boolean;\n  pendingChanges: number;\n  lastSyncAt: number | null;\n} {\n  const [status, setStatus] = useState<SyncStatus>('synced');\n  const [pendingChanges, setPendingChanges] = useState(0);\n  const [lastSyncAt, setLastSyncAt] = useState<number | null>(null);\n  const [isOnline, setIsOnline] = useState(navigator.onLine);\n\n  useEffect(() => {\n    const unsubscribe = engine.subscribe((event: SyncEvent) => {\n      switch (event.type) {\n        case 'sync:start':\n          setStatus('syncing');\n          break;\n        case 'sync:complete':\n          setStatus('synced');\n          setLastSyncAt(Date.now());\n          break;\n        case 'sync:error':\n          setStatus('error');\n          break;\n        case 'offline-queue-change':\n          setPendingChanges((event.data as { count: number }).count);\n          break;\n      }\n    });\n\n    const handleOnline = (): void => setIsOnline(true);\n    const handleOffline = (): void => setIsOnline(false);\n\n    window.addEventListener('online', handleOnline);\n    window.addEventListener('offline', handleOffline);\n\n    return () => {\n      unsubscribe();\n      window.removeEventListener('online', handleOnline);\n      window.removeEventListener('offline', handleOffline);\n    };\n  }, [engine]);\n\n  return { status, isOnline, pendingChanges, lastSyncAt };\n}\n\n/**\n * Hook for conflict management\n *\n * @param engine - Sync engine instance\n * @returns Conflict management methods\n */\nexport function useSyncConflicts(engine: SyncEngine): {\n  conflicts: SyncConflict[];\n  hasConflicts: boolean;\n  resolveConflict: (id: string, data: Entity) => Promise<void>;\n  resolveAllLocal: () => Promise<void>;\n  resolveAllRemote: () => Promise<void>;\n} {\n  const [conflicts, setConflicts] = useState<SyncConflict[]>([]);\n\n  useEffect(() => {\n\n\n    return engine.subscribe((event: SyncEvent) => {\n      if (event.type === 'sync:conflict') {\n        setConflicts((prev) => [...prev, event.data as SyncConflict]);\n      }\n      if (event.type === 'conflict-resolved') {\n        const { id } = event.data as { id: string };\n        setConflicts((prev) => prev.filter((c) => c.id !== id));\n      }\n    });\n  }, [engine]);\n\n  const resolveConflict = useCallback(\n    async (id: string, data: Entity) => {\n      await engine.resolveConflict(id, data);\n      setConflicts((prev) => prev.filter((c) => c.id !== id));\n    },\n    [engine]\n  );\n\n  const resolveAllLocal = useCallback(async () => {\n    for (const conflict of conflicts) {\n      await resolveConflict(conflict.id, conflict.localData as Entity);\n    }\n  }, [conflicts, resolveConflict]);\n\n  const resolveAllRemote = useCallback(async () => {\n    for (const conflict of conflicts) {\n      await resolveConflict(conflict.id, conflict.remoteData as Entity);\n    }\n  }, [conflicts, resolveConflict]);\n\n  return {\n    conflicts,\n    hasConflicts: conflicts.length > 0,\n    resolveConflict,\n    resolveAllLocal,\n    resolveAllRemote,\n  };\n}\n"],"names":["useDataSync","options","engine","entityType","initialData","autoSync","syncInterval","onSyncSuccess","onSyncError","onDataChange","optimisticUpdates","filter","sort","state","setState","useState","intervalRef","useRef","mountedRef","engineRef","processedData","useMemo","result","useEffect","unsubscribe","event","prev","sync","useCallback","syncOptions","error","err","syncRef","useLatestRef","handleOnline","handleOffline","create","data","tempId","newEntity","created","item","update","id","originalItem","updated","remove","resolveConflict","conflictId","resolution","mergedData","conflict","c","resolvedData","resolveAllConflicts","strategy","retryFailed","clearOfflineQueue","getById","refresh","stateRef","currentState","useSyncStatus","status","setStatus","pendingChanges","setPendingChanges","lastSyncAt","setLastSyncAt","isOnline","setIsOnline","useSyncConflicts","conflicts","setConflicts","resolveAllLocal","resolveAllRemote"],"mappings":"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"}