@pol-studios/powersync 1.0.7 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +933 -0
  2. package/dist/CacheSettingsManager-uz-kbnRH.d.ts +461 -0
  3. package/dist/attachments/index.d.ts +709 -6
  4. package/dist/attachments/index.js +133 -5
  5. package/dist/chunk-24RDMMCL.js +44 -0
  6. package/dist/chunk-24RDMMCL.js.map +1 -0
  7. package/dist/chunk-4TXTAEF2.js +2060 -0
  8. package/dist/chunk-4TXTAEF2.js.map +1 -0
  9. package/dist/chunk-63PXSPIN.js +358 -0
  10. package/dist/chunk-63PXSPIN.js.map +1 -0
  11. package/dist/chunk-654ERHA7.js +1 -0
  12. package/dist/{chunk-BREGB4WL.js → chunk-BRXQNASY.js} +287 -335
  13. package/dist/chunk-BRXQNASY.js.map +1 -0
  14. package/dist/{chunk-DHYUBVP7.js → chunk-CAB26E6F.js} +20 -9
  15. package/dist/chunk-CAB26E6F.js.map +1 -0
  16. package/dist/{chunk-H772V6XQ.js → chunk-CUCAYK7Z.js} +7 -43
  17. package/dist/chunk-CUCAYK7Z.js.map +1 -0
  18. package/dist/{chunk-4C3RY5SU.js → chunk-HWSNV45P.js} +76 -1
  19. package/dist/chunk-HWSNV45P.js.map +1 -0
  20. package/dist/{chunk-HFOFLW5F.js → chunk-KN2IZERF.js} +139 -6
  21. package/dist/chunk-KN2IZERF.js.map +1 -0
  22. package/dist/{chunk-UEYRTLKE.js → chunk-P4HZA6ZT.js} +20 -9
  23. package/dist/chunk-P4HZA6ZT.js.map +1 -0
  24. package/dist/chunk-T4AO7JIG.js +1 -0
  25. package/dist/{chunk-XQAJM2MW.js → chunk-VACPAAQZ.js} +33 -2
  26. package/dist/{chunk-XQAJM2MW.js.map → chunk-VACPAAQZ.js.map} +1 -1
  27. package/dist/{chunk-53WH2JJV.js → chunk-WN5ZJ3E2.js} +5 -8
  28. package/dist/chunk-WN5ZJ3E2.js.map +1 -0
  29. package/dist/chunk-XAEII4ZX.js +456 -0
  30. package/dist/chunk-XAEII4ZX.js.map +1 -0
  31. package/dist/chunk-XOY2CJ67.js +289 -0
  32. package/dist/chunk-XOY2CJ67.js.map +1 -0
  33. package/dist/chunk-YHTZ7VMV.js +1 -0
  34. package/dist/{chunk-MKD2VCX3.js → chunk-Z6VOBGTU.js} +8 -8
  35. package/dist/chunk-Z6VOBGTU.js.map +1 -0
  36. package/dist/chunk-ZM4ENYMF.js +230 -0
  37. package/dist/chunk-ZM4ENYMF.js.map +1 -0
  38. package/dist/connector/index.d.ts +56 -3
  39. package/dist/connector/index.js +8 -5
  40. package/dist/core/index.d.ts +12 -1
  41. package/dist/core/index.js +3 -2
  42. package/dist/error/index.js +0 -1
  43. package/dist/index.d.ts +12 -10
  44. package/dist/index.js +191 -29
  45. package/dist/index.native.d.ts +11 -9
  46. package/dist/index.native.js +191 -29
  47. package/dist/index.web.d.ts +11 -9
  48. package/dist/index.web.js +191 -29
  49. package/dist/maintenance/index.js +0 -1
  50. package/dist/platform/index.js +0 -2
  51. package/dist/platform/index.js.map +1 -1
  52. package/dist/platform/index.native.js +1 -2
  53. package/dist/platform/index.web.js +0 -1
  54. package/dist/pol-attachment-queue-BVAIueoP.d.ts +817 -0
  55. package/dist/provider/index.d.ts +38 -34
  56. package/dist/provider/index.js +11 -12
  57. package/dist/react/index.d.ts +372 -0
  58. package/dist/react/index.js +25 -0
  59. package/dist/storage/index.d.ts +3 -3
  60. package/dist/storage/index.js +22 -8
  61. package/dist/storage/index.native.d.ts +3 -3
  62. package/dist/storage/index.native.js +21 -7
  63. package/dist/storage/index.web.d.ts +3 -3
  64. package/dist/storage/index.web.js +21 -7
  65. package/dist/storage/upload/index.d.ts +7 -8
  66. package/dist/storage/upload/index.js +3 -3
  67. package/dist/storage/upload/index.native.d.ts +7 -8
  68. package/dist/storage/upload/index.native.js +4 -3
  69. package/dist/storage/upload/index.web.d.ts +1 -4
  70. package/dist/storage/upload/index.web.js +3 -3
  71. package/dist/supabase-connector-T9vHq_3i.d.ts +202 -0
  72. package/dist/sync/index.js +3 -3
  73. package/dist/{supabase-connector-qLm-WHkM.d.ts → types-B212hgfA.d.ts} +48 -170
  74. package/dist/{types-BVacP54t.d.ts → types-CyvBaAl8.d.ts} +12 -4
  75. package/dist/types-D0WcHrq6.d.ts +234 -0
  76. package/package.json +18 -4
  77. package/dist/CacheSettingsManager-1exbOC6S.d.ts +0 -261
  78. package/dist/chunk-4C3RY5SU.js.map +0 -1
  79. package/dist/chunk-53WH2JJV.js.map +0 -1
  80. package/dist/chunk-BREGB4WL.js.map +0 -1
  81. package/dist/chunk-DGUM43GV.js +0 -11
  82. package/dist/chunk-DHYUBVP7.js.map +0 -1
  83. package/dist/chunk-GKF7TOMT.js +0 -1
  84. package/dist/chunk-H772V6XQ.js.map +0 -1
  85. package/dist/chunk-HFOFLW5F.js.map +0 -1
  86. package/dist/chunk-KGSFAE5B.js +0 -1
  87. package/dist/chunk-LNL64IJZ.js +0 -1
  88. package/dist/chunk-MKD2VCX3.js.map +0 -1
  89. package/dist/chunk-UEYRTLKE.js.map +0 -1
  90. package/dist/chunk-WQ5MPAVC.js +0 -449
  91. package/dist/chunk-WQ5MPAVC.js.map +0 -1
  92. package/dist/chunk-ZEOKPWUC.js +0 -1165
  93. package/dist/chunk-ZEOKPWUC.js.map +0 -1
  94. package/dist/pol-attachment-queue-C7YNXXhK.d.ts +0 -676
  95. package/dist/types-Bgvx7-E8.d.ts +0 -187
  96. /package/dist/{chunk-DGUM43GV.js.map → chunk-654ERHA7.js.map} +0 -0
  97. /package/dist/{chunk-GKF7TOMT.js.map → chunk-T4AO7JIG.js.map} +0 -0
  98. /package/dist/{chunk-KGSFAE5B.js.map → chunk-YHTZ7VMV.js.map} +0 -0
  99. /package/dist/{chunk-LNL64IJZ.js.map → react/index.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/provider/PowerSyncProvider.tsx","../src/conflicts/conflict-bus.ts","../src/provider/OfflineDataProvider.tsx","../src/provider/ProviderBridge.tsx"],"sourcesContent":["/**\n * PowerSyncProvider Component for @pol-studios/powersync\n *\n * Main provider component that initializes and manages the PowerSync database,\n * connector, attachment queue, and all monitoring services.\n */\n\nimport React, { useEffect, useState, useRef, useMemo, useCallback } from 'react';\nimport type { Session } from '@supabase/supabase-js';\nimport type { AbstractPowerSyncDatabase, SyncStatus, ConnectionHealth, SyncMetrics, CrudEntry, FailedTransaction, CompletedTransaction, SyncMode } from '../core/types';\nimport { SupabaseConnector } from '../connector/supabase-connector';\nimport { extractEntityIds, extractTableNames, createSyncError } from '../core/errors';\nimport { PolAttachmentQueue, createPolAttachmentQueue } from '../attachments/pol-attachment-queue';\nimport { SyncStatusTracker } from '../sync/status-tracker';\nimport { MetricsCollector } from '../sync/metrics-collector';\nimport { HealthMonitor } from '../sync/health-monitor';\nimport { ConflictBus } from '../conflicts/conflict-bus';\nimport { PowerSyncContext, SyncStatusContext, ConnectionHealthContext, SyncMetricsContext, AttachmentQueueContext, ConnectionStatusContext, SyncActivityContext, PendingMutationsContext, FailedTransactionsContext, CompletedTransactionsContext, SyncModeContext } from './context';\nimport type { PowerSyncProviderProps, PowerSyncContextValue, SyncStatusContextValue, ConnectionHealthContextValue, SyncMetricsContextValue, ConnectionStatusContextValue, SyncActivityContextValue, PendingMutationsContextValue, FailedTransactionsContextValue, CompletedTransactionsContextValue, SyncModeContextValue } from './types';\nimport { DEFAULT_SYNC_STATUS, DEFAULT_CONNECTION_HEALTH, DEFAULT_SYNC_METRICS } from './types';\n\n/**\n * PowerSyncProvider initializes and manages the PowerSync database and related services.\n *\n * Features:\n * - Initializes PowerSync database using platform adapter\n * - Creates and manages SupabaseConnector\n * - Connects/disconnects based on auth state\n * - Tracks sync status and connection health\n * - Optionally initializes AttachmentQueue\n * - Provides all contexts to children\n * - Handles cleanup on unmount\n *\n * @example\n * ```tsx\n * import { PowerSyncProvider, usePowerSync, useSyncStatus } from '@pol-studios/powersync';\n *\n * function App() {\n * return (\n * <PowerSyncProvider\n * config={{\n * platform: createNativePlatformAdapter(logger),\n * schema: AppSchema,\n * powerSyncUrl: 'https://your-powersync.com',\n * supabaseClient: supabase,\n * }}\n * onReady={() => console.log('PowerSync ready!')}\n * onError={(err) => console.error('PowerSync error:', err)}\n * >\n * <MainApp />\n * </PowerSyncProvider>\n * );\n * }\n * ```\n */\nexport function PowerSyncProvider<TSchema = unknown>({\n config,\n children,\n onReady,\n onError,\n onSyncStatusChange\n}: PowerSyncProviderProps<TSchema>): React.ReactElement {\n const {\n platform,\n schema,\n powerSyncUrl,\n supabaseClient,\n dbFilename = 'powersync.db',\n connector: connectorConfig,\n attachments: attachmentConfig,\n sync: syncConfig\n } = config;\n const logger = platform.logger;\n\n // Merge sync config with defaults\n const mergedSyncConfig = {\n autoConnect: syncConfig?.autoConnect ?? true,\n syncInterval: syncConfig?.syncInterval ?? 0,\n enableHealthMonitoring: syncConfig?.enableHealthMonitoring ?? true,\n enableMetrics: syncConfig?.enableMetrics ?? true\n };\n\n // ─── State ─────────────────────────────────────────────────────────────────\n\n const [db, setDb] = useState<AbstractPowerSyncDatabase | null>(null);\n const [connector, setConnector] = useState<SupabaseConnector | null>(null);\n const [attachmentQueue, setAttachmentQueue] = useState<PolAttachmentQueue | null>(null);\n const [isReady, setIsReady] = useState(false);\n const [isInitializing, setIsInitializing] = useState(true);\n // Track whether the attachment queue has finished initializing\n // True if: (1) attachments not configured, or (2) queue successfully initialized\n const [attachmentQueueReady, setAttachmentQueueReady] = useState(!attachmentConfig);\n const [error, setError] = useState<Error | null>(null);\n const [session, setSession] = useState<Session | null>(null);\n\n // Conflict bus - created once and stable for the lifetime of the provider\n const conflictBusRef = useRef<ConflictBus | null>(null);\n if (!conflictBusRef.current) {\n conflictBusRef.current = new ConflictBus();\n }\n const conflictBus = conflictBusRef.current;\n\n // Sync status state\n const [syncStatus, setSyncStatus] = useState<SyncStatus>(DEFAULT_SYNC_STATUS);\n const [pendingMutations, setPendingMutations] = useState<CrudEntry[]>([]);\n // Combined sync mode state to ensure atomic updates and prevent React batching issues\n const [syncModeState, setSyncModeState] = useState<{\n loaded: boolean;\n mode: SyncMode;\n }>({\n loaded: false,\n mode: 'push-pull'\n });\n const [lastSyncedAt, setLastSyncedAt] = useState<Date | null>(null);\n const [connectionError, setConnectionError] = useState<Error | null>(null);\n const [failedTransactions, setFailedTransactions] = useState<FailedTransaction[]>([]);\n const [completedTransactions, setCompletedTransactions] = useState<CompletedTransaction[]>([]);\n // Track \"new\" completed transactions (since last notification display) for toast/banner notifications\n const [newCompletedTransactions, setNewCompletedTransactions] = useState<CompletedTransaction[]>([]);\n\n // Health and metrics state\n const [connectionHealth, setConnectionHealth] = useState<ConnectionHealth>(DEFAULT_CONNECTION_HEALTH);\n const [syncMetrics, setSyncMetrics] = useState<SyncMetrics>(DEFAULT_SYNC_METRICS);\n\n // Auto-offline state: tracks whether offline mode was set automatically due to network loss\n // When true, sync will auto-resume when network returns\n // When false (user manually chose offline), sync won't auto-resume\n const [isAutoOffline, setIsAutoOffline] = useState(false);\n\n // Network reachability state: tracks whether network is currently reachable\n // This is used as a gate to block uploads even when syncMode is 'push-pull'\n const [networkReachable, setNetworkReachable] = useState(true);\n\n // ─── Refs ──────────────────────────────────────────────────────────────────\n\n const statusTrackerRef = useRef<SyncStatusTracker | null>(null);\n const metricsCollectorRef = useRef<MetricsCollector | null>(null);\n const healthMonitorRef = useRef<HealthMonitor | null>(null);\n const attachmentQueueRef = useRef<PolAttachmentQueue | null>(null);\n const listenerUnsubscribeRef = useRef<(() => void) | null>(null);\n const wasSyncingRef = useRef(false);\n const wasUploadingRef = useRef(false);\n const initializingRef = useRef(false);\n // Track when database is being/has been closed to prevent operations on closed db\n const dbClosedRef = useRef(false);\n // Store connector to clean up on recreation\n const connectorRef = useRef<SupabaseConnector | null>(null);\n // Track cleanup promise to prevent re-initialization during cleanup\n const cleanupPromiseRef = useRef<Promise<void> | null>(null);\n const isCleaningUpRef = useRef(false);\n // Track previous network state for auto-offline detection\n const prevNetworkConnectedRef = useRef<boolean | null>(null);\n // Track if auto-offline handling is initialized (to avoid setting offline on initial false network check)\n const autoOfflineInitializedRef = useRef(false);\n // Refs to avoid stale closures in network listener when checking auto-offline conditions\n const isAutoOfflineRef = useRef(false);\n const syncModeRef = useRef<SyncMode>('push-pull');\n // Ref for removePendingMutation to avoid stale closures in connector callback\n const removePendingMutationRef = useRef<(id: string) => void>(() => {});\n\n // Callback refs - prevents unnecessary effect re-runs when parent passes inline functions\n const onSyncStatusChangeRef = useRef(onSyncStatusChange);\n const onReadyRef = useRef(onReady);\n const onErrorRef = useRef(onError);\n\n // Keep callback refs updated\n useEffect(() => {\n onSyncStatusChangeRef.current = onSyncStatusChange;\n }, [onSyncStatusChange]);\n useEffect(() => {\n onReadyRef.current = onReady;\n }, [onReady]);\n useEffect(() => {\n onErrorRef.current = onError;\n }, [onError]);\n\n // Keep auto-offline and sync mode refs updated to avoid stale closures in network listener\n useEffect(() => {\n isAutoOfflineRef.current = isAutoOffline;\n syncModeRef.current = syncModeState.mode;\n }, [isAutoOffline, syncModeState.mode]);\n\n // ─── Initialize Monitoring Services ────────────────────────────────────────\n\n useEffect(() => {\n // Create status tracker\n const statusTracker = new SyncStatusTracker(platform.storage, logger, {\n onStatusChange: status => {\n setSyncStatus(status);\n setLastSyncedAt(status.lastSyncedAt);\n onSyncStatusChangeRef.current?.(status);\n }\n });\n statusTrackerRef.current = statusTracker;\n\n // Create metrics collector\n const metricsCollector = new MetricsCollector(platform.storage, logger, {\n onMetricsChange: setSyncMetrics\n });\n metricsCollectorRef.current = metricsCollector;\n\n // Create health monitor\n const healthMonitor = new HealthMonitor(logger, {\n onHealthChange: setConnectionHealth\n });\n healthMonitorRef.current = healthMonitor;\n\n // Initialize async with timeout fallback\n const initPromise = Promise.all([statusTracker.init(), metricsCollector.init()]);\n const timeoutPromise = new Promise<[void, void]>(resolve => {\n setTimeout(() => {\n logger.warn('[PowerSyncProvider] Sync mode state load timed out, using default (push-pull)');\n resolve([undefined, undefined]);\n }, 5000); // 5 second timeout\n });\n Promise.race([initPromise, timeoutPromise]).then(() => {\n const loadedMode = statusTracker.getSyncMode();\n const loadedIsAutoOffline = statusTracker.getIsAutoOffline();\n logger.info('[PowerSyncProvider] Sync mode state loaded:', {\n mode: loadedMode,\n isAutoOffline: loadedIsAutoOffline\n });\n // Use single state update to ensure atomic change and prevent React batching issues\n setSyncModeState({\n loaded: true,\n mode: loadedMode\n });\n // Load persisted auto-offline flag so auto-restore works after app restart\n setIsAutoOffline(loadedIsAutoOffline);\n // Load initial completed transactions from storage\n setCompletedTransactions(statusTracker.getCompletedTransactions());\n // newCompletedTransactions starts empty since lastNotificationTime is Date.now() on init\n setNewCompletedTransactions(statusTracker.getNewCompletedTransactions());\n // Load initial failed transactions from storage\n setFailedTransactions(statusTracker.getFailedTransactions());\n });\n\n // Cleanup\n return () => {\n statusTracker.dispose();\n metricsCollector.dispose();\n healthMonitor.dispose();\n };\n }, [platform, logger]);\n\n // ─── Auth State Listener ───────────────────────────────────────────────────\n\n useEffect(() => {\n logger.debug('[PowerSyncProvider] Setting up auth listener');\n\n // Get initial session\n supabaseClient.auth.getSession().then(({\n data: {\n session: initialSession\n }\n }) => {\n logger.debug('[PowerSyncProvider] Initial session:', !!initialSession);\n setSession(initialSession);\n });\n\n // Listen for auth changes\n const {\n data: {\n subscription\n }\n } = supabaseClient.auth.onAuthStateChange((_event, newSession) => {\n logger.debug('[PowerSyncProvider] Auth state changed, hasSession:', !!newSession);\n setSession(newSession);\n });\n return () => {\n subscription.unsubscribe();\n };\n }, [supabaseClient, logger]);\n\n // ─── Database Initialization ───────────────────────────────────────────────\n\n useEffect(() => {\n // Guard against StrictMode double-mounting\n // The ref persists across the quick unmount/remount cycle\n if (initializingRef.current) {\n logger.debug('[PowerSyncProvider] Already initializing, skipping...');\n return;\n }\n initializingRef.current = true;\n\n // Use a controller object to track cancellation\n const controller = {\n cancelled: false\n };\n const initDatabase = async () => {\n try {\n // Wait for any pending cleanup to complete before initializing\n // This prevents \"database is locked\" errors during StrictMode double-mount\n if (cleanupPromiseRef.current) {\n logger.debug('[PowerSyncProvider] Waiting for cleanup to complete...');\n await cleanupPromiseRef.current;\n if (controller.cancelled) {\n initializingRef.current = false;\n return;\n }\n logger.debug('[PowerSyncProvider] Cleanup complete, proceeding with init');\n }\n\n // Reset cleanup state for fresh initialization\n dbClosedRef.current = false;\n logger.info('[PowerSyncProvider] Initializing database...');\n\n // Create database using platform adapter (includes init())\n const database = await platform.createDatabase({\n dbFilename,\n schema\n });\n\n // Check if cancelled during async operation\n if (controller.cancelled) {\n logger.debug('[PowerSyncProvider] Init cancelled, closing database...');\n await database.close();\n initializingRef.current = false;\n return;\n }\n logger.info('[PowerSyncProvider] Database initialized');\n setDb(database);\n setIsReady(true);\n setIsInitializing(false);\n\n // Set database on health monitor\n healthMonitorRef.current?.setDatabase(database);\n\n // Start health monitoring if enabled\n if (mergedSyncConfig.enableHealthMonitoring) {\n healthMonitorRef.current?.start();\n }\n onReadyRef.current?.();\n } catch (err) {\n const initError = err instanceof Error ? err : new Error(String(err));\n logger.error('[PowerSyncProvider] Initialization failed:', initError);\n\n // Only update state if not cancelled\n if (!controller.cancelled) {\n setError(initError);\n setIsInitializing(false);\n onErrorRef.current?.(initError);\n }\n\n // Reset ref on error so retry is possible\n initializingRef.current = false;\n }\n };\n initDatabase();\n return () => {\n // Mark as cancelled - the async operation will check this\n controller.cancelled = true;\n // Reset initializingRef so StrictMode double-mount can reinitialize\n initializingRef.current = false;\n };\n }, [platform, dbFilename, schema, logger, mergedSyncConfig.enableHealthMonitoring]);\n\n // ─── Connect to PowerSync ──────────────────────────────────────────────────\n\n useEffect(() => {\n // Console.log fallback for critical diagnostic point (always visible regardless of logger level)\n if (__DEV__) {\n console.log('[PowerSyncProvider] Connect effect triggered:', {\n hasDb: !!db,\n hasSession: !!session,\n autoConnect: mergedSyncConfig.autoConnect,\n syncModeState\n });\n }\n\n // Use info level for critical connect path so it always appears\n logger.info('[PowerSyncProvider] Connect effect - db:', !!db, 'session:', !!session, 'autoConnect:', mergedSyncConfig.autoConnect, 'syncModeLoaded:', syncModeState.loaded, 'syncMode:', syncModeState.mode);\n\n // Individual checks with logging for each early return condition\n if (!db) {\n logger.debug('[PowerSyncProvider] Connect effect - waiting for db');\n return;\n }\n if (!session) {\n logger.debug('[PowerSyncProvider] Connect effect - no session');\n return;\n }\n if (!mergedSyncConfig.autoConnect) {\n logger.debug('[PowerSyncProvider] Connect effect - autoConnect disabled');\n return;\n }\n\n // Wait for sync mode state to be loaded before deciding\n if (!syncModeState.loaded) {\n logger.info('[PowerSyncProvider] Waiting for sync mode state to load...');\n return;\n }\n\n // Skip connect if offline mode\n if (syncModeState.mode === 'offline') {\n logger.debug('[PowerSyncProvider] Skipping connect - offline mode');\n return;\n }\n\n // Create abort controller to handle sync mode changes during connect\n // This prevents race conditions when mode changes while connection is in progress\n const abortController = new AbortController();\n const connectPowerSync = async () => {\n try {\n // Check if aborted before starting work\n if (abortController.signal.aborted) {\n logger.debug('[PowerSyncProvider] Connect aborted before start');\n return;\n }\n setConnectionError(null);\n\n // Destroy previous connector to clean up listeners and mark as destroyed\n // This sets isDestroyed flag on the old connector to prevent active uploads\n // from continuing with stale connector state\n if (connectorRef.current) {\n connectorRef.current.destroy();\n connectorRef.current = null;\n }\n\n // Check if aborted after destroying previous connector\n if (abortController.signal.aborted) {\n logger.debug('[PowerSyncProvider] Connect aborted after connector cleanup');\n return;\n }\n\n // Create connector with failure callbacks\n const statusTracker_0 = statusTrackerRef.current;\n const newConnector = new SupabaseConnector({\n supabaseClient,\n powerSyncUrl,\n schemaRouter: connectorConfig?.schemaRouter,\n crudHandler: connectorConfig?.crudHandler,\n retryConfig: connectorConfig?.retryConfig,\n logger,\n // Conflict detection - enabled by default\n conflictDetection: {\n enabled: true\n },\n conflictBus,\n // Check if uploads should be performed based on sync mode\n shouldUpload: () => statusTrackerRef.current?.shouldUpload() ?? true,\n // Clear failures when transaction succeeds\n onTransactionSuccess: entries => {\n if (!statusTracker_0) return;\n const entityIds = extractEntityIds(entries);\n entityIds.forEach(id => {\n // Find and clear failures affecting this entity\n const failures = statusTracker_0.getFailuresForEntity(id);\n failures.forEach(f => statusTracker_0.clearFailure(f.id));\n });\n // Update local state\n setFailedTransactions(statusTracker_0.getFailedTransactions());\n },\n // Record failures when transaction fails\n onTransactionFailure: (entries_0, error_0, classified) => {\n if (!statusTracker_0) return;\n statusTracker_0.recordTransactionFailure(entries_0, createSyncError(classified, error_0.message), classified.isPermanent, extractEntityIds(entries_0), extractTableNames(entries_0));\n // Update local state\n setFailedTransactions(statusTracker_0.getFailedTransactions());\n },\n // Record completed transactions\n onTransactionComplete: entries_1 => {\n if (!statusTracker_0) return;\n statusTracker_0.recordTransactionComplete(entries_1);\n // Update local state\n setCompletedTransactions(statusTracker_0.getCompletedTransactions());\n setNewCompletedTransactions(statusTracker_0.getNewCompletedTransactions());\n }\n });\n\n // Check if aborted after creating connector but before using it\n if (abortController.signal.aborted) {\n logger.debug('[PowerSyncProvider] Connect aborted after connector creation, destroying new connector');\n newConnector.destroy();\n return;\n }\n setConnector(newConnector);\n connectorRef.current = newConnector;\n\n // Check if already connected\n if (db.connected) {\n logger.debug('[PowerSyncProvider] Already connected, reconnecting...');\n await db.disconnect();\n }\n\n // Check if aborted after disconnect\n if (abortController.signal.aborted) {\n logger.debug('[PowerSyncProvider] Connect aborted after disconnect');\n return;\n }\n logger.info('[PowerSyncProvider] Connecting to PowerSync...');\n await db.connect(newConnector);\n\n // Check if aborted after connect - if so, don't update state\n if (abortController.signal.aborted) {\n logger.debug('[PowerSyncProvider] Connect aborted after connection established');\n return;\n }\n\n // Verify actual connection status\n if (db.connected) {\n logger.info('[PowerSyncProvider] Connected successfully');\n // Reset reconnect attempts on successful connection\n healthMonitorRef.current?.resetReconnectAttempts();\n } else {\n logger.warn('[PowerSyncProvider] Connection initiated but streaming not established - check PowerSync URL');\n }\n } catch (err_0) {\n // Ignore errors if aborted\n if (abortController.signal.aborted) {\n logger.debug('[PowerSyncProvider] Connect error ignored due to abort');\n return;\n }\n const connectError = err_0 instanceof Error ? err_0 : new Error(String(err_0));\n logger.error('[PowerSyncProvider] Connection failed:', connectError);\n setConnectionError(connectError);\n healthMonitorRef.current?.recordReconnectAttempt();\n }\n };\n connectPowerSync();\n\n // Cleanup: abort any in-progress connection when effect re-runs or unmounts\n return () => {\n abortController.abort();\n };\n }, [db, session, powerSyncUrl, supabaseClient, connectorConfig, conflictBus, mergedSyncConfig.autoConnect, syncModeState, logger]);\n\n // ─── Status Listener ───────────────────────────────────────────────────────\n\n useEffect(() => {\n if (!db) return;\n\n // Set initial status\n const initialStatus = db.currentStatus;\n if (initialStatus) {\n statusTrackerRef.current?.handleStatusChange(initialStatus);\n }\n\n // Register listener\n const unsubscribe = db.registerListener({\n statusChanged: status_0 => {\n statusTrackerRef.current?.handleStatusChange(status_0 as Record<string, unknown>);\n\n // Track sync timing for metrics\n const dataFlow = (status_0 as Record<string, unknown>).dataFlowStatus as Record<string, boolean> | undefined;\n const isDownloading = dataFlow?.downloading ?? false;\n const isUploading = dataFlow?.uploading ?? false;\n const progress = (status_0 as Record<string, unknown>).downloadProgress as Record<string, number> | undefined;\n\n // Log download state changes\n if (isDownloading && !wasSyncingRef.current) {\n logger.info('[PowerSyncProvider] Downloading from server...');\n metricsCollectorRef.current?.markSyncStart();\n }\n if (!isDownloading && wasSyncingRef.current) {\n const duration = metricsCollectorRef.current?.markSyncEnd();\n logger.info('[PowerSyncProvider] Download complete', duration ? `(${duration}ms)` : '');\n if (duration !== null && duration !== undefined) {\n metricsCollectorRef.current?.recordSync({\n durationMs: duration,\n success: true,\n operationsDownloaded: progress?.totalOperations ?? 0\n });\n }\n }\n\n // Log upload state changes\n if (isUploading && !wasUploadingRef.current) {\n logger.info('[PowerSyncProvider] Uploading local changes...');\n }\n if (!isUploading && wasUploadingRef.current) {\n logger.info('[PowerSyncProvider] Upload complete');\n }\n wasSyncingRef.current = isDownloading;\n wasUploadingRef.current = isUploading;\n }\n });\n listenerUnsubscribeRef.current = unsubscribe;\n return () => {\n unsubscribe();\n listenerUnsubscribeRef.current = null;\n };\n }, [db]);\n\n // ─── Pending Mutations Management ─────────────────────────────────────────\n // hydratePendingMutations: Called once on startup to recover unsynced mutations\n // addPendingMutation: Called by mutation hooks after writes\n // removePendingMutation: Called when transactions complete sync\n\n const hydratePendingMutations = useCallback(async () => {\n if (!db || dbClosedRef.current) {\n return;\n }\n try {\n // Read ALL pending mutations (no limit) for full hydration on startup\n const rows = await db.getAll<{\n id: string;\n tx_id: number | null;\n data: string;\n }>('SELECT id, tx_id, data FROM ps_crud ORDER BY id ASC');\n const mutations: CrudEntry[] = rows.map((row): CrudEntry | null => {\n try {\n const parsed = JSON.parse(row.data);\n\n // Extract timestamp from _metadata if available\n let createdAt = new Date(); // fallback\n if (parsed.data?._metadata) {\n try {\n const metadata = typeof parsed.data._metadata === 'string' ? JSON.parse(parsed.data._metadata) : parsed.data._metadata;\n if (metadata?.createdAt) {\n createdAt = new Date(metadata.createdAt);\n }\n } catch {\n // Use fallback if metadata parsing fails\n }\n }\n return {\n id: parsed.data?.id ?? parsed.id ?? row.id,\n clientId: parseInt(row.id, 10) || 0,\n op: parsed.op ?? 'PUT',\n table: parsed.type ?? 'unknown',\n opData: parsed.data,\n transactionId: row.tx_id ?? undefined,\n createdAt\n };\n } catch {\n return null;\n }\n }).filter((e): e is CrudEntry => e !== null);\n if (!dbClosedRef.current) {\n statusTrackerRef.current?.updatePendingMutations(mutations);\n setPendingMutations(mutations);\n }\n } catch {\n // Ignore errors during shutdown\n }\n }, [db]);\n\n // Add a single mutation (called by hooks after successful writes)\n const addPendingMutation = useCallback((entry: CrudEntry) => {\n const entryWithTimestamp = {\n ...entry,\n createdAt: entry.createdAt ?? new Date()\n };\n setPendingMutations(prev => {\n const newMutations = [...prev, entryWithTimestamp];\n statusTrackerRef.current?.updatePendingMutations(newMutations);\n return newMutations;\n });\n }, []);\n\n // Remove a mutation when synced (called from onTransactionComplete)\n const removePendingMutation = useCallback((id_0: string) => {\n setPendingMutations(prev_0 => {\n const newMutations_0 = prev_0.filter(m => m.id !== id_0);\n statusTrackerRef.current?.updatePendingMutations(newMutations_0);\n return newMutations_0;\n });\n }, []);\n\n // Keep ref updated for connector callback\n useEffect(() => {\n removePendingMutationRef.current = removePendingMutation;\n }, [removePendingMutation]);\n\n // ─── Hydrate Pending Mutations on Startup ─────────────────────────────────\n // Only called once when db becomes available to recover unsynced mutations from previous session\n\n useEffect(() => {\n if (!db) return;\n\n // Reset closed flag when db becomes available (fixes race condition with cleanup effect)\n dbClosedRef.current = false;\n\n // Hydrate pending mutations from ps_crud (once on startup only)\n hydratePendingMutations();\n\n // No listener for statusChanged - mutations are now added directly by hooks\n }, [db, hydratePendingMutations]);\n\n // ─── Attachment Queue Initialization ───────────────────────────────────────\n\n useEffect(() => {\n if (!db || !attachmentConfig || attachmentQueueRef.current) {\n return;\n }\n\n // Cancellation controller to prevent setting state after unmount/re-render\n const controller_0 = {\n cancelled: false\n };\n const initAttachmentQueue = async () => {\n try {\n logger.info('[PowerSyncProvider] Initializing attachment queue...');\n\n // Create PolAttachmentQueue (extends AbstractAttachmentQueue from @powersync/attachments)\n const queue = createPolAttachmentQueue(db as any,\n // PowerSync DB instance\n platform, attachmentConfig);\n await queue.init();\n\n // Check if cancelled during async init\n if (controller_0.cancelled) {\n queue.dispose();\n return;\n }\n attachmentQueueRef.current = queue;\n setAttachmentQueue(queue);\n setAttachmentQueueReady(true);\n logger.info('[PowerSyncProvider] Attachment queue initialized successfully');\n } catch (err_1) {\n // Only update state if not cancelled\n if (!controller_0.cancelled) {\n logger.error('[PowerSyncProvider] Attachment queue initialization failed:', err_1);\n // Even on failure, mark as \"ready\" so consumers aren't stuck waiting forever\n // They will see attachmentQueue as null and can handle accordingly\n setAttachmentQueueReady(true);\n }\n }\n };\n initAttachmentQueue();\n return () => {\n controller_0.cancelled = true;\n attachmentQueueRef.current?.dispose();\n attachmentQueueRef.current = null;\n // Reset to false on cleanup - the effect will set the correct initial value on re-run\n setAttachmentQueueReady(false);\n };\n }, [db, attachmentConfig, platform, logger]);\n\n // ─── Cleanup ─────────────────────────────────────────────────────────────────\n\n useEffect(() => {\n // Only run cleanup on unmount\n return () => {\n // Prevent multiple concurrent cleanups\n if (isCleaningUpRef.current) {\n logger.debug('[PowerSyncProvider] Cleanup already in progress, skipping...');\n return;\n }\n logger.info('[PowerSyncProvider] Cleaning up...');\n isCleaningUpRef.current = true;\n\n // Mark database as closed FIRST to prevent any pending operations\n dbClosedRef.current = true;\n\n // Destroy connector to clean up event listeners\n connectorRef.current?.destroy();\n connectorRef.current = null;\n listenerUnsubscribeRef.current?.();\n attachmentQueueRef.current?.dispose();\n healthMonitorRef.current?.stop();\n conflictBusRef.current?.destroy();\n if (db) {\n // Track cleanup promise so initialization can wait for it\n cleanupPromiseRef.current = (async () => {\n try {\n await db.disconnect();\n await db.close();\n logger.debug('[PowerSyncProvider] Database cleanup completed');\n } catch (err_2) {\n // Only log if it's not a \"database already closed\" error\n const errorMessage = err_2 instanceof Error ? err_2.message : String(err_2);\n if (!errorMessage.includes('not open') && !errorMessage.includes('closed')) {\n logger.warn('[PowerSyncProvider] Error during cleanup:', err_2);\n }\n } finally {\n isCleaningUpRef.current = false;\n cleanupPromiseRef.current = null;\n }\n })();\n } else {\n isCleaningUpRef.current = false;\n }\n };\n }, [db, logger]);\n\n // ─── Auto-Offline Network Listener ─────────────────────────────────────────\n // Automatically switch to offline mode when network is lost,\n // and auto-resume when network returns (unless user manually chose offline)\n\n useEffect(() => {\n // Skip if not ready or sync mode not loaded yet\n if (!isReady || !syncModeState.loaded) return;\n const handleNetworkChange = async (isConnected: boolean) => {\n const wasConnected = prevNetworkConnectedRef.current;\n prevNetworkConnectedRef.current = isConnected;\n\n // Update network reachability gate on the status tracker\n // This instantly blocks/allows uploads without changing sync mode\n const tracker = statusTrackerRef.current;\n if (tracker) {\n tracker.setNetworkReachable(isConnected);\n }\n // Also update React state for UI components\n setNetworkReachable(isConnected);\n\n // Initialize on first call - don't auto-offline on startup\n if (!autoOfflineInitializedRef.current) {\n autoOfflineInitializedRef.current = true;\n logger.debug('[PowerSyncProvider] Auto-offline initialized, network:', isConnected);\n return;\n }\n\n // Network lost: auto-enter offline mode\n if (wasConnected === true && !isConnected) {\n logger.info('[PowerSyncProvider] Network lost - auto-entering offline mode');\n const tracker_0 = statusTrackerRef.current;\n if (tracker_0) {\n // Persist auto-offline flag so it survives app restart\n await tracker_0.setIsAutoOffline(true);\n setIsAutoOffline(true);\n await tracker_0.setSyncMode('offline');\n setSyncModeState({\n loaded: true,\n mode: 'offline'\n });\n }\n return;\n }\n\n // Network restored: auto-resume sync (only if we auto-set offline, not user-set)\n if (wasConnected === false && isConnected) {\n // Only auto-resume if we auto-set offline mode (use refs to avoid stale closures)\n if (isAutoOfflineRef.current && syncModeRef.current === 'offline') {\n logger.info('[PowerSyncProvider] Network restored - auto-resuming sync');\n const tracker_1 = statusTrackerRef.current;\n if (tracker_1) {\n // Clear persisted auto-offline flag\n await tracker_1.setIsAutoOffline(false);\n setIsAutoOffline(false);\n await tracker_1.setSyncMode('push-pull');\n setSyncModeState({\n loaded: true,\n mode: 'push-pull'\n });\n\n // Reconnect if we have a connector and db\n if (db && connector && !db.connected) {\n try {\n await db.connect(connector);\n logger.info('[PowerSyncProvider] Reconnected after network restore');\n } catch (err_3) {\n logger.warn('[PowerSyncProvider] Failed to reconnect after network restore:', err_3);\n }\n }\n }\n } else {\n logger.debug('[PowerSyncProvider] Network restored but not auto-resuming (manual offline or different mode)');\n }\n }\n };\n\n // Subscribe to network changes\n const unsubscribe_0 = platform.network.addConnectionListener(handleNetworkChange);\n\n // Get initial network state\n platform.network.isConnected().then(connected => {\n prevNetworkConnectedRef.current = connected;\n autoOfflineInitializedRef.current = true;\n // Set initial network reachability\n const tracker_2 = statusTrackerRef.current;\n if (tracker_2) {\n tracker_2.setNetworkReachable(connected);\n }\n setNetworkReachable(connected);\n\n // Edge case: On app restart with isAutoOffline=true and syncMode='offline',\n // network listener initializes with network already available.\n // No transition (false→true) happens, so auto-resume path never triggers.\n // Check immediately if we should auto-resume.\n if (connected && isAutoOfflineRef.current && syncModeRef.current === 'offline') {\n logger.info('[PowerSyncProvider] Network available on startup with auto-offline active, auto-resuming from offline');\n if (tracker_2) {\n tracker_2.setIsAutoOffline(false);\n setIsAutoOffline(false);\n tracker_2.setSyncMode('push-pull');\n setSyncModeState({\n loaded: true,\n mode: 'push-pull'\n });\n\n // Reconnect if we have a connector and db\n if (db && connector && !db.connected) {\n db.connect(connector).then(() => {\n logger.info('[PowerSyncProvider] Reconnected after auto-resume on startup');\n }).catch(err_4 => {\n logger.warn('[PowerSyncProvider] Failed to reconnect after auto-resume on startup:', err_4);\n });\n }\n }\n }\n logger.debug('[PowerSyncProvider] Auto-offline ready, initial network:', connected);\n });\n return () => {\n unsubscribe_0();\n };\n }, [isReady, syncModeState.loaded, syncModeState.mode, isAutoOffline, db, connector, platform, logger]);\n\n // ─── Clear Failure Functions ────────────────────────────────────────────────\n\n const clearFailure = useCallback((failureId: string) => {\n const tracker_3 = statusTrackerRef.current;\n if (!tracker_3) {\n logger.warn('[PowerSyncProvider] Cannot clear failure - tracker not initialized');\n return;\n }\n tracker_3.clearFailure(failureId);\n setFailedTransactions(tracker_3.getFailedTransactions());\n }, [logger]);\n const clearAllFailures = useCallback(() => {\n const tracker_4 = statusTrackerRef.current;\n if (!tracker_4) {\n logger.warn('[PowerSyncProvider] Cannot clear failures - tracker not initialized');\n return;\n }\n tracker_4.clearAllFailures();\n setFailedTransactions(tracker_4.getFailedTransactions());\n }, [logger]);\n const clearCompletedHistory = useCallback(() => {\n const tracker_5 = statusTrackerRef.current;\n if (!tracker_5) {\n logger.warn('[PowerSyncProvider] Cannot clear completed history - tracker not initialized');\n return;\n }\n tracker_5.clearCompletedHistory();\n setCompletedTransactions(tracker_5.getCompletedTransactions());\n setNewCompletedTransactions(tracker_5.getNewCompletedTransactions());\n }, [logger]);\n const clearCompletedItem = useCallback((completedId: string) => {\n const tracker_6 = statusTrackerRef.current;\n if (!tracker_6) {\n logger.warn('[PowerSyncProvider] Cannot clear completed item - tracker not initialized');\n return;\n }\n tracker_6.clearCompletedItem(completedId);\n setCompletedTransactions(tracker_6.getCompletedTransactions());\n setNewCompletedTransactions(tracker_6.getNewCompletedTransactions());\n }, [logger]);\n const markNotificationsAsSeen = useCallback(() => {\n const tracker_7 = statusTrackerRef.current;\n if (!tracker_7) {\n logger.warn('[PowerSyncProvider] Cannot mark notifications as seen - tracker not initialized');\n return;\n }\n tracker_7.markNotificationsAsSeen();\n setNewCompletedTransactions(tracker_7.getNewCompletedTransactions());\n }, [logger]);\n const setSyncMode = useCallback(async (mode: SyncMode) => {\n const tracker_8 = statusTrackerRef.current;\n if (!tracker_8) {\n logger.warn('[PowerSyncProvider] Cannot set sync mode - tracker not initialized');\n return;\n }\n // Clear auto-offline flag when user manually sets sync mode\n // This ensures manual offline choice won't be auto-resumed\n // Persist the change so it survives app restart\n await tracker_8.setIsAutoOffline(false);\n setIsAutoOffline(false);\n await tracker_8.setSyncMode(mode);\n setSyncModeState({\n loaded: true,\n mode\n });\n }, [logger]);\n const setForceNextUpload = useCallback((force: boolean) => {\n const tracker_9 = statusTrackerRef.current;\n if (!tracker_9) {\n logger.warn('[PowerSyncProvider] Cannot set force upload - tracker not initialized');\n return;\n }\n tracker_9.setForceNextUpload(force);\n }, [logger]);\n\n // Internal function for auto-offline mode changes (sets isAutoOffline flag)\n const setAutoOfflineMode = useCallback(async (mode_0: SyncMode, isAuto: boolean) => {\n const tracker_10 = statusTrackerRef.current;\n if (!tracker_10) {\n logger.warn('[PowerSyncProvider] Cannot set sync mode - tracker not initialized');\n return;\n }\n // Persist the auto-offline flag so it survives app restart\n await tracker_10.setIsAutoOffline(isAuto);\n setIsAutoOffline(isAuto);\n await tracker_10.setSyncMode(mode_0);\n setSyncModeState({\n loaded: true,\n mode: mode_0\n });\n }, [logger]);\n\n // ─── Discard Mutation Functions ────────────────────────────────────────────\n\n const discardPendingMutation = useCallback(async (clientId: number) => {\n if (!db || !connector) {\n logger.warn('[PowerSync] Cannot discard - not initialized');\n return;\n }\n if (syncStatus.uploading) {\n throw new Error('Cannot discard while upload is in progress');\n }\n logger.info('[PowerSync] Discarding pending mutation:', clientId);\n\n // Disconnect to ensure no active transaction\n await db.disconnect();\n try {\n await db.execute('DELETE FROM ps_crud WHERE id = ?', [clientId]);\n logger.info('[PowerSync] Mutation discarded successfully');\n } finally {\n // Use connectorRef.current to avoid stale connector in finally block\n const currentConnector = connectorRef.current;\n if (currentConnector && db) {\n try {\n await db.connect(currentConnector);\n } catch (reconnectError) {\n logger.error('[PowerSync] Failed to reconnect after discard:', reconnectError);\n // Surface the error - don't silently fail\n throw reconnectError;\n }\n }\n }\n }, [db, connector, syncStatus.uploading, logger]);\n const discardAllPendingMutations = useCallback(async () => {\n if (!db || !connector) {\n logger.warn('[PowerSync] Cannot discard all - not initialized');\n return;\n }\n if (syncStatus.uploading) {\n throw new Error('Cannot discard while upload is in progress');\n }\n logger.info('[PowerSync] Discarding all pending mutations');\n await db.disconnect();\n try {\n await db.execute('DELETE FROM ps_crud');\n logger.info('[PowerSync] All mutations discarded successfully');\n } finally {\n // Use connectorRef.current to avoid stale connector in finally block\n const currentConnector = connectorRef.current;\n if (currentConnector && db) {\n try {\n await db.connect(currentConnector);\n } catch (reconnectError) {\n logger.error('[PowerSync] Failed to reconnect after discard:', reconnectError);\n // Surface the error - don't silently fail\n throw reconnectError;\n }\n }\n }\n }, [db, connector, syncStatus.uploading, logger]);\n\n // ─── Retry Control Functions ──────────────────────────────────────────────\n\n const pauseAutoRetry = useCallback(() => {\n if (!connector) {\n logger.warn('[PowerSyncProvider] Cannot pause auto-retry - connector not initialized');\n return;\n }\n connector.pauseAutoRetry();\n }, [connector, logger]);\n const resumeAutoRetry = useCallback(() => {\n if (!connector) {\n logger.warn('[PowerSyncProvider] Cannot resume auto-retry - connector not initialized');\n return;\n }\n connector.resumeAutoRetry();\n }, [connector, logger]);\n const retryFailure = useCallback(async (failureId_0: string) => {\n const tracker_11 = statusTrackerRef.current;\n if (!tracker_11) return;\n\n // Get the failure first (before removing) to preserve the error info\n const failures_0 = tracker_11.getFailedTransactions();\n const failure = failures_0.find(f_0 => f_0.id === failureId_0);\n if (!failure) {\n logger.warn('[PowerSyncProvider] Failure not found:', failureId_0);\n return;\n }\n\n // Remove from tracking (entries stay in ps_crud for retry)\n const entries_2 = tracker_11.takeFailureForRetry(failureId_0);\n if (!entries_2 || entries_2.length === 0) return;\n\n // Update local state\n setFailedTransactions(tracker_11.getFailedTransactions());\n\n // Trigger a sync to pick up pending items\n if (!db || !connector) {\n logger.warn('[PowerSyncProvider] Cannot retry - not initialized');\n // Re-record the failure since we can't sync\n tracker_11.recordTransactionFailure(failure.entries, failure.error, failure.isPermanent, failure.affectedEntityIds, failure.affectedTables, {\n retryCount: failure.retryCount,\n firstFailedAt: failure.firstFailedAt\n });\n setFailedTransactions(tracker_11.getFailedTransactions());\n return;\n }\n try {\n // Disconnect and reconnect to force a fresh sync\n if (db.connected) {\n await db.disconnect();\n }\n await db.connect(connector);\n logger.info('[PowerSyncProvider] Retry triggered for failure:', failureId_0);\n } catch (err_5) {\n logger.error('[PowerSyncProvider] Retry failed, re-recording failure:', err_5);\n // Re-record the failure so user can try again\n tracker_11.recordTransactionFailure(failure.entries, failure.error, failure.isPermanent, failure.affectedEntityIds, failure.affectedTables, {\n retryCount: failure.retryCount,\n firstFailedAt: failure.firstFailedAt\n });\n setFailedTransactions(tracker_11.getFailedTransactions());\n }\n }, [db, connector, logger]);\n\n // ─── Context Values ────────────────────────────────────────────────────────\n\n const powerSyncContextValue = useMemo<PowerSyncContextValue<TSchema>>(() => ({\n db,\n connector,\n attachmentQueue,\n isReady,\n isInitializing,\n attachmentQueueReady,\n error,\n schema,\n platform,\n conflictBus\n }), [db, connector, attachmentQueue, isReady, isInitializing, attachmentQueueReady, error, schema, platform, conflictBus]);\n const syncStatusContextValue = useMemo<SyncStatusContextValue>(() => ({\n status: syncStatus,\n pendingMutations,\n pendingCount: pendingMutations.length,\n // Expose uploading/downloading directly from syncStatus for reliable activity detection\n isUploading: syncStatus.uploading,\n isDownloading: syncStatus.downloading,\n isPaused: syncModeState.mode === 'offline',\n syncMode: syncModeState.mode,\n lastSyncedAt,\n // Connection error for consumers to display\n connectionError,\n // Failed transaction fields\n failedTransactions,\n hasUploadErrors: failedTransactions.length > 0,\n permanentErrorCount: failedTransactions.filter(f_1 => f_1.isPermanent).length,\n // Clear failure functions\n clearFailure,\n clearAllFailures,\n // Completed transaction fields\n completedTransactions,\n clearCompletedHistory,\n // Sync mode control functions\n setSyncMode,\n setForceNextUpload,\n // Discard mutation functions\n discardPendingMutation,\n discardAllPendingMutations,\n // Retry control functions\n pauseAutoRetry,\n resumeAutoRetry\n }), [syncStatus, pendingMutations, syncModeState.mode, lastSyncedAt, connectionError, failedTransactions, clearFailure, clearAllFailures, completedTransactions, clearCompletedHistory, setSyncMode, setForceNextUpload, discardPendingMutation, discardAllPendingMutations, pauseAutoRetry, resumeAutoRetry]);\n const connectionHealthContextValue = useMemo<ConnectionHealthContextValue>(() => ({\n health: connectionHealth\n }), [connectionHealth]);\n const syncMetricsContextValue = useMemo<SyncMetricsContextValue>(() => ({\n metrics: syncMetrics\n }), [syncMetrics]);\n\n // ─── Split Context Values (Performance Optimization) ────────────────────────\n // Each context is memoized independently so changes to one don't trigger\n // re-renders in components subscribed to others.\n\n // Connection status - rarely changes (on connect/disconnect)\n const connectionStatusValue = useMemo<ConnectionStatusContextValue>(() => ({\n connected: syncStatus.connected,\n connecting: syncStatus.connecting,\n hasSynced: syncStatus.hasSynced,\n lastSyncedAt,\n connectionError\n }), [syncStatus.connected, syncStatus.connecting, syncStatus.hasSynced, lastSyncedAt, connectionError]);\n\n // Sync activity - changes during active sync\n const syncActivityValue = useMemo<SyncActivityContextValue>(() => ({\n uploading: syncStatus.uploading,\n downloading: syncStatus.downloading,\n downloadProgress: syncStatus.downloadProgress\n }), [syncStatus.uploading, syncStatus.downloading, syncStatus.downloadProgress]);\n\n // Pending mutations - changes on local writes\n const pendingMutationsValue = useMemo<PendingMutationsContextValue>(() => ({\n pendingMutations,\n pendingCount: pendingMutations.length,\n discardPendingMutation,\n discardAllPendingMutations,\n addPendingMutation,\n removePendingMutation\n }), [pendingMutations, discardPendingMutation, discardAllPendingMutations, addPendingMutation, removePendingMutation]);\n\n // Failed transactions - changes on failures\n const failedTransactionsValue = useMemo<FailedTransactionsContextValue>(() => ({\n failedTransactions,\n hasUploadErrors: failedTransactions.length > 0,\n permanentErrorCount: failedTransactions.filter(f_2 => f_2.isPermanent).length,\n clearFailure,\n clearAllFailures,\n pauseAutoRetry,\n resumeAutoRetry,\n retryFailure\n }), [failedTransactions, clearFailure, clearAllFailures, pauseAutoRetry, resumeAutoRetry, retryFailure]);\n\n // Completed transactions - changes on successful syncs\n const completedTransactionsValue = useMemo<CompletedTransactionsContextValue>(() => ({\n completedTransactions,\n clearCompletedHistory,\n clearCompletedItem,\n newCompletedTransactions,\n markNotificationsAsSeen\n }), [completedTransactions, clearCompletedHistory, clearCompletedItem, newCompletedTransactions, markNotificationsAsSeen]);\n\n // Sync mode - rarely changes (user action or auto-offline)\n const syncModeValue = useMemo<SyncModeContextValue>(() => ({\n syncMode: syncModeState.mode,\n isPaused: syncModeState.mode === 'offline',\n isAutoOffline,\n networkReachable,\n setSyncMode,\n setForceNextUpload\n }), [syncModeState.mode, isAutoOffline, networkReachable, setSyncMode, setForceNextUpload]);\n\n // ─── Render ────────────────────────────────────────────────────────────────\n\n return <PowerSyncContext.Provider value={powerSyncContextValue as PowerSyncContextValue}>\n <ConnectionStatusContext.Provider value={connectionStatusValue}>\n <SyncActivityContext.Provider value={syncActivityValue}>\n <PendingMutationsContext.Provider value={pendingMutationsValue}>\n <FailedTransactionsContext.Provider value={failedTransactionsValue}>\n <CompletedTransactionsContext.Provider value={completedTransactionsValue}>\n <SyncModeContext.Provider value={syncModeValue}>\n <SyncStatusContext.Provider value={syncStatusContextValue}>\n <ConnectionHealthContext.Provider value={connectionHealthContextValue}>\n <SyncMetricsContext.Provider value={syncMetricsContextValue}>\n <AttachmentQueueContext.Provider value={attachmentQueue}>\n {children}\n </AttachmentQueueContext.Provider>\n </SyncMetricsContext.Provider>\n </ConnectionHealthContext.Provider>\n </SyncStatusContext.Provider>\n </SyncModeContext.Provider>\n </CompletedTransactionsContext.Provider>\n </FailedTransactionsContext.Provider>\n </PendingMutationsContext.Provider>\n </SyncActivityContext.Provider>\n </ConnectionStatusContext.Provider>\n </PowerSyncContext.Provider>;\n}","import type { ConflictCheckResult, ConflictResolution } from './types';\nexport type ConflictListener = (conflict: ConflictCheckResult) => void;\nexport type ResolutionListener = (table: string, recordId: string, resolution: ConflictResolution) => void;\n\n/**\n * Event bus for decoupling conflict detection from UI resolution.\n *\n * Flow:\n * 1. Connector detects conflict -> calls bus.emitConflict()\n * 2. ConflictContext subscribes via bus.onConflict() -> shows UI\n * 3. User resolves -> ConflictContext calls bus.emitResolution()\n * 4. Connector subscribes via bus.onResolution() -> triggers re-upload\n */\nexport class ConflictBus {\n private static MAX_PENDING = 100;\n private conflictListeners = new Set<ConflictListener>();\n private resolutionListeners = new Set<ResolutionListener>();\n private pendingConflicts: ConflictCheckResult[] = [];\n\n /**\n * Subscribe to conflict detection events.\n * Flushes any pending conflicts to ALL listeners (including the new one).\n * @returns Unsubscribe function\n */\n onConflict(listener: ConflictListener): () => void {\n this.conflictListeners.add(listener);\n\n // Flush pending conflicts to ALL listeners, not just the new one\n if (this.pendingConflicts.length > 0) {\n const pending = [...this.pendingConflicts];\n this.pendingConflicts = [];\n for (const conflict of pending) {\n this.conflictListeners.forEach(l => l(conflict));\n }\n }\n return () => this.conflictListeners.delete(listener);\n }\n\n /**\n * Subscribe to resolution events.\n * @returns Unsubscribe function\n */\n onResolution(listener: ResolutionListener): () => void {\n this.resolutionListeners.add(listener);\n return () => this.resolutionListeners.delete(listener);\n }\n\n /**\n * Emit a conflict detection event (called by connector).\n * If no listeners are subscribed, queues the conflict for later delivery.\n */\n emitConflict(conflict: ConflictCheckResult): void {\n if (this.conflictListeners.size === 0) {\n console.warn('[ConflictBus] No listeners - queueing conflict');\n if (this.pendingConflicts.length >= ConflictBus.MAX_PENDING) {\n console.warn('[ConflictBus] Pending queue full, dropping oldest conflict');\n this.pendingConflicts.shift();\n }\n this.pendingConflicts.push(conflict);\n return;\n }\n this.conflictListeners.forEach(listener => listener(conflict));\n }\n\n /**\n * Emit a resolution event (called by UI/ConflictContext).\n */\n emitResolution(table: string, recordId: string, resolution: ConflictResolution): void {\n this.resolutionListeners.forEach(listener => listener(table, recordId, resolution));\n }\n\n /**\n * Clear all listeners and pending conflicts (for cleanup).\n */\n destroy(): void {\n this.conflictListeners.clear();\n this.resolutionListeners.clear();\n this.pendingConflicts = [];\n }\n\n /**\n * Get the number of pending conflicts (useful for debugging/testing).\n */\n get pendingCount(): number {\n return this.pendingConflicts.length;\n }\n}","import { c as _c } from \"react/compiler-runtime\";\n/**\n * OfflineDataProvider Component for @pol-studios/powersync\n *\n * Batteries-included offline data provider that combines:\n * - PowerSyncProvider for offline-first data sync\n * - DataLayerProvider integration from @pol-studios/db\n * - ConflictProvider for conflict resolution UI\n * - StorageQueueProvider for attachment queue access\n * - Background sync system setup\n * - Error recovery UI with retry capability\n * - Online-only mode fallback (no PowerSync URL)\n *\n * This is the recommended entry point for apps using offline-first data.\n *\n * @example\n * ```tsx\n * <OfflineDataProvider\n * config={{\n * schema: AppSchema,\n * supabaseClient: supabase,\n * queryClient: queryClient,\n * powerSyncUrl: env.powerSyncUrl,\n * attachments: {\n * bucket: 'my-bucket',\n * sourceTable: 'MediaContent',\n * idColumn: 'storagePath',\n * },\n * }}\n * dataLayer={{ config: dataLayerConfig }}\n * renderInitError={(error, retry) => <MyErrorUI error={error} onRetry={retry} />}\n * >\n * <App />\n * </OfflineDataProvider>\n * ```\n */\n\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { View, Text, StyleSheet, Pressable } from 'react-native';\nimport type { CrudEntry, AbstractPowerSyncDatabase } from '../core/types';\nimport type { OfflineDataProviderProps, PowerSyncSyncStatusSnapshot } from './OfflineDataProvider.types';\nimport type { BackgroundSyncSystem } from '../sync/background-sync';\n\n/**\n * SyncControl interface matching @pol-studios/db DataLayerProvider expectations.\n * This is defined locally to avoid circular dependencies.\n */\ninterface DataLayerSyncControl {\n triggerSync: () => Promise<void>;\n startLiveSync: () => Promise<void>;\n stopLiveSync: () => void;\n setScope: (scopeName: string, values: string[]) => Promise<void>;\n retryFailedUploads?: () => Promise<void>;\n clearFailedUploads?: () => void;\n failedUploads?: unknown[];\n pauseAutoRetry: () => void;\n resumeAutoRetry: () => void;\n isAutoRetryPaused: boolean;\n addPendingMutation: (entry: {\n id: string;\n table: string;\n op: string;\n opData?: unknown;\n createdAt?: Date;\n }) => void;\n removePendingMutation: (id: string) => void;\n}\nimport { PowerSyncProvider } from './PowerSyncProvider';\nimport { PowerSyncErrorBoundary } from '../error';\nimport { SupabaseStorageAdapter } from '../storage';\nimport { createNativePlatformAdapter } from '../platform/index.native';\nimport type { LoggerAdapter, PlatformAdapter } from '../platform/types';\nimport { ProviderBridge } from './ProviderBridge';\n\n// ─── Default Logger ───────────────────────────────────────────────────────────\n\n/**\n * Default console logger for when no platform is provided.\n */\nconst defaultLogger: LoggerAdapter = {\n debug: (...args) => console.debug('[OfflineData]', ...args),\n info: (...args) => console.info('[OfflineData]', ...args),\n warn: (...args) => console.warn('[OfflineData]', ...args),\n error: (...args) => console.error('[OfflineData]', ...args)\n};\n\n// ─── Error Recovery UI Styles ─────────────────────────────────────────────────\n\nconst errorStyles = StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n backgroundColor: '#f5f5f5',\n padding: 20\n },\n content: {\n backgroundColor: 'white',\n borderRadius: 12,\n padding: 24,\n maxWidth: 400,\n width: '100%',\n shadowColor: '#000',\n shadowOffset: {\n width: 0,\n height: 2\n },\n shadowOpacity: 0.1,\n shadowRadius: 8,\n elevation: 4\n },\n title: {\n fontSize: 20,\n fontWeight: '600',\n color: '#1a1a1a',\n marginBottom: 12,\n textAlign: 'center'\n },\n message: {\n fontSize: 14,\n color: '#666',\n marginBottom: 16,\n textAlign: 'center',\n lineHeight: 20\n },\n errorDetail: {\n fontSize: 12,\n color: '#999',\n marginBottom: 20,\n textAlign: 'center',\n fontFamily: 'monospace'\n },\n retryButton: {\n backgroundColor: '#007AFF',\n borderRadius: 8,\n paddingVertical: 12,\n paddingHorizontal: 24,\n alignItems: 'center'\n },\n retryButtonText: {\n color: 'white',\n fontSize: 16,\n fontWeight: '600'\n }\n});\n\n// ─── Default Error Recovery UI ───────────────────────────────────────────────\n\n/**\n * Default error recovery UI shown when initialization fails.\n */\nfunction DefaultErrorRecoveryUI(t0) {\n const $ = _c(10);\n const {\n error,\n onRetry\n } = t0;\n let t1;\n let t2;\n if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n t1 = <Text style={errorStyles.title}>Database Error</Text>;\n t2 = <Text style={errorStyles.message}>The local database encountered an error. This can happen if the app was interrupted during startup.</Text>;\n $[0] = t1;\n $[1] = t2;\n } else {\n t1 = $[0];\n t2 = $[1];\n }\n let t3;\n if ($[2] !== error.message) {\n t3 = <Text style={errorStyles.errorDetail}>{error.message}</Text>;\n $[2] = error.message;\n $[3] = t3;\n } else {\n t3 = $[3];\n }\n let t4;\n if ($[4] === Symbol.for(\"react.memo_cache_sentinel\")) {\n t4 = <Text style={errorStyles.retryButtonText}>Retry</Text>;\n $[4] = t4;\n } else {\n t4 = $[4];\n }\n let t5;\n if ($[5] !== onRetry) {\n t5 = <Pressable style={errorStyles.retryButton} onPress={onRetry}>{t4}</Pressable>;\n $[5] = onRetry;\n $[6] = t5;\n } else {\n t5 = $[6];\n }\n let t6;\n if ($[7] !== t3 || $[8] !== t5) {\n t6 = <View style={errorStyles.container}><View style={errorStyles.content}>{t1}{t2}{t3}{t5}</View></View>;\n $[7] = t3;\n $[8] = t5;\n $[9] = t6;\n } else {\n t6 = $[9];\n }\n return t6;\n}\n\n// ─── Main Provider Component ──────────────────────────────────────────────────\n\n/**\n * Batteries-included offline data provider.\n *\n * Combines PowerSyncProvider with error boundary, DataLayerProvider integration,\n * and sensible defaults for a complete offline-first data solution.\n *\n * Key features:\n * - Automatic PowerSync setup and initialization\n * - Integration with @pol-studios/db DataLayerProvider\n * - ConflictProvider and StorageQueueProvider wiring\n * - Background sync system support\n * - Error recovery UI with retry capability\n * - Online-only mode fallback when no PowerSync URL is provided\n *\n * @example\n * ```tsx\n * // Basic usage\n * <OfflineDataProvider\n * config={{\n * schema: AppSchema,\n * supabaseClient: supabase,\n * queryClient: queryClient,\n * powerSyncUrl: process.env.EXPO_PUBLIC_POWERSYNC_URL,\n * }}\n * >\n * <App />\n * </OfflineDataProvider>\n *\n * // With DataLayer integration\n * <OfflineDataProvider\n * config={{ ... }}\n * dataLayer={{ config: dataLayerConfig }}\n * >\n * <App />\n * </OfflineDataProvider>\n *\n * // With custom error UI\n * <OfflineDataProvider\n * config={{ ... }}\n * renderInitError={(error, retry) => <MyErrorUI error={error} onRetry={retry} />}\n * >\n * <App />\n * </OfflineDataProvider>\n * ```\n */\nexport function OfflineDataProvider(t0) {\n const $ = _c(109);\n const {\n config,\n children,\n dataLayer,\n backgroundSync,\n skipConflictProvider: t1,\n skipStorageQueueProvider: t2,\n storageAdapter: customStorageAdapter,\n uploadHandler: customUploadHandler,\n renderInitError,\n renderError,\n onReady,\n onError,\n onSyncStatusChange,\n onBackgroundSyncSystemReady: onBackgroundSyncSystemReadyProp\n } = t0;\n const skipConflictProvider = t1 === undefined ? false : t1;\n const skipStorageQueueProvider = t2 === undefined ? false : t2;\n const {\n schema,\n supabaseClient,\n queryClient,\n powerSyncUrl,\n dbFilename: t3,\n attachments,\n platform: customPlatform,\n connector: connectorConfig,\n sync: syncConfig\n } = config;\n const dbFilename = t3 === undefined ? \"powersync.db\" : t3;\n const [initError, setInitError] = useState(null);\n const [retryKey, setRetryKey] = useState(0);\n const [powerSyncInstance, setPowerSyncInstance] = useState(null);\n const [powerSyncSyncStatus, setPowerSyncSyncStatus] = useState(undefined);\n const addPendingMutationRef = useRef(null);\n const removePendingMutationRef = useRef(null);\n const backgroundSyncSystemRef = useRef(null);\n let t4;\n if ($[0] !== customPlatform) {\n t4 = customPlatform ?? createNativePlatformAdapter(defaultLogger);\n $[0] = customPlatform;\n $[1] = t4;\n } else {\n t4 = $[1];\n }\n const platform = t4;\n let t5;\n bb0: {\n if (customStorageAdapter) {\n t5 = customStorageAdapter;\n break bb0;\n }\n if (!attachments) {\n t5 = undefined;\n break bb0;\n }\n let t6;\n if ($[2] !== attachments.bucket || $[3] !== platform.fileSystem || $[4] !== supabaseClient) {\n t6 = new SupabaseStorageAdapter({\n client: supabaseClient,\n bucketConfig: {\n defaultBucket: attachments.bucket\n }\n }, platform.fileSystem);\n $[2] = attachments.bucket;\n $[3] = platform.fileSystem;\n $[4] = supabaseClient;\n $[5] = t6;\n } else {\n t6 = $[5];\n }\n t5 = t6;\n }\n const storageAdapter = t5;\n let t10;\n let t11;\n let t6;\n let t7;\n let t8;\n let t9;\n if ($[6] !== platform.logger) {\n t6 = async () => {\n platform.logger.warn(\"Sync not available: Use useSyncControl from PowerSync context\");\n };\n t7 = async () => {\n platform.logger.warn(\"Live sync not available: Use useSyncControl from PowerSync context\");\n };\n t8 = () => {\n platform.logger.warn(\"Live sync not available: Use useSyncControl from PowerSync context\");\n };\n t9 = async () => {\n platform.logger.warn(\"Scope control not available: Use useSyncControl from PowerSync context\");\n };\n t10 = async () => {\n platform.logger.warn(\"Retry not available: Use useSyncControl from PowerSync context\");\n };\n t11 = () => {\n platform.logger.warn(\"Clear failed uploads not available: Use useSyncControl from PowerSync context\");\n };\n $[6] = platform.logger;\n $[7] = t10;\n $[8] = t11;\n $[9] = t6;\n $[10] = t7;\n $[11] = t8;\n $[12] = t9;\n } else {\n t10 = $[7];\n t11 = $[8];\n t6 = $[9];\n t7 = $[10];\n t8 = $[11];\n t9 = $[12];\n }\n let t12;\n if ($[13] === Symbol.for(\"react.memo_cache_sentinel\")) {\n t12 = [];\n $[13] = t12;\n } else {\n t12 = $[13];\n }\n let t13;\n let t14;\n if ($[14] !== platform.logger) {\n t13 = () => {\n platform.logger.warn(\"Pause auto-retry not available: Use useSyncControl from PowerSync context\");\n };\n t14 = () => {\n platform.logger.warn(\"Resume auto-retry not available: Use useSyncControl from PowerSync context\");\n };\n $[14] = platform.logger;\n $[15] = t13;\n $[16] = t14;\n } else {\n t13 = $[15];\n t14 = $[16];\n }\n let t15;\n let t16;\n if ($[17] === Symbol.for(\"react.memo_cache_sentinel\")) {\n t15 = entry => {\n if (addPendingMutationRef.current) {\n addPendingMutationRef.current(entry as CrudEntry);\n }\n };\n t16 = id => {\n if (removePendingMutationRef.current) {\n removePendingMutationRef.current(id);\n }\n };\n $[17] = t15;\n $[18] = t16;\n } else {\n t15 = $[17];\n t16 = $[18];\n }\n let t17;\n if ($[19] !== t10 || $[20] !== t11 || $[21] !== t13 || $[22] !== t14 || $[23] !== t6 || $[24] !== t7 || $[25] !== t8 || $[26] !== t9) {\n t17 = {\n triggerSync: t6,\n startLiveSync: t7,\n stopLiveSync: t8,\n setScope: t9,\n retryFailedUploads: t10,\n clearFailedUploads: t11,\n failedUploads: t12,\n pauseAutoRetry: t13,\n resumeAutoRetry: t14,\n isAutoRetryPaused: false,\n addPendingMutation: t15,\n removePendingMutation: t16\n };\n $[19] = t10;\n $[20] = t11;\n $[21] = t13;\n $[22] = t14;\n $[23] = t6;\n $[24] = t7;\n $[25] = t8;\n $[26] = t9;\n $[27] = t17;\n } else {\n t17 = $[27];\n }\n const syncControl = t17;\n let t18;\n bb1: {\n if (!attachments) {\n t18 = undefined;\n break bb1;\n }\n let t19;\n if ($[28] !== attachments.idColumn || $[29] !== attachments.orderByColumn || $[30] !== attachments.projectFilter || $[31] !== attachments.sourceTable) {\n t19 = {\n table: attachments.sourceTable,\n idColumn: attachments.idColumn,\n orderByColumn: attachments.orderByColumn,\n projectFilter: attachments.projectFilter\n };\n $[28] = attachments.idColumn;\n $[29] = attachments.orderByColumn;\n $[30] = attachments.projectFilter;\n $[31] = attachments.sourceTable;\n $[32] = t19;\n } else {\n t19 = $[32];\n }\n let t20;\n if ($[33] !== platform.logger) {\n t20 = async (attachment, error) => {\n platform.logger.warn(`[AttachmentQueue] Download failed for ${attachment.filename}:`, error);\n return {\n retry: true\n };\n };\n $[33] = platform.logger;\n $[34] = t20;\n } else {\n t20 = $[34];\n }\n let t21;\n if ($[35] !== customUploadHandler) {\n t21 = customUploadHandler ? {\n handler: customUploadHandler,\n config: {\n concurrency: 3,\n timeoutMs: 120000,\n baseRetryDelayMs: 5000,\n maxRetryDelayMs: 3600000,\n staleDaysThreshold: 7\n }\n } : undefined;\n $[35] = customUploadHandler;\n $[36] = t21;\n } else {\n t21 = $[36];\n }\n let t22;\n if ($[37] !== storageAdapter || $[38] !== t19 || $[39] !== t20 || $[40] !== t21) {\n t22 = {\n source: t19,\n remoteStorage: storageAdapter,\n attachmentTableName: \"photo_attachments\",\n performInitialSync: true,\n onDownloadError: t20,\n upload: t21\n };\n $[37] = storageAdapter;\n $[38] = t19;\n $[39] = t20;\n $[40] = t21;\n $[41] = t22;\n } else {\n t22 = $[41];\n }\n t18 = t22;\n }\n const attachmentConfig = t18;\n const t19 = powerSyncUrl ?? \"\";\n const t20 = syncConfig?.autoConnect ?? true;\n const t21 = syncConfig?.enableHealthMonitoring ?? true;\n const t22 = syncConfig?.enableMetrics ?? true;\n let t23;\n if ($[42] !== t20 || $[43] !== t21 || $[44] !== t22) {\n t23 = {\n autoConnect: t20,\n enableHealthMonitoring: t21,\n enableMetrics: t22\n };\n $[42] = t20;\n $[43] = t21;\n $[44] = t22;\n $[45] = t23;\n } else {\n t23 = $[45];\n }\n let t24;\n if ($[46] !== attachmentConfig || $[47] !== connectorConfig || $[48] !== dbFilename || $[49] !== platform || $[50] !== queryClient || $[51] !== schema || $[52] !== supabaseClient || $[53] !== t19 || $[54] !== t23) {\n t24 = {\n platform,\n schema,\n powerSyncUrl: t19,\n supabaseClient,\n queryClient,\n dbFilename,\n connector: connectorConfig,\n attachments: attachmentConfig,\n sync: t23\n };\n $[46] = attachmentConfig;\n $[47] = connectorConfig;\n $[48] = dbFilename;\n $[49] = platform;\n $[50] = queryClient;\n $[51] = schema;\n $[52] = supabaseClient;\n $[53] = t19;\n $[54] = t23;\n $[55] = t24;\n } else {\n t24 = $[55];\n }\n const powerSyncConfig = t24;\n let t25;\n if ($[56] !== onError || $[57] !== platform.logger) {\n t25 = err => {\n platform.logger.error(\"PowerSync error:\", err);\n const errorMessage = err.message ?? \"\";\n if (errorMessage.includes(\"not open\") || errorMessage.includes(\"closed\") || errorMessage.includes(\"failed to open\") || errorMessage.includes(\"initialization failed\")) {\n setInitError(err);\n }\n onError?.(err);\n };\n $[56] = onError;\n $[57] = platform.logger;\n $[58] = t25;\n } else {\n t25 = $[58];\n }\n const handlePowerSyncError = t25;\n let t26;\n if ($[59] !== platform.logger) {\n t26 = () => {\n platform.logger.info(\"Retrying PowerSync initialization...\");\n setInitError(null);\n setRetryKey(_temp);\n };\n $[59] = platform.logger;\n $[60] = t26;\n } else {\n t26 = $[60];\n }\n const handleRetry = t26;\n let t27;\n if ($[61] !== backgroundSync?.callbacks || $[62] !== onBackgroundSyncSystemReadyProp || $[63] !== platform.logger) {\n t27 = system => {\n backgroundSyncSystemRef.current = system;\n backgroundSync?.callbacks?.onSyncStart?.();\n onBackgroundSyncSystemReadyProp?.(system);\n platform.logger.info(\"[Background Sync] System ready\");\n };\n $[61] = backgroundSync?.callbacks;\n $[62] = onBackgroundSyncSystemReadyProp;\n $[63] = platform.logger;\n $[64] = t27;\n } else {\n t27 = $[64];\n }\n backgroundSync?.callbacks;\n const handleBackgroundSyncSystemReady = t27;\n let t28;\n if ($[65] !== renderError || $[66] !== renderInitError) {\n t28 = (error_0, retry) => {\n const customRenderer = renderInitError ?? renderError;\n if (customRenderer) {\n return customRenderer(error_0, retry);\n }\n return <DefaultErrorRecoveryUI error={error_0} onRetry={retry} />;\n };\n $[65] = renderError;\n $[66] = renderInitError;\n $[67] = t28;\n } else {\n t28 = $[67];\n }\n const errorFallback = t28;\n let t29;\n if ($[68] !== powerSyncSyncStatus || $[69] !== powerSyncUrl) {\n t29 = !powerSyncUrl ? {\n hasSynced: true,\n connected: true,\n connecting: false,\n isOnline: true\n } : powerSyncSyncStatus;\n $[68] = powerSyncSyncStatus;\n $[69] = powerSyncUrl;\n $[70] = t29;\n } else {\n t29 = $[70];\n }\n const effectiveSyncStatus = t29;\n let t30;\n let t31;\n if ($[71] !== effectiveSyncStatus || $[72] !== onSyncStatusChange) {\n t30 = () => {\n if (effectiveSyncStatus) {\n onSyncStatusChange?.(effectiveSyncStatus);\n }\n };\n t31 = [effectiveSyncStatus, onSyncStatusChange];\n $[71] = effectiveSyncStatus;\n $[72] = onSyncStatusChange;\n $[73] = t30;\n $[74] = t31;\n } else {\n t30 = $[73];\n t31 = $[74];\n }\n useEffect(t30, t31);\n let t32;\n let t33;\n if ($[75] !== backgroundSync || $[76] !== children || $[77] !== dataLayer || $[78] !== effectiveSyncStatus || $[79] !== errorFallback || $[80] !== handleBackgroundSyncSystemReady || $[81] !== handlePowerSyncError || $[82] !== handleRetry || $[83] !== initError || $[84] !== onError || $[85] !== onReady || $[86] !== platform.logger || $[87] !== powerSyncConfig || $[88] !== powerSyncInstance || $[89] !== powerSyncUrl || $[90] !== queryClient || $[91] !== renderError || $[92] !== renderInitError || $[93] !== retryKey || $[94] !== skipConflictProvider || $[95] !== skipStorageQueueProvider || $[96] !== supabaseClient || $[97] !== syncControl) {\n t33 = Symbol.for(\"react.early_return_sentinel\");\n bb2: {\n const renderContent = () => {\n if (!powerSyncUrl) {\n return <>{children}</>;\n }\n if (initError) {\n const customRenderer_0 = renderInitError ?? renderError;\n if (customRenderer_0) {\n return <>{customRenderer_0(initError, handleRetry)}</>;\n }\n return <DefaultErrorRecoveryUI error={initError} onRetry={handleRetry} />;\n }\n return <PowerSyncErrorBoundary fallback={errorFallback} onError={handlePowerSyncError}><PowerSyncProvider key={retryKey} config={powerSyncConfig as any} onReady={() => {\n platform.logger.info(\"PowerSync initialized and ready\");\n setInitError(null);\n onReady?.();\n }} onError={handlePowerSyncError}><ProviderBridge skipConflictProvider={skipConflictProvider} skipStorageQueueProvider={skipStorageQueueProvider} backgroundSync={backgroundSync} onBackgroundSyncSystemReady={handleBackgroundSyncSystemReady} onDbReady={(db, syncStatus) => {\n setPowerSyncInstance(db);\n setPowerSyncSyncStatus(syncStatus);\n }} onSyncStatusChange={syncStatus_0 => {\n setPowerSyncSyncStatus(syncStatus_0);\n }} onAddPendingMutationReady={add => {\n addPendingMutationRef.current = add;\n }} onRemovePendingMutationReady={remove => {\n removePendingMutationRef.current = remove;\n }}>{children}</ProviderBridge></PowerSyncProvider></PowerSyncErrorBoundary>;\n };\n let t34;\n if ($[100] !== dataLayer.config || $[101] !== effectiveSyncStatus || $[102] !== onError || $[103] !== platform.logger || $[104] !== powerSyncInstance || $[105] !== queryClient || $[106] !== supabaseClient || $[107] !== syncControl) {\n t34 = content => {\n const {\n DataLayerProvider\n } = require(\"@pol-studios/db\");\n return <DataLayerProvider config={dataLayer.config} powerSyncInstance={powerSyncInstance} supabaseClient={supabaseClient} queryClient={queryClient} powerSyncSyncStatus={effectiveSyncStatus} syncControl={syncControl} onInitialized={() => {\n platform.logger.info(\"Data layer initialized\");\n }} onError={err_0 => {\n platform.logger.error(\"Data layer error:\", err_0);\n onError?.(err_0);\n }}>{content}</DataLayerProvider>;\n };\n $[100] = dataLayer.config;\n $[101] = effectiveSyncStatus;\n $[102] = onError;\n $[103] = platform.logger;\n $[104] = powerSyncInstance;\n $[105] = queryClient;\n $[106] = supabaseClient;\n $[107] = syncControl;\n $[108] = t34;\n } else {\n t34 = $[108];\n }\n const renderWithDataLayer = t34;\n if (dataLayer && !dataLayer.skip) {\n t33 = renderWithDataLayer(renderContent());\n break bb2;\n }\n t32 = renderContent();\n }\n $[75] = backgroundSync;\n $[76] = children;\n $[77] = dataLayer;\n $[78] = effectiveSyncStatus;\n $[79] = errorFallback;\n $[80] = handleBackgroundSyncSystemReady;\n $[81] = handlePowerSyncError;\n $[82] = handleRetry;\n $[83] = initError;\n $[84] = onError;\n $[85] = onReady;\n $[86] = platform.logger;\n $[87] = powerSyncConfig;\n $[88] = powerSyncInstance;\n $[89] = powerSyncUrl;\n $[90] = queryClient;\n $[91] = renderError;\n $[92] = renderInitError;\n $[93] = retryKey;\n $[94] = skipConflictProvider;\n $[95] = skipStorageQueueProvider;\n $[96] = supabaseClient;\n $[97] = syncControl;\n $[98] = t32;\n $[99] = t33;\n } else {\n t32 = $[98];\n t33 = $[99];\n }\n if (t33 !== Symbol.for(\"react.early_return_sentinel\")) {\n return t33;\n }\n return t32;\n}\nfunction _temp(prev) {\n return prev + 1;\n}\nexport default OfflineDataProvider;","/**\n * ProviderBridge Component for @pol-studios/powersync\n *\n * Internal bridge component that connects PowerSync context to external providers:\n * - DataLayerProvider from @pol-studios/db\n * - ConflictProvider from @pol-studios/db\n * - StorageQueueProvider from @pol-studios/db\n *\n * This component is used internally by OfflineDataProvider and should not be\n * exported directly. It handles the complex wiring between packages.\n */\n\nimport React, { ReactNode, useCallback, useEffect, useMemo, useRef } from 'react';\nimport { PowerSyncContext, AbstractPowerSyncDatabase } from '@powersync/react-native';\nimport type { CrudEntry } from '../core/types';\nimport type { ProviderBridgeProps, PowerSyncSyncStatusSnapshot, BackgroundSyncStatus } from './OfflineDataProvider.types';\nimport type { BackgroundSyncSystem } from '../sync/background-sync';\nimport { usePowerSync, useSyncStatus, useOnlineStatus, usePendingMutationsContext } from './hooks';\n\n/**\n * ProviderBridge connects the PowerSync package context to external providers\n * like ConflictProvider and StorageQueueProvider from @pol-studios/db.\n *\n * This component:\n * 1. Signals the parent when the db is ready (onDbReady)\n * 2. Reports sync status changes (onSyncStatusChange)\n * 3. Exposes pending mutation functions to parent (for DataLayerProvider)\n * 4. Sets up background sync system when enabled\n * 5. Wraps children with ConflictProvider and StorageQueueProvider\n * 6. Exposes PowerSync db via native PowerSyncContext for SDK hooks\n *\n * IMPORTANT: DataLayerProvider is rendered OUTSIDE this component (in OfflineDataProvider)\n * so it always exists in the React tree even before PowerSync is ready.\n * This prevents \"useDataLayer must be used within a DataLayerProvider\" errors\n * when routes mount before the db is initialized.\n *\n * CRITICAL: The conflictBus is created internally by PowerSyncProvider and\n * passed to the connector. We MUST use the same bus instance from context\n * for ConflictProvider, otherwise conflicts detected by the connector won't\n * reach the UI components subscribed via ConflictProvider.\n */\nexport function ProviderBridge({\n children,\n skipConflictProvider = false,\n skipStorageQueueProvider = false,\n backgroundSync,\n onBackgroundSyncSystemReady,\n onDbReady,\n onSyncStatusChange,\n onAddPendingMutationReady,\n onRemovePendingMutationReady\n}: ProviderBridgeProps): React.ReactElement | null {\n const {\n db,\n attachmentQueue,\n isReady,\n attachmentQueueReady,\n conflictBus,\n platform\n } = usePowerSync();\n const {\n status: syncStatus\n } = useSyncStatus();\n const {\n addPendingMutation,\n removePendingMutation\n } = usePendingMutationsContext();\n // Get online status from PowerSync's platform adapter (uses NetInfo on React Native)\n // This is the single source of truth for network connectivity\n const isOnline = useOnlineStatus();\n\n // Refs to track callbacks and readiness so effects don't need them as deps\n const onDbReadyRef = useRef(onDbReady);\n const onSyncStatusChangeRef = useRef(onSyncStatusChange);\n useEffect(() => {\n onDbReadyRef.current = onDbReady;\n }, [onDbReady]);\n useEffect(() => {\n onSyncStatusChangeRef.current = onSyncStatusChange;\n }, [onSyncStatusChange]);\n\n // Track whether we've already signalled readiness to avoid calling onDbReady multiple times\n const hasSignalledReady = useRef(false);\n\n // Signal parent with pending mutation functions once ready\n // These are CRITICAL for SyncTrackingAdapter to work correctly\n useEffect(() => {\n if (!isReady) return;\n platform.logger.debug('[ProviderBridge] Passing pending mutation functions to parent');\n onAddPendingMutationReady(addPendingMutation);\n onRemovePendingMutationReady(removePendingMutation);\n }, [isReady, addPendingMutation, removePendingMutation, onAddPendingMutationReady, onRemovePendingMutationReady, platform]);\n\n // Signal parent with db instance once ready\n useEffect(() => {\n if (!isReady || !db) return;\n const snapshot: PowerSyncSyncStatusSnapshot = {\n hasSynced: syncStatus.hasSynced,\n connected: syncStatus.connected,\n connecting: syncStatus.connecting,\n isOnline\n };\n if (!hasSignalledReady.current) {\n hasSignalledReady.current = true;\n onDbReadyRef.current(db, snapshot);\n } else {\n onSyncStatusChangeRef.current(snapshot);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isReady, db, syncStatus.hasSynced, syncStatus.connected, syncStatus.connecting, isOnline]);\n\n // Set up background sync system when db is ready and background sync is enabled\n useEffect(() => {\n if (!isReady || !db || !backgroundSync?.enabled) return;\n\n // Create BackgroundSyncSystem adapter for background sync\n const backgroundSystem: BackgroundSyncSystem = {\n init: async () => {\n // Already initialized via normal flow\n if (!db.connected) {\n // Note: db.connect() requires a connector, but in background mode\n // the db should already be initialized from the foreground session\n platform.logger.info('[Background Sync] DB not connected, waiting for connection...');\n }\n },\n disconnect: async () => {\n await db.disconnect();\n },\n isConnected: () => db.connected,\n getDatabase: () => db,\n onStatusChange: (callback: (status: BackgroundSyncStatus) => void) => {\n return db.registerListener({\n statusChanged: (status: {\n lastSyncedAt?: Date | null;\n dataFlowStatus?: {\n downloading?: boolean;\n uploading?: boolean;\n };\n }) => {\n callback({\n lastSyncedAt: status.lastSyncedAt ?? null,\n downloading: status.dataFlowStatus?.downloading ?? false,\n uploading: status.dataFlowStatus?.uploading ?? false\n });\n }\n });\n }\n };\n\n // Signal parent that background sync system is ready\n onBackgroundSyncSystemReady?.(backgroundSystem);\n\n // Cleanup: signal parent that system is no longer available on unmount\n return () => {\n onBackgroundSyncSystemReady?.(null as unknown as BackgroundSyncSystem);\n };\n }, [isReady, db, backgroundSync?.enabled, onBackgroundSyncSystemReady, platform]);\n\n // Don't render until PowerSync is ready\n if (!isReady) {\n return null; // Or a loading spinner - DataLayerProvider is still mounted above\n }\n\n // Build the provider tree based on skip flags\n let content: ReactNode = children;\n\n // Wrap with StorageQueueProvider if not skipped\n if (!skipStorageQueueProvider) {\n // Dynamically import to avoid hard dependency\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const {\n StorageQueueProvider\n } = require('@pol-studios/db');\n content = <StorageQueueProvider attachmentQueue={attachmentQueue} isReady={attachmentQueueReady}>\n {content}\n </StorageQueueProvider>;\n }\n\n // Wrap with ConflictProvider if not skipped\n if (!skipConflictProvider) {\n // Dynamically import to avoid hard dependency\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const {\n ConflictProvider\n } = require('@pol-studios/db');\n content = <ConflictProvider conflictBus={conflictBus}>\n {content}\n </ConflictProvider>;\n }\n\n // Wrap with native PowerSyncContext for SDK hooks to work\n // Note: Using 'as any' because our AbstractPowerSyncDatabase is a subset interface,\n // but the SDK's PowerSyncContext expects the full @powersync/common type\n if (db) {\n return (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n <PowerSyncContext.Provider value={db as any}>\n {content}\n </PowerSyncContext.Provider>\n );\n }\n return <>{content}</>;\n}\nexport default ProviderBridge;"],"mappings":"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","names":["useEffect","useRef","useState","useEffect","useRef","PowerSyncContext","jsx","useRef","useEffect","PowerSyncContext","Fragment","jsx","useState","useRef","t6","t19","t20","t21","t22","useEffect"]}
@@ -1,11 +0,0 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
- export {
9
- __require
10
- };
11
- //# sourceMappingURL=chunk-DGUM43GV.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/storage/upload/SupabaseUploadHandler.native.ts"],"sourcesContent":["/**\n * Supabase Upload Handler for React Native\n *\n * Implements UploadHandler interface using react-native-background-upload\n * for iOS background upload capability.\n */\n\nimport { Platform } from 'react-native';\nimport type { StorageUploadHandler, BucketConfig } from '../types';\nimport { resolveBucketFromConfig } from '../types';\nimport type { SupabaseUploadHandlerOptions, UploadNotificationConfig } from './types';\nimport { DEFAULT_UPLOAD_NOTIFICATION } from './types';\n\n// Lazy-loaded module reference\nlet Upload: typeof import('react-native-background-upload').default | null = null;\n\n/**\n * Load react-native-background-upload lazily.\n * This prevents the module from being bundled on web.\n */\nasync function loadUploadModule(): Promise<typeof import('react-native-background-upload').default> {\n if (!Upload) {\n const module = await import('react-native-background-upload');\n Upload = module.default;\n }\n return Upload;\n}\n\n/**\n * React Native upload handler using react-native-background-upload.\n *\n * Features:\n * - iOS background upload support\n * - AbortSignal cancellation support\n * - Android notification support\n * - Signed URL-based uploads\n *\n * @example\n * ```typescript\n * const handler = createSupabaseUploadHandler(supabaseClient, {\n * defaultBucket: 'attachments',\n * bucketMap: new Map([['avatars/', 'user-avatars']]),\n * });\n *\n * await handler.uploadFile(\n * 'photos/image.jpg',\n * 'file:///path/to/image.jpg',\n * 'image/jpeg'\n * );\n * ```\n */\nexport class SupabaseUploadHandler implements StorageUploadHandler {\n private supabase: any;\n private bucketConfig: BucketConfig;\n private notificationConfig: UploadNotificationConfig;\n constructor(options: SupabaseUploadHandlerOptions, notificationConfig?: Partial<UploadNotificationConfig>) {\n this.supabase = options.supabaseClient;\n this.bucketConfig = options.bucketConfig;\n this.notificationConfig = {\n ...DEFAULT_UPLOAD_NOTIFICATION,\n ...notificationConfig\n };\n }\n\n /**\n * Upload a file to Supabase Storage using react-native-background-upload.\n * Supports iOS background uploads and AbortSignal for cancellation.\n */\n async uploadFile(storagePath: string, localFileUri: string, mediaType: string, signal?: AbortSignal): Promise<void> {\n // Check if already aborted\n if (signal?.aborted) {\n throw new DOMException('Operation aborted', 'AbortError');\n }\n const bucket = this.resolveBucket(storagePath);\n\n // 1. Get signed upload URL from Supabase\n const {\n data,\n error\n } = await this.supabase.storage.from(bucket).createSignedUploadUrl(storagePath);\n if (error || !data?.signedUrl) {\n throw new Error(error?.message || 'Failed to create signed upload URL');\n }\n\n // Check abort after async operation\n if (signal?.aborted) {\n throw new DOMException('Operation aborted', 'AbortError');\n }\n\n // Load the upload module\n const UploadModule = await loadUploadModule();\n\n // 2. Upload using react-native-background-upload\n return new Promise((resolve, reject) => {\n const uploadId = `upload_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n let isSettled = false;\n\n // Setup listeners before starting\n const completedSub = UploadModule.addListener('completed', uploadId, (eventData: {\n responseCode: number;\n }) => {\n if (isSettled) return;\n isSettled = true;\n cleanup();\n if (eventData.responseCode >= 200 && eventData.responseCode < 300) {\n resolve();\n } else {\n reject(new Error(`Upload failed with status ${eventData.responseCode}`));\n }\n });\n const errorSub = UploadModule.addListener('error', uploadId, (eventData: {\n error: string;\n }) => {\n if (isSettled) return;\n isSettled = true;\n cleanup();\n reject(new Error(eventData.error));\n });\n const cancelledSub = UploadModule.addListener('cancelled', uploadId, () => {\n if (isSettled) return;\n isSettled = true;\n cleanup();\n reject(new DOMException('Operation aborted', 'AbortError'));\n });\n const cleanup = () => {\n completedSub.remove();\n errorSub.remove();\n cancelledSub.remove();\n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n };\n\n // Register abort handler to cancel the upload\n const abortHandler = () => {\n if (isSettled) return;\n UploadModule.cancelUpload(uploadId).catch(() => {\n // Ignore errors when cancelling - the upload may have already completed\n });\n };\n if (signal) {\n signal.addEventListener('abort', abortHandler, {\n once: true\n });\n }\n\n // Determine platform for notification settings\n const isAndroid = Platform.OS === 'android';\n\n // Start the upload\n UploadModule.startUpload({\n url: data.signedUrl,\n path: localFileUri,\n method: 'PUT',\n type: 'raw',\n customUploadId: uploadId,\n headers: {\n 'Content-Type': mediaType\n },\n // Android notification settings\n ...(isAndroid && {\n notification: this.notificationConfig\n })\n }).catch((err: Error) => {\n if (isSettled) return;\n isSettled = true;\n cleanup();\n reject(err);\n });\n });\n }\n\n /**\n * Resolve the storage bucket for a given path.\n */\n resolveBucket(storagePath: string): string {\n return resolveBucketFromConfig(this.bucketConfig, storagePath);\n }\n}\n\n/**\n * Factory function for creating a SupabaseUploadHandler.\n */\nexport function createSupabaseUploadHandler(supabaseClient: any, bucketConfig: BucketConfig, notificationConfig?: Partial<UploadNotificationConfig>): SupabaseUploadHandler {\n return new SupabaseUploadHandler({\n supabaseClient,\n bucketConfig\n }, notificationConfig);\n}"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- //# sourceMappingURL=chunk-GKF7TOMT.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/provider/types.ts","../src/sync/status-tracker.ts","../src/sync/metrics-collector.ts","../src/sync/health-monitor.ts"],"sourcesContent":["/**\n * Provider Types for @pol-studios/powersync\n *\n * Defines configuration and context interfaces for the PowerSyncProvider.\n */\n\nimport type { SupabaseClient } from '@supabase/supabase-js';\nimport type { QueryClient } from '@tanstack/react-query';\nimport type { AbstractPowerSyncDatabase, SyncStatus, ConnectionHealth, SyncMetrics, CrudEntry, FailedTransaction, CompletedTransaction, SyncMode, DownloadProgress } from '../core/types';\nimport type { PlatformAdapter } from '../platform/types';\nimport type { ConnectorConfig } from '../connector/types';\nimport type { PolAttachmentQueueConfig } from '../attachments/types';\nimport type { PolAttachmentQueue } from '../attachments/pol-attachment-queue';\nimport type { SupabaseConnector } from '../connector/supabase-connector';\nimport type { ConflictBus } from '../conflicts/conflict-bus';\n\n// ─── Provider Configuration ──────────────────────────────────────────────────\n\n/**\n * Main configuration for PowerSyncProvider.\n *\n * @template TSchema - The PowerSync schema type\n *\n * @example\n * ```typescript\n * const config: PowerSyncConfig<AppSchema> = {\n * platform: createNativePlatformAdapter(logger),\n * schema: AppSchema,\n * powerSyncUrl: 'https://your-powersync-instance.com',\n * supabaseClient: supabase,\n * dbFilename: 'myapp.db',\n * sync: {\n * autoConnect: true,\n * },\n * };\n * ```\n */\nexport interface PowerSyncConfig<TSchema = unknown> {\n /**\n * Platform adapter for platform-specific operations.\n * Use createNativePlatformAdapter() for React Native or createWebPlatformAdapter() for Web.\n */\n platform: PlatformAdapter;\n\n /**\n * PowerSync schema definition.\n * This defines the tables and their structure for the local database.\n */\n schema: TSchema;\n\n /**\n * PowerSync service URL.\n * @example \"https://your-instance.powersync.journeyapps.com\"\n */\n powerSyncUrl: string;\n\n /**\n * Supabase client instance.\n * Used for authentication and as the backend for CRUD uploads.\n */\n supabaseClient: SupabaseClient;\n\n /**\n * Optional: TanStack Query client for cache invalidation.\n * If provided, will invalidate queries when sync completes.\n */\n queryClient?: QueryClient;\n\n /**\n * Optional: Database filename.\n * @default \"powersync.db\"\n */\n dbFilename?: string;\n\n /**\n * Optional: Connector configuration for custom CRUD handling.\n */\n connector?: ConnectorConfig;\n\n /**\n * Optional: Attachment queue configuration for offline file caching.\n *\n * @example\n * ```typescript\n * attachments: {\n * source: { table: 'photos', idColumn: 'storage_path' },\n * remoteStorage: supabaseStorageAdapter,\n * }\n * ```\n */\n attachments?: PolAttachmentQueueConfig;\n\n /**\n * Optional: Sync behavior configuration.\n */\n sync?: SyncConfig;\n}\n\n/**\n * Sync behavior configuration.\n */\nexport interface SyncConfig {\n /**\n * Automatically connect when the provider mounts and there's an authenticated session.\n * @default true\n */\n autoConnect?: boolean;\n\n /**\n * Sync interval for periodic sync checks (in milliseconds).\n * Set to 0 to disable periodic sync.\n * @default 0 (disabled)\n */\n syncInterval?: number;\n\n /**\n * Enable health monitoring.\n * @default true\n */\n enableHealthMonitoring?: boolean;\n\n /**\n * Enable metrics collection.\n * @default true\n */\n enableMetrics?: boolean;\n}\n\n// ─── Context Types ───────────────────────────────────────────────────────────\n\n/**\n * Value provided by the main PowerSyncContext.\n *\n * @template TSchema - The PowerSync schema type\n */\nexport interface PowerSyncContextValue<TSchema = unknown> {\n /**\n * The PowerSync database instance.\n * Will be null if not initialized or if initialization failed.\n */\n db: AbstractPowerSyncDatabase | null;\n\n /**\n * The Supabase connector instance.\n * Will be null if not initialized.\n */\n connector: SupabaseConnector | null;\n\n /**\n * The attachment queue instance.\n * Will be null if attachments are not configured or not initialized.\n */\n attachmentQueue: PolAttachmentQueue | null;\n\n /**\n * Whether the PowerSync database is ready for use.\n */\n isReady: boolean;\n\n /**\n * Whether the provider is currently initializing.\n */\n isInitializing: boolean;\n\n /**\n * Whether the attachment queue is ready for use.\n * This is separate from isReady because the attachment queue initializes\n * asynchronously after the database is ready.\n *\n * States:\n * - `false`: Attachment queue is still initializing\n * - `true` with `attachmentQueue !== null`: Ready and available\n * - `true` with `attachmentQueue === null`: Either attachments not configured, OR initialization failed\n */\n attachmentQueueReady: boolean;\n\n /**\n * Error that occurred during initialization, if any.\n */\n error: Error | null;\n\n /**\n * The schema used for this database.\n */\n schema: TSchema;\n\n /**\n * The platform adapter instance.\n */\n platform: PlatformAdapter;\n\n /**\n * The conflict bus for subscribing to conflict events.\n * Use this to wire up conflict UI components.\n */\n conflictBus: ConflictBus;\n}\n\n/**\n * Value provided by SyncStatusContext.\n */\nexport interface SyncStatusContextValue {\n /**\n * Current sync status.\n */\n status: SyncStatus;\n\n /**\n * Pending mutations waiting to be uploaded.\n */\n pendingMutations: CrudEntry[];\n\n /**\n * Number of pending mutations.\n */\n pendingCount: number;\n\n /**\n * Whether data is currently being uploaded to the server.\n * This is the authoritative source for upload activity.\n */\n isUploading: boolean;\n\n /**\n * Whether data is currently being downloaded from the server.\n * This is the authoritative source for download activity.\n */\n isDownloading: boolean;\n\n /**\n * Whether sync is currently paused (offline mode).\n */\n isPaused: boolean;\n\n /**\n * Current sync mode: 'push-pull' (full sync), 'pull-only' (download only), or 'offline' (no sync).\n */\n syncMode: SyncMode;\n\n /**\n * Timestamp of the last successful sync.\n */\n lastSyncedAt: Date | null;\n\n /**\n * Error that occurred during connection, if any.\n */\n connectionError: Error | null;\n\n /**\n * Failed transactions that need attention.\n */\n failedTransactions: FailedTransaction[];\n\n /**\n * Whether there are any upload errors.\n */\n hasUploadErrors: boolean;\n\n /**\n * Count of permanent errors that need user action.\n */\n permanentErrorCount: number;\n\n /**\n * Clear a specific failure by its ID.\n */\n clearFailure: (failureId: string) => void;\n\n /**\n * Clear all failures.\n */\n clearAllFailures: () => void;\n\n /**\n * Completed transactions history.\n */\n completedTransactions: CompletedTransaction[];\n\n /**\n * Clear the completed transaction history.\n */\n clearCompletedHistory: () => void;\n\n /**\n * Set the sync mode.\n * @param mode - The sync mode to set\n */\n setSyncMode: (mode: SyncMode) => Promise<void>;\n\n /**\n * Set the force next upload flag.\n * When true, the next sync cycle will upload regardless of sync mode.\n */\n setForceNextUpload: (force: boolean) => void;\n\n /**\n * Discard a specific pending mutation by its client ID.\n * Uses safe disconnect/reconnect pattern to avoid transaction conflicts.\n * @throws Error if upload is in progress\n */\n discardPendingMutation: (clientId: number) => Promise<void>;\n\n /**\n * Discard all pending mutations.\n * Uses safe disconnect/reconnect pattern to avoid transaction conflicts.\n * @throws Error if upload is in progress\n */\n discardAllPendingMutations: () => Promise<void>;\n\n /**\n * Pause automatic retry of failed uploads.\n * Useful when user is actively resolving conflicts.\n */\n pauseAutoRetry: () => void;\n\n /**\n * Resume automatic retry of failed uploads.\n */\n resumeAutoRetry: () => void;\n}\n\n// ─── Split Context Types (Performance Optimization) ─────────────────────────\n// These focused contexts allow components to subscribe to only the data they need,\n// preventing re-renders when unrelated data changes.\n\n/**\n * Connection state - changes rarely (on connect/disconnect).\n * Use this for components that only need to display connection status.\n */\nexport interface ConnectionStatusContextValue {\n /** Whether connected to the PowerSync service */\n connected: boolean;\n /** Whether currently attempting to connect */\n connecting: boolean;\n /** Whether initial sync has completed */\n hasSynced: boolean;\n /** Timestamp of last successful sync */\n lastSyncedAt: Date | null;\n /** Error that occurred during connection, if any */\n connectionError: Error | null;\n}\n\n/**\n * Sync activity - changes during active sync.\n * Use this for components that display sync progress.\n */\nexport interface SyncActivityContextValue {\n /** Whether data is currently being uploaded to the server */\n uploading: boolean;\n /** Whether data is currently being downloaded from the server */\n downloading: boolean;\n /** Download progress details */\n downloadProgress: DownloadProgress | null;\n}\n\n/**\n * Pending mutations - changes on local writes.\n * Use this for components that display pending upload count or list.\n */\nexport interface PendingMutationsContextValue {\n /** Pending mutations waiting to be uploaded */\n pendingMutations: CrudEntry[];\n /** Number of pending mutations */\n pendingCount: number;\n /** Discard a specific pending mutation by its client ID */\n discardPendingMutation: (clientId: number) => Promise<void>;\n /** Discard all pending mutations */\n discardAllPendingMutations: () => Promise<void>;\n /**\n * Add a pending mutation to the list.\n * Called by mutation hooks (useDbInsert, useDbUpdate, useDbDelete, useDbUpsert)\n * after a successful write. Includes createdAt timestamp for display.\n */\n addPendingMutation: (entry: CrudEntry) => void;\n /**\n * Remove a pending mutation by its entity ID.\n * Called when a transaction completes sync.\n */\n removePendingMutation: (id: string) => void;\n}\n\n/**\n * Failed transactions - changes on failures.\n * Use this for components that display sync errors.\n */\nexport interface FailedTransactionsContextValue {\n /** Failed transactions that need attention */\n failedTransactions: FailedTransaction[];\n /** Whether there are any upload errors */\n hasUploadErrors: boolean;\n /** Count of permanent errors that need user action */\n permanentErrorCount: number;\n /** Clear a specific failure by its ID */\n clearFailure: (failureId: string) => void;\n /** Clear all failures */\n clearAllFailures: () => void;\n /** Pause automatic retry of failed uploads */\n pauseAutoRetry: () => void;\n /** Resume automatic retry of failed uploads */\n resumeAutoRetry: () => void;\n /**\n * Retry a specific failed transaction.\n *\n * This removes the failure from tracking and triggers a sync.\n * The actual CRUD entries remain in PowerSync's queue - this just\n * clears our error tracking so the sync can retry them.\n *\n * If the sync fails to start, the failure is re-recorded.\n */\n retryFailure: (failureId: string) => Promise<void>;\n}\n\n/**\n * Completed transactions - changes on successful syncs.\n * Use this for components that display sync history.\n */\nexport interface CompletedTransactionsContextValue {\n /** Recently completed transactions */\n completedTransactions: CompletedTransaction[];\n /** Clear the completed transaction history */\n clearCompletedHistory: () => void;\n /** Clear a specific completed transaction by ID */\n clearCompletedItem: (completedId: string) => void;\n /**\n * Completed transactions that occurred AFTER the last notification display.\n * Use this for toast/banner notifications to avoid showing stale historical counts.\n */\n newCompletedTransactions: CompletedTransaction[];\n /**\n * Mark notifications as seen (updates the lastNotificationTime).\n * Call this when a sync notification is displayed or auto-dismissed.\n */\n markNotificationsAsSeen: () => void;\n}\n\n/**\n * Sync mode control - changes rarely (user action).\n * Use this for components that display/control sync mode.\n */\nexport interface SyncModeContextValue {\n /** Current sync mode */\n syncMode: SyncMode;\n /** Whether sync is currently paused (offline mode) */\n isPaused: boolean;\n /**\n * Whether offline mode was automatically set due to network loss.\n * When true, sync will auto-resume when network returns.\n * When false (user manually chose offline), sync won't auto-resume.\n */\n isAutoOffline: boolean;\n /**\n * Whether the network is currently reachable.\n * This is used as a gate to block uploads even when syncMode is 'push-pull'.\n */\n networkReachable: boolean;\n /** Set the sync mode (manual - won't auto-resume) */\n setSyncMode: (mode: SyncMode) => Promise<void>;\n /** Set the force next upload flag */\n setForceNextUpload: (force: boolean) => void;\n}\n\n/**\n * Value provided by ConnectionHealthContext.\n */\nexport interface ConnectionHealthContextValue {\n /**\n * Current connection health status.\n */\n health: ConnectionHealth;\n}\n\n/**\n * Value provided by SyncMetricsContext.\n */\nexport interface SyncMetricsContextValue {\n /**\n * Current sync metrics.\n */\n metrics: SyncMetrics;\n}\n\n// ─── Provider Props ──────────────────────────────────────────────────────────\n\n/**\n * Props for the PowerSyncProvider component.\n *\n * @template TSchema - The PowerSync schema type\n */\nexport interface PowerSyncProviderProps<TSchema = unknown> {\n /**\n * PowerSync configuration.\n */\n config: PowerSyncConfig<TSchema>;\n\n /**\n * Child components to render.\n */\n children: React.ReactNode;\n\n /**\n * Called when the database is initialized and ready.\n */\n onReady?: () => void;\n\n /**\n * Called when an error occurs during initialization.\n */\n onError?: (error: Error) => void;\n\n /**\n * Called when sync status changes.\n */\n onSyncStatusChange?: (status: SyncStatus) => void;\n}\n\n// ─── Default Values ──────────────────────────────────────────────────────────\n\n/**\n * Default sync status.\n */\nexport const DEFAULT_SYNC_STATUS: SyncStatus = {\n connected: false,\n connecting: false,\n hasSynced: false,\n lastSyncedAt: null,\n uploading: false,\n downloading: false,\n downloadProgress: null,\n failedTransactions: [],\n hasUploadErrors: false,\n permanentErrorCount: 0\n};\n\n/**\n * Default connection health.\n */\nexport const DEFAULT_CONNECTION_HEALTH: ConnectionHealth = {\n status: 'disconnected',\n latency: null,\n lastHealthCheck: null,\n consecutiveFailures: 0,\n reconnectAttempts: 0\n};\n\n/**\n * Default sync metrics.\n */\nexport const DEFAULT_SYNC_METRICS: SyncMetrics = {\n totalSyncs: 0,\n successfulSyncs: 0,\n failedSyncs: 0,\n lastSyncDuration: null,\n averageSyncDuration: null,\n totalDataDownloaded: 0,\n totalDataUploaded: 0,\n lastError: null\n};\n\n/**\n * Default sync configuration.\n */\nexport const DEFAULT_SYNC_CONFIG: Required<SyncConfig> = {\n autoConnect: true,\n syncInterval: 0,\n enableHealthMonitoring: true,\n enableMetrics: true\n};","/**\n * Sync Status Tracker for @pol-studios/powersync\n *\n * Tracks and normalizes PowerSync status changes, providing a consistent\n * interface for status updates with throttling support.\n */\n\nimport type { SyncStatus, DownloadProgress, CrudEntry, FailedTransaction, SyncError, CompletedTransaction, SyncMode } from '../core/types';\nimport { generateFailureId } from '../core/errors';\nimport type { LoggerAdapter, AsyncStorageAdapter } from '../platform/types';\nimport type { SyncStatusState, SyncStatusTrackerOptions, PowerSyncRawStatus, Unsubscribe } from './types';\nimport { STORAGE_KEY_PAUSED, STORAGE_KEY_SYNC_MODE, STORAGE_KEY_AUTO_OFFLINE, STATUS_NOTIFY_THROTTLE_MS } from '../core/constants';\nconst STORAGE_KEY_COMPLETED_TRANSACTIONS = '@pol-powersync:completed_transactions';\nconst STORAGE_KEY_FAILED_TRANSACTIONS = '@pol-powersync:failed_transactions';\nimport { DEFAULT_SYNC_STATUS } from '../provider/types';\n\n/**\n * Tracks sync status from PowerSync and provides normalized updates.\n *\n * Features:\n * - Normalizes raw PowerSync status to a consistent format\n * - Throttles notifications to prevent UI thrashing\n * - Tracks pending mutations count\n * - Persists and restores paused state\n *\n * @example\n * ```typescript\n * const tracker = new SyncStatusTracker({\n * storage,\n * logger,\n * onStatusChange: (status) => console.log('Status:', status),\n * });\n *\n * // Register with PowerSync\n * db.registerListener({\n * statusChanged: (rawStatus) => tracker.handleStatusChange(rawStatus),\n * });\n *\n * // Get current status\n * const status = tracker.getStatus();\n * ```\n */\nexport class SyncStatusTracker {\n private readonly storage: AsyncStorageAdapter;\n private readonly logger: LoggerAdapter;\n private readonly notifyThrottleMs: number;\n private readonly onStatusChange?: (status: SyncStatus) => void;\n private _state: SyncStatusState;\n private _pendingMutations: CrudEntry[] = [];\n private _lastNotifyTime = 0;\n private _notifyTimer: ReturnType<typeof setTimeout> | null = null;\n private _listeners = new Set<(status: SyncStatus) => void>();\n private _syncModeListeners = new Set<(mode: SyncMode) => void>();\n\n // Force next upload flag for \"Sync Now\" functionality\n private _forceNextUpload = false;\n\n // Network reachability gate - blocks uploads instantly when network is unreachable\n private _networkReachable = true;\n private _networkRestoreTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly _networkRestoreDelayMs = 1500; // 1.5 seconds delay before restoring\n\n // Debounce timer for persist operations to avoid race conditions\n private _persistDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Track download progress separately to preserve it when offline\n private _lastProgress: DownloadProgress | null = null;\n\n // Failed transaction tracking\n private _failedTransactions: FailedTransaction[] = [];\n private readonly _maxStoredFailures = 50;\n private readonly _failureTTLMs = 24 * 60 * 60 * 1000; // 24 hours\n private _failureListeners = new Set<(failures: FailedTransaction[]) => void>();\n\n // Completed transaction tracking (no limit - full audit trail)\n private _completedTransactions: CompletedTransaction[] = [];\n private _completedListeners = new Set<(completed: CompletedTransaction[]) => void>();\n\n // Track when notifications were last displayed/dismissed for \"auto-dismiss on display\"\n // This allows filtering completed transactions to only show new ones since last display\n private _lastNotificationTime: number = Date.now();\n\n // Auto-offline flag: tracks whether offline mode was set automatically (network loss)\n // vs manually (user chose offline). Persisted so auto-restore works after app restart.\n private _isAutoOffline = false;\n constructor(storage: AsyncStorageAdapter, logger: LoggerAdapter, options: SyncStatusTrackerOptions = {}) {\n this.storage = storage;\n this.logger = logger;\n this.notifyThrottleMs = options.notifyThrottleMs ?? STATUS_NOTIFY_THROTTLE_MS;\n this.onStatusChange = options.onStatusChange;\n this._state = {\n status: {\n ...DEFAULT_SYNC_STATUS\n },\n syncMode: 'push-pull',\n lastUpdated: new Date()\n };\n }\n\n // ─── Initialization ────────────────────────────────────────────────────────\n\n /**\n * Initialize the tracker by loading persisted state.\n * Includes migration from old isPaused boolean to new syncMode.\n */\n async init(): Promise<void> {\n try {\n // Try to load new sync mode first\n const modeValue = await this.storage.getItem(STORAGE_KEY_SYNC_MODE);\n if (modeValue && ['push-pull', 'pull-only', 'offline'].includes(modeValue)) {\n this._state.syncMode = modeValue as SyncMode;\n this.logger.debug('[StatusTracker] Loaded sync mode:', this._state.syncMode);\n } else {\n // Migrate from old isPaused boolean\n const pausedValue = await this.storage.getItem(STORAGE_KEY_PAUSED);\n if (pausedValue === 'true') {\n this._state.syncMode = 'offline';\n await this.storage.setItem(STORAGE_KEY_SYNC_MODE, 'offline');\n this.logger.debug('[StatusTracker] Migrated isPaused=true to syncMode=offline');\n } else {\n this._state.syncMode = 'push-pull';\n }\n // Clean up old key\n await this.storage.removeItem(STORAGE_KEY_PAUSED);\n }\n } catch (err) {\n this.logger.warn('[StatusTracker] Failed to load sync mode:', err);\n }\n\n // Load persisted auto-offline flag\n try {\n const autoOfflineValue = await this.storage.getItem(STORAGE_KEY_AUTO_OFFLINE);\n this._isAutoOffline = autoOfflineValue === 'true';\n this.logger.debug('[StatusTracker] Loaded isAutoOffline:', this._isAutoOffline);\n } catch (err) {\n this.logger.warn('[StatusTracker] Failed to load auto-offline flag:', err);\n }\n\n // Load persisted completed transactions\n try {\n const completedJson = await this.storage.getItem(STORAGE_KEY_COMPLETED_TRANSACTIONS);\n if (completedJson) {\n const parsed = JSON.parse(completedJson) as Array<Omit<CompletedTransaction, 'completedAt'> & {\n completedAt: string;\n }>;\n this._completedTransactions = parsed.map(item => {\n const remappedEntries = item.entries.map(e => this.remapEntry(e)).filter((e): e is CrudEntry => e !== null);\n return {\n ...item,\n completedAt: new Date(item.completedAt),\n entries: remappedEntries\n };\n }).filter(item => !isNaN(item.completedAt.getTime()) && item.entries.length > 0);\n this.logger.debug('[StatusTracker] Loaded', this._completedTransactions.length, 'completed transactions');\n }\n } catch (err) {\n this.logger.warn('[StatusTracker] Failed to load completed transactions:', err);\n }\n\n // Load persisted failed transactions\n try {\n const failedJson = await this.storage.getItem(STORAGE_KEY_FAILED_TRANSACTIONS);\n if (failedJson) {\n const parsed = JSON.parse(failedJson) as Array<Omit<FailedTransaction, 'firstFailedAt' | 'lastFailedAt' | 'error'> & {\n firstFailedAt: string;\n lastFailedAt: string;\n error: Omit<SyncError, 'timestamp'> & {\n timestamp: string;\n };\n }>;\n this._failedTransactions = parsed.map(item => {\n const remappedEntries = item.entries.map(e => this.remapEntry(e)).filter((e): e is CrudEntry => e !== null);\n return {\n ...item,\n firstFailedAt: new Date(item.firstFailedAt),\n lastFailedAt: new Date(item.lastFailedAt),\n error: {\n ...item.error,\n timestamp: new Date(item.error.timestamp)\n },\n entries: remappedEntries\n };\n }).filter(item => !isNaN(item.firstFailedAt.getTime()) && !isNaN(item.lastFailedAt.getTime()) && item.entries.length > 0);\n this.logger.debug('[StatusTracker] Loaded', this._failedTransactions.length, 'failed transactions');\n }\n } catch (err) {\n this.logger.warn('[StatusTracker] Failed to load failed transactions:', err);\n }\n\n // Clean up any stale failures that were persisted\n this.cleanupStaleFailures();\n }\n\n /**\n * Dispose the tracker and clear timers.\n */\n dispose(): void {\n if (this._notifyTimer) {\n clearTimeout(this._notifyTimer);\n this._notifyTimer = null;\n }\n if (this._persistDebounceTimer) {\n clearTimeout(this._persistDebounceTimer);\n this._persistDebounceTimer = null;\n }\n if (this._networkRestoreTimer) {\n clearTimeout(this._networkRestoreTimer);\n this._networkRestoreTimer = null;\n }\n this._listeners.clear();\n this._syncModeListeners.clear();\n this._failureListeners.clear();\n this._completedListeners.clear();\n }\n\n // ─── Status Getters ────────────────────────────────────────────────────────\n\n /**\n * Get the current sync status.\n */\n getStatus(): SyncStatus {\n const baseStatus = this._state.status;\n\n // Build the status with failed transaction info\n const status: SyncStatus = {\n ...baseStatus,\n failedTransactions: this._failedTransactions,\n hasUploadErrors: this._failedTransactions.length > 0,\n permanentErrorCount: this._failedTransactions.filter(f => f.isPermanent).length\n };\n\n // If offline, use saved progress instead of live (which would be null)\n if (this._state.syncMode === 'offline' && this._lastProgress) {\n return {\n ...status,\n downloadProgress: this._lastProgress\n };\n }\n return status;\n }\n\n // ─── Sync Mode Getters ────────────────────────────────────────────────────────\n\n /**\n * Get the current sync mode.\n */\n getSyncMode(): SyncMode {\n return this._state.syncMode;\n }\n\n /**\n * Check if uploads are allowed based on current sync mode and network reachability.\n */\n canUpload(): boolean {\n return this._networkReachable && this._state.syncMode === 'push-pull';\n }\n\n /**\n * Check if downloads are allowed based on current sync mode.\n */\n canDownload(): boolean {\n return this._state.syncMode !== 'offline';\n }\n\n /**\n * Set the force next upload flag for \"Sync Now\" functionality.\n */\n setForceNextUpload(force: boolean): void {\n this._forceNextUpload = force;\n this.logger.debug('[StatusTracker] Force next upload set to:', force);\n }\n\n /**\n * Clear the force next upload flag.\n * Should be called after all pending uploads have been processed.\n */\n clearForceNextUpload(): void {\n if (this._forceNextUpload) {\n this._forceNextUpload = false;\n this.logger.debug('[StatusTracker] Force next upload flag cleared');\n }\n }\n\n /**\n * Check if upload should proceed, considering force flag and network reachability.\n * NOTE: Does NOT auto-reset the flag - caller must use clearForceNextUpload()\n * after all uploads are complete. This prevents race conditions when\n * PowerSync calls uploadData() multiple times for multiple transactions.\n */\n shouldUpload(): boolean {\n // Force flag bypasses all gates (user explicitly requested sync)\n if (this._forceNextUpload) {\n return true;\n }\n // Network gate - instant block when unreachable (0ms, no timeouts)\n if (!this._networkReachable) {\n return false;\n }\n return this._state.syncMode === 'push-pull';\n }\n\n /**\n * Set network reachability state.\n * - When unreachable: Instantly blocks uploads (0ms)\n * - When reachable: Delayed restore (1-2 seconds) to avoid flickering on brief disconnects\n */\n setNetworkReachable(reachable: boolean): void {\n // Clear any pending restore timer\n if (this._networkRestoreTimer) {\n clearTimeout(this._networkRestoreTimer);\n this._networkRestoreTimer = null;\n }\n if (!reachable) {\n // Instant block when network becomes unreachable\n if (this._networkReachable) {\n this._networkReachable = false;\n this.logger.debug('[StatusTracker] Network unreachable - uploads blocked instantly');\n }\n } else {\n // Delayed restore when network becomes reachable\n if (!this._networkReachable) {\n this.logger.debug('[StatusTracker] Network reachable - scheduling delayed restore');\n this._networkRestoreTimer = setTimeout(() => {\n this._networkRestoreTimer = null;\n this._networkReachable = true;\n this.logger.debug('[StatusTracker] Network restored - uploads enabled');\n }, this._networkRestoreDelayMs);\n }\n }\n }\n\n /**\n * Get current network reachability state.\n */\n isNetworkReachable(): boolean {\n return this._networkReachable;\n }\n\n /**\n * Get pending mutations.\n */\n getPendingMutations(): CrudEntry[] {\n return this._pendingMutations;\n }\n\n /**\n * Get pending mutation count.\n */\n getPendingCount(): number {\n return this._pendingMutations.length;\n }\n\n // ─── Status Updates ────────────────────────────────────────────────────────\n\n /**\n * Handle a raw status update from PowerSync.\n */\n handleStatusChange(rawStatus: PowerSyncRawStatus): void {\n const progress = rawStatus.downloadProgress;\n const dataFlow = rawStatus.dataFlowStatus;\n\n // Build normalized download progress\n let downloadProgress: DownloadProgress | null = null;\n if (progress && progress.totalOperations && progress.totalOperations > 0) {\n downloadProgress = {\n current: progress.downloadedOperations ?? 0,\n target: progress.totalOperations,\n percentage: Math.round((progress.downloadedFraction ?? 0) * 100)\n };\n // Save progress for when paused\n this._lastProgress = downloadProgress;\n }\n\n // Build normalized status (failed transaction fields are added in getStatus())\n const newStatus: SyncStatus = {\n connected: rawStatus.connected ?? false,\n connecting: rawStatus.connecting ?? false,\n hasSynced: rawStatus.hasSynced ?? false,\n lastSyncedAt: rawStatus.lastSyncedAt ?? null,\n uploading: dataFlow?.uploading ?? false,\n downloading: dataFlow?.downloading ?? false,\n downloadProgress,\n // These are computed from _failedTransactions in getStatus()\n failedTransactions: [],\n hasUploadErrors: false,\n permanentErrorCount: 0\n };\n\n // Check if status actually changed\n const changed = this._hasStatusChanged(newStatus);\n this._state = {\n status: newStatus,\n syncMode: this._state.syncMode,\n lastUpdated: new Date()\n };\n if (changed) {\n this._notifyListeners();\n }\n }\n\n /**\n * Update pending mutations from a CRUD transaction.\n */\n updatePendingMutations(mutations: CrudEntry[]): void {\n this._pendingMutations = mutations;\n }\n\n /**\n * Valid sync modes for runtime validation.\n */\n private static readonly VALID_SYNC_MODES: SyncMode[] = ['push-pull', 'pull-only', 'offline'];\n\n /**\n * Set the sync mode.\n */\n async setSyncMode(mode: SyncMode): Promise<void> {\n // Runtime validation\n if (!SyncStatusTracker.VALID_SYNC_MODES.includes(mode)) {\n this.logger.warn('[StatusTracker] Invalid sync mode, ignoring:', mode);\n return;\n }\n if (this._state.syncMode === mode) return;\n const previousMode = this._state.syncMode;\n this._state.syncMode = mode;\n\n // Persist to storage\n try {\n await this.storage.setItem(STORAGE_KEY_SYNC_MODE, mode);\n this.logger.info('[StatusTracker] Sync mode changed:', previousMode, '->', mode);\n } catch (err) {\n this.logger.warn('[StatusTracker] Failed to persist sync mode:', err);\n }\n\n // Notify sync mode listeners\n for (const listener of this._syncModeListeners) {\n try {\n listener(mode);\n } catch (err) {\n this.logger.warn('[StatusTracker] Sync mode listener error:', err);\n }\n }\n this._notifyListeners(true);\n }\n\n // ─── Auto-Offline Management ──────────────────────────────────────────────\n\n /**\n * Get whether offline mode was set automatically (network loss) vs manually.\n * Used to determine if sync should auto-resume when network returns.\n */\n getIsAutoOffline(): boolean {\n return this._isAutoOffline;\n }\n\n /**\n * Set the auto-offline flag and persist it.\n * @param isAuto - true if offline was set automatically, false if user chose offline\n */\n async setIsAutoOffline(isAuto: boolean): Promise<void> {\n if (this._isAutoOffline === isAuto) return;\n this._isAutoOffline = isAuto;\n\n // Persist to storage\n try {\n await this.storage.setItem(STORAGE_KEY_AUTO_OFFLINE, isAuto ? 'true' : 'false');\n this.logger.debug('[StatusTracker] Auto-offline flag changed:', isAuto);\n } catch (err) {\n this.logger.warn('[StatusTracker] Failed to persist auto-offline flag:', err);\n }\n }\n\n // ─── Subscriptions ─────────────────────────────────────────────────────────\n\n /**\n * Subscribe to status changes.\n * @returns Unsubscribe function\n */\n onStatusUpdate(listener: (status: SyncStatus) => void): Unsubscribe {\n this._listeners.add(listener);\n // Immediately call with current status\n listener(this.getStatus());\n return () => {\n this._listeners.delete(listener);\n };\n }\n\n /**\n * Subscribe to sync mode changes.\n * @returns Unsubscribe function\n */\n onSyncModeChange(listener: (mode: SyncMode) => void): Unsubscribe {\n this._syncModeListeners.add(listener);\n listener(this._state.syncMode);\n return () => {\n this._syncModeListeners.delete(listener);\n };\n }\n\n // ─── Failed Transaction Tracking ────────────────────────────────────────────\n\n /**\n * Record a transaction failure.\n * If a failure for the same entries already exists, updates the retry count.\n * Otherwise, creates a new failure record.\n *\n * @param preserveMetadata - Optional. If provided, preserves retryCount and firstFailedAt from a previous failure.\n */\n recordTransactionFailure(entries: CrudEntry[], error: SyncError, isPermanent: boolean, affectedEntityIds: string[], affectedTables: string[], preserveMetadata?: {\n retryCount: number;\n firstFailedAt: Date;\n }): void {\n const now = new Date();\n\n // Normalize entries to plain objects to avoid CrudEntry.toJSON() remapping issues\n const normalizedEntries = this.normalizeEntries(entries);\n const entryIds = normalizedEntries.map(e => e.id).sort().join(',');\n\n // Check if a failure for these entries already exists\n const existingIndex = this._failedTransactions.findIndex(f => {\n const existingIds = f.entries.map(e => e.id).sort().join(',');\n return existingIds === entryIds;\n });\n if (existingIndex !== -1) {\n // Update existing failure\n const existing = this._failedTransactions[existingIndex];\n this._failedTransactions[existingIndex] = {\n ...existing,\n error,\n retryCount: existing.retryCount + 1,\n lastFailedAt: now,\n isPermanent\n };\n } else {\n // Create new failure record\n const newFailure: FailedTransaction = {\n id: generateFailureId(normalizedEntries),\n entries: normalizedEntries,\n error,\n retryCount: preserveMetadata?.retryCount ?? 1,\n firstFailedAt: preserveMetadata?.firstFailedAt ?? now,\n lastFailedAt: now,\n isPermanent,\n affectedEntityIds,\n affectedTables\n };\n this._failedTransactions.push(newFailure);\n\n // Enforce max stored failures (remove oldest)\n if (this._failedTransactions.length > this._maxStoredFailures) {\n this._failedTransactions.sort((a, b) => a.firstFailedAt.getTime() - b.firstFailedAt.getTime());\n this._failedTransactions = this._failedTransactions.slice(-this._maxStoredFailures);\n }\n }\n this._schedulePersist();\n this._notifyFailureListeners();\n this._notifyListeners();\n }\n\n /**\n * Clear a specific failure by ID.\n */\n clearFailure(failureId: string): void {\n const initialLength = this._failedTransactions.length;\n this._failedTransactions = this._failedTransactions.filter(f => f.id !== failureId);\n if (this._failedTransactions.length !== initialLength) {\n this._schedulePersist();\n this._notifyFailureListeners();\n this._notifyListeners();\n }\n }\n\n /**\n * Clear all failures.\n */\n clearAllFailures(): void {\n if (this._failedTransactions.length === 0) return;\n this._failedTransactions = [];\n this._schedulePersist();\n this._notifyFailureListeners();\n this._notifyListeners();\n }\n\n /**\n * Remove a failed transaction from tracking and return its entries.\n * This is a \"pop\" operation - the failure is removed from the list.\n *\n * Note: The actual CRUD entries remain in PowerSync's ps_crud table\n * until successfully uploaded. This just removes from our tracking.\n *\n * @param failureId - The failure ID to remove\n * @returns The CrudEntry[] that were in the failure, or null if not found\n */\n takeFailureForRetry(failureId: string): CrudEntry[] | null {\n const failure = this._failedTransactions.find(f => f.id === failureId);\n if (!failure) {\n this.logger.warn('[StatusTracker] Failure not found for retry:', failureId);\n return null;\n }\n\n // Remove from failed list\n this._failedTransactions = this._failedTransactions.filter(f => f.id !== failureId);\n this._notifyFailureListeners();\n this._schedulePersist();\n this.logger.info('[StatusTracker] Retrieved failure for retry:', failureId, 'entries:', failure.entries.length);\n return failure.entries;\n }\n\n /**\n * Get failures affecting a specific entity.\n */\n getFailuresForEntity(entityId: string): FailedTransaction[] {\n return this._failedTransactions.filter(f => f.affectedEntityIds.includes(entityId));\n }\n\n /**\n * Get all failed transactions.\n */\n getFailedTransactions(): FailedTransaction[] {\n return [...this._failedTransactions];\n }\n\n /**\n * Check if there are any upload errors.\n */\n hasUploadErrors(): boolean {\n return this._failedTransactions.length > 0;\n }\n\n /**\n * Get count of permanent errors.\n */\n getPermanentErrorCount(): number {\n return this._failedTransactions.filter(f => f.isPermanent).length;\n }\n\n /**\n * Subscribe to failure changes.\n * @returns Unsubscribe function\n */\n onFailureChange(listener: (failures: FailedTransaction[]) => void): Unsubscribe {\n this._failureListeners.add(listener);\n // Immediately call with current failures\n listener(this.getFailedTransactions());\n return () => {\n this._failureListeners.delete(listener);\n };\n }\n\n /**\n * Clean up stale failures (older than TTL).\n */\n cleanupStaleFailures(): void {\n const cutoff = Date.now() - this._failureTTLMs;\n const initialLength = this._failedTransactions.length;\n this._failedTransactions = this._failedTransactions.filter(f => f.lastFailedAt.getTime() > cutoff);\n if (this._failedTransactions.length !== initialLength) {\n this.logger.debug(`[StatusTracker] Cleaned up ${initialLength - this._failedTransactions.length} stale failures`);\n this._schedulePersist();\n this._notifyFailureListeners();\n this._notifyListeners();\n }\n }\n\n // ─── Completed Transaction Tracking ────────────────────────────────────────\n\n /**\n * Record a successfully completed transaction.\n * Creates a CompletedTransaction record and adds it to history.\n */\n recordTransactionComplete(entries: CrudEntry[]): void {\n // Normalize entries to plain objects to avoid CrudEntry.toJSON() remapping issues\n const normalizedEntries = this.normalizeEntries(entries);\n\n // Extract unique affected tables\n const affectedTables = [...new Set(normalizedEntries.map(e => e.table))];\n\n // Extract unique affected entity IDs\n const affectedEntityIds = [...new Set(normalizedEntries.map(e => e.id))];\n\n // Generate unique ID\n const id = `completed_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;\n const completed: CompletedTransaction = {\n id,\n entries: normalizedEntries,\n completedAt: new Date(),\n affectedTables,\n affectedEntityIds\n };\n\n // Add to front of array (most recent first)\n this._completedTransactions.unshift(completed);\n\n // No limit on completed history - user wants full audit trail\n\n this._schedulePersist();\n this._notifyCompletedListeners();\n this.logger.debug(`[StatusTracker] Recorded completed transaction: ${completed.id} (${entries.length} entries)`);\n }\n\n /**\n * Get all completed transactions.\n */\n getCompletedTransactions(): CompletedTransaction[] {\n return [...this._completedTransactions];\n }\n\n /**\n * Clear completed transaction history.\n */\n clearCompletedHistory(): void {\n if (this._completedTransactions.length === 0) return;\n this._completedTransactions = [];\n this._schedulePersist();\n this._notifyCompletedListeners();\n this.logger.debug('[StatusTracker] Cleared completed transaction history');\n }\n\n /**\n * Clear a specific completed transaction by ID.\n */\n clearCompletedItem(completedId: string): void {\n const initialLength = this._completedTransactions.length;\n this._completedTransactions = this._completedTransactions.filter(c => c.id !== completedId);\n if (this._completedTransactions.length !== initialLength) {\n this._schedulePersist();\n this._notifyCompletedListeners();\n this.logger.debug('[StatusTracker] Cleared completed transaction:', completedId);\n }\n }\n\n /**\n * Subscribe to completed transaction changes.\n * @returns Unsubscribe function\n */\n onCompletedChange(listener: (completed: CompletedTransaction[]) => void): Unsubscribe {\n this._completedListeners.add(listener);\n // Immediately call with current completed transactions\n listener(this.getCompletedTransactions());\n return () => {\n this._completedListeners.delete(listener);\n };\n }\n\n // ─── Notification Tracking ─────────────────────────────────────────────────\n\n /**\n * Get completed transactions that occurred AFTER the last notification time.\n * This is used for displaying \"X changes synced\" notifications to avoid\n * showing stale counts from historical completed transactions.\n */\n getNewCompletedTransactions(): CompletedTransaction[] {\n return this._completedTransactions.filter(tx => tx.completedAt.getTime() > this._lastNotificationTime);\n }\n\n /**\n * Mark notifications as seen by updating the last notification time.\n * Call this when the notification is displayed or dismissed.\n */\n markNotificationsAsSeen(): void {\n this._lastNotificationTime = Date.now();\n this.logger.debug('[StatusTracker] Notifications marked as seen');\n // Notify listeners so UI can update (newCompletedTransactions will now be empty)\n this._notifyCompletedListeners();\n }\n\n /**\n * Get the timestamp of when notifications were last displayed/dismissed.\n */\n getLastNotificationTime(): number {\n return this._lastNotificationTime;\n }\n\n // ─── Private Methods ───────────────────────────────────────────────────────\n\n /**\n * Schedule a debounced persist operation.\n * This prevents race conditions from multiple rapid persist calls.\n */\n private _schedulePersist(): void {\n if (this._persistDebounceTimer) {\n clearTimeout(this._persistDebounceTimer);\n }\n this._persistDebounceTimer = setTimeout(() => {\n this._persistDebounceTimer = null;\n this._persistTransactions();\n }, 100); // 100ms debounce\n }\n\n /**\n * Persist completed and failed transactions to storage.\n */\n private async _persistTransactions(): Promise<void> {\n try {\n await Promise.all([this.storage.setItem(STORAGE_KEY_COMPLETED_TRANSACTIONS, JSON.stringify(this._completedTransactions)), this.storage.setItem(STORAGE_KEY_FAILED_TRANSACTIONS, JSON.stringify(this._failedTransactions))]);\n } catch (err) {\n this.logger.warn('[StatusTracker] Failed to persist transactions:', err);\n }\n }\n private _hasStatusChanged(newStatus: SyncStatus): boolean {\n const old = this._state.status;\n return old.connected !== newStatus.connected || old.connecting !== newStatus.connecting || old.hasSynced !== newStatus.hasSynced || old.uploading !== newStatus.uploading || old.downloading !== newStatus.downloading || old.lastSyncedAt?.getTime() !== newStatus.lastSyncedAt?.getTime() || old.downloadProgress?.current !== newStatus.downloadProgress?.current || old.downloadProgress?.target !== newStatus.downloadProgress?.target;\n }\n\n /**\n * Notify all listeners of status changes with throttling.\n *\n * Uses a \"dirty\" flag pattern: when throttled, we schedule a timer\n * but get the CURRENT state when the timer fires, not the stale state\n * from when the timer was scheduled. This ensures rapid state changes\n * during the throttle window aren't lost.\n */\n private _notifyListeners(forceImmediate = false): void {\n const now = Date.now();\n const timeSinceLastNotify = now - this._lastNotifyTime;\n\n // If a timer is already scheduled, don't reschedule - just let it fire\n // and it will pick up the current (latest) state at that time\n if (this._notifyTimer && !forceImmediate) {\n return; // Already scheduled, will get current state when it fires\n }\n if (this._notifyTimer) {\n clearTimeout(this._notifyTimer);\n this._notifyTimer = null;\n }\n const notify = () => {\n this._notifyTimer = null;\n this._lastNotifyTime = Date.now();\n // Get CURRENT state at notification time, not stale state\n const status = this.getStatus();\n\n // Call the main callback\n this.onStatusChange?.(status);\n\n // Call all listeners\n for (const listener of this._listeners) {\n try {\n listener(status);\n } catch (err) {\n this.logger.warn('[StatusTracker] Listener error:', err);\n }\n }\n };\n if (forceImmediate || timeSinceLastNotify >= this.notifyThrottleMs) {\n notify();\n } else {\n const delayMs = this.notifyThrottleMs - timeSinceLastNotify;\n this._notifyTimer = setTimeout(notify, delayMs);\n }\n }\n private _notifyFailureListeners(): void {\n const failures = this.getFailedTransactions();\n for (const listener of this._failureListeners) {\n try {\n listener(failures);\n } catch (err) {\n this.logger.warn('[StatusTracker] Failure listener error:', err);\n }\n }\n }\n private _notifyCompletedListeners(): void {\n const completed = this.getCompletedTransactions();\n for (const listener of this._completedListeners) {\n try {\n listener(completed);\n } catch (err) {\n this.logger.warn('[StatusTracker] Completed listener error:', err);\n }\n }\n }\n\n /**\n * Remap a CrudEntry from persisted JSON (handles toJSON() property remapping).\n * PowerSync's CrudEntry.toJSON() remaps: opData→data, table→type, clientId→op_id, transactionId→tx_id\n *\n * @returns The remapped CrudEntry, or null if critical fields (table, id) are missing\n */\n private remapEntry(entry: any): CrudEntry | null {\n const table = entry.table ?? entry.type;\n const id = entry.id;\n\n // Validate critical fields\n if (!table || typeof table !== 'string') {\n this.logger.warn('[StatusTracker] Invalid CrudEntry: missing or invalid table field', entry);\n return null;\n }\n if (!id || typeof id !== 'string') {\n this.logger.warn('[StatusTracker] Invalid CrudEntry: missing or invalid id field', entry);\n return null;\n }\n return {\n id,\n clientId: entry.clientId ?? entry.op_id ?? 0,\n op: entry.op,\n table,\n opData: entry.opData ?? entry.data,\n transactionId: entry.transactionId ?? entry.tx_id\n };\n }\n\n /**\n * Normalize CrudEntry array to plain objects to avoid CrudEntry.toJSON() remapping issues.\n * PowerSync's CrudEntry.toJSON() remaps property names which breaks deserialization.\n */\n private normalizeEntries(entries: CrudEntry[]): CrudEntry[] {\n return entries.map(e => ({\n id: e.id,\n clientId: e.clientId,\n op: e.op,\n table: e.table,\n opData: e.opData,\n transactionId: e.transactionId\n }));\n }\n}","/**\n * Sync Metrics Collector for @pol-studios/powersync\n *\n * Collects and persists sync operation metrics for monitoring and debugging.\n */\n\nimport type { SyncMetrics, SyncError, SyncErrorType } from '../core/types';\nimport type { AsyncStorageAdapter, LoggerAdapter } from '../platform/types';\nimport type { MetricsCollectorOptions, SyncOperationData, Unsubscribe } from './types';\nimport { STORAGE_KEY_METRICS } from '../core/constants';\nimport { classifyError } from '../core/errors';\nimport { DEFAULT_SYNC_METRICS } from '../provider/types';\n\n/**\n * Collects sync metrics including operation counts, timing, and errors.\n *\n * Features:\n * - Tracks sync operation success/failure rates\n * - Calculates average sync duration\n * - Monitors data transfer amounts\n * - Persists metrics to storage for continuity across sessions\n * - Records last error for debugging\n *\n * @example\n * ```typescript\n * const collector = new MetricsCollector({\n * storage,\n * logger,\n * onMetricsChange: (metrics) => updateUI(metrics),\n * });\n *\n * // Start tracking a sync\n * const startTime = Date.now();\n *\n * // On sync complete\n * collector.recordSync({\n * durationMs: Date.now() - startTime,\n * success: true,\n * operationsDownloaded: 150,\n * });\n *\n * // Get current metrics\n * const metrics = collector.getMetrics();\n * ```\n */\nexport class MetricsCollector {\n private readonly storage: AsyncStorageAdapter;\n private readonly logger: LoggerAdapter;\n private readonly storageKey: string;\n private readonly persistMetrics: boolean;\n private readonly onMetricsChange?: (metrics: SyncMetrics) => void;\n private _metrics: SyncMetrics;\n private _listeners = new Set<(metrics: SyncMetrics) => void>();\n private _initialized = false;\n\n // Track active sync for timing\n private _syncStartTime: number | null = null;\n private _wasSyncing = false;\n constructor(storage: AsyncStorageAdapter, logger: LoggerAdapter, options: MetricsCollectorOptions = {}) {\n this.storage = storage;\n this.logger = logger;\n this.storageKey = options.storageKey ?? STORAGE_KEY_METRICS;\n this.persistMetrics = options.persistMetrics ?? true;\n this.onMetricsChange = options.onMetricsChange;\n this._metrics = {\n ...DEFAULT_SYNC_METRICS\n };\n }\n\n // ─── Initialization ────────────────────────────────────────────────────────\n\n /**\n * Initialize the collector by loading persisted metrics.\n */\n async init(): Promise<void> {\n if (this._initialized) return;\n try {\n const stored = await this.storage.getItem(this.storageKey);\n if (stored) {\n const parsed = JSON.parse(stored);\n // Restore Date objects\n if (parsed.lastError?.timestamp) {\n parsed.lastError.timestamp = new Date(parsed.lastError.timestamp);\n }\n this._metrics = {\n ...DEFAULT_SYNC_METRICS,\n ...parsed\n };\n this.logger.debug('[MetricsCollector] Loaded persisted metrics');\n }\n } catch (err) {\n this.logger.warn('[MetricsCollector] Failed to load metrics:', err);\n }\n this._initialized = true;\n }\n\n /**\n * Dispose the collector.\n */\n dispose(): void {\n this._listeners.clear();\n }\n\n // ─── Getters ───────────────────────────────────────────────────────────────\n\n /**\n * Get current sync metrics.\n */\n getMetrics(): SyncMetrics {\n return {\n ...this._metrics\n };\n }\n\n // ─── Recording ─────────────────────────────────────────────────────────────\n\n /**\n * Record a completed sync operation.\n */\n async recordSync(data: SyncOperationData): Promise<void> {\n const {\n durationMs,\n success,\n operationsDownloaded,\n operationsUploaded,\n error\n } = data;\n const totalSyncs = this._metrics.totalSyncs + 1;\n const successfulSyncs = this._metrics.successfulSyncs + (success ? 1 : 0);\n const failedSyncs = this._metrics.failedSyncs + (success ? 0 : 1);\n\n // Calculate running average duration (only for successful syncs)\n let averageSyncDuration = this._metrics.averageSyncDuration;\n if (success) {\n if (averageSyncDuration !== null) {\n averageSyncDuration = (averageSyncDuration * (successfulSyncs - 1) + durationMs) / successfulSyncs;\n } else {\n averageSyncDuration = durationMs;\n }\n }\n\n // Estimate data transfer (rough approximation: ~100 bytes per operation)\n const bytesPerOp = 100;\n const downloaded = (operationsDownloaded ?? 0) * bytesPerOp;\n const uploaded = (operationsUploaded ?? 0) * bytesPerOp;\n\n // Build error record if failed\n let lastError: SyncError | null = this._metrics.lastError;\n if (!success && error) {\n const errorType = classifyError(error);\n lastError = {\n type: errorType,\n message: error.message,\n userMessage: error.message,\n // Use original message as user message for metrics\n timestamp: new Date(),\n isPermanent: false\n };\n }\n this._metrics = {\n totalSyncs,\n successfulSyncs,\n failedSyncs,\n lastSyncDuration: durationMs,\n averageSyncDuration: averageSyncDuration !== null ? Math.round(averageSyncDuration) : null,\n totalDataDownloaded: this._metrics.totalDataDownloaded + downloaded,\n totalDataUploaded: this._metrics.totalDataUploaded + uploaded,\n lastError\n };\n await this._persist();\n this._notifyListeners();\n }\n\n /**\n * Record a sync error without a full sync operation.\n */\n async recordError(error: Error): Promise<void> {\n this._metrics = {\n ...this._metrics,\n failedSyncs: this._metrics.failedSyncs + 1,\n lastError: {\n type: classifyError(error),\n message: error.message,\n userMessage: error.message,\n // Use original message as user message for metrics\n timestamp: new Date(),\n isPermanent: false\n }\n };\n await this._persist();\n this._notifyListeners();\n }\n\n /**\n * Record an upload operation.\n */\n async recordUpload(operationCount: number): Promise<void> {\n const bytesPerOp = 100;\n this._metrics = {\n ...this._metrics,\n totalDataUploaded: this._metrics.totalDataUploaded + operationCount * bytesPerOp\n };\n await this._persist();\n this._notifyListeners();\n }\n\n /**\n * Clear all metrics and start fresh.\n */\n async reset(): Promise<void> {\n this._metrics = {\n ...DEFAULT_SYNC_METRICS\n };\n await this._persist();\n this._notifyListeners();\n }\n\n // ─── Sync Timing Helpers ───────────────────────────────────────────────────\n\n /**\n * Called when sync starts (downloading becomes true).\n */\n markSyncStart(): void {\n if (!this._wasSyncing) {\n this._syncStartTime = Date.now();\n this._wasSyncing = true;\n }\n }\n\n /**\n * Called when sync ends (downloading becomes false).\n * Returns the duration if a sync was in progress.\n */\n markSyncEnd(): number | null {\n if (this._wasSyncing && this._syncStartTime !== null) {\n const duration = Date.now() - this._syncStartTime;\n this._syncStartTime = null;\n this._wasSyncing = false;\n return duration;\n }\n return null;\n }\n\n /**\n * Check if sync is currently in progress.\n */\n isSyncInProgress(): boolean {\n return this._wasSyncing;\n }\n\n // ─── Subscriptions ─────────────────────────────────────────────────────────\n\n /**\n * Subscribe to metrics changes.\n * @returns Unsubscribe function\n */\n onMetricsUpdate(listener: (metrics: SyncMetrics) => void): Unsubscribe {\n this._listeners.add(listener);\n listener(this.getMetrics());\n return () => {\n this._listeners.delete(listener);\n };\n }\n\n // ─── Private Methods ───────────────────────────────────────────────────────\n\n private async _persist(): Promise<void> {\n if (!this.persistMetrics) return;\n try {\n await this.storage.setItem(this.storageKey, JSON.stringify(this._metrics));\n } catch (err) {\n this.logger.warn('[MetricsCollector] Failed to persist metrics:', err);\n }\n }\n private _notifyListeners(): void {\n const metrics = this.getMetrics();\n\n // Call main callback\n this.onMetricsChange?.(metrics);\n\n // Call all listeners\n for (const listener of this._listeners) {\n try {\n listener(metrics);\n } catch (err) {\n this.logger.warn('[MetricsCollector] Listener error:', err);\n }\n }\n }\n}","/**\n * Connection Health Monitor for @pol-studios/powersync\n *\n * Monitors database connection health with periodic checks and latency tracking.\n */\n\nimport type { ConnectionHealth } from '../core/types';\nimport type { AbstractPowerSyncDatabase } from '../core/types';\nimport type { LoggerAdapter } from '../platform/types';\nimport type { HealthMonitorOptions, HealthCheckResult, Unsubscribe } from './types';\nimport { HEALTH_CHECK_INTERVAL_MS, HEALTH_CHECK_TIMEOUT_MS, LATENCY_DEGRADED_THRESHOLD_MS, MAX_CONSECUTIVE_FAILURES } from '../core/constants';\nimport { DEFAULT_CONNECTION_HEALTH } from '../provider/types';\n\n/**\n * Monitors connection health with periodic checks.\n *\n * Features:\n * - Periodic health checks with configurable interval\n * - Latency measurement and degraded state detection\n * - Consecutive failure tracking\n * - Auto-recovery detection\n *\n * @example\n * ```typescript\n * const monitor = new HealthMonitor(db, logger, {\n * checkIntervalMs: 30000,\n * onHealthChange: (health) => {\n * if (health.status === 'degraded') {\n * showWarning('Connection is slow');\n * }\n * },\n * });\n *\n * // Start monitoring\n * monitor.start();\n *\n * // Get current health\n * const health = monitor.getHealth();\n *\n * // Stop when done\n * monitor.stop();\n * ```\n */\nexport class HealthMonitor {\n private readonly logger: LoggerAdapter;\n private readonly checkIntervalMs: number;\n private readonly checkTimeoutMs: number;\n private readonly degradedThresholdMs: number;\n private readonly maxConsecutiveFailures: number;\n private readonly onHealthChange?: (health: ConnectionHealth) => void;\n private _db: AbstractPowerSyncDatabase | null = null;\n private _health: ConnectionHealth;\n private _intervalId: ReturnType<typeof setInterval> | null = null;\n private _listeners = new Set<(health: ConnectionHealth) => void>();\n private _running = false;\n private _paused = false;\n private _pendingTimers = new Set<ReturnType<typeof setTimeout>>();\n constructor(logger: LoggerAdapter, options: HealthMonitorOptions = {}) {\n this.logger = logger;\n this.checkIntervalMs = options.checkIntervalMs ?? HEALTH_CHECK_INTERVAL_MS;\n this.checkTimeoutMs = options.checkTimeoutMs ?? HEALTH_CHECK_TIMEOUT_MS;\n this.degradedThresholdMs = options.degradedThresholdMs ?? LATENCY_DEGRADED_THRESHOLD_MS;\n this.maxConsecutiveFailures = options.maxConsecutiveFailures ?? MAX_CONSECUTIVE_FAILURES;\n this.onHealthChange = options.onHealthChange;\n this._health = {\n ...DEFAULT_CONNECTION_HEALTH\n };\n }\n\n // ─── Lifecycle ─────────────────────────────────────────────────────────────\n\n /**\n * Set the database instance to monitor.\n */\n setDatabase(db: AbstractPowerSyncDatabase | null): void {\n this._db = db;\n if (!db) {\n // Reset health when database is cleared\n this._updateHealth({\n status: 'disconnected',\n latency: null,\n lastHealthCheck: new Date(),\n consecutiveFailures: 0,\n reconnectAttempts: this._health.reconnectAttempts\n });\n }\n }\n\n /**\n * Start the health monitor.\n */\n start(): void {\n if (this._running) return;\n this.logger.info('[HealthMonitor] Starting');\n this._running = true;\n\n // Perform initial check\n this._checkHealth().catch(err => {\n this.logger.warn('[HealthMonitor] Initial check error:', err);\n });\n\n // Set up periodic checks\n this._intervalId = setInterval(() => {\n if (!this._paused) {\n this._checkHealth().catch(err => {\n this.logger.warn('[HealthMonitor] Periodic check error:', err);\n });\n }\n }, this.checkIntervalMs);\n }\n\n /**\n * Stop the health monitor.\n */\n stop(): void {\n if (!this._running) return;\n this.logger.info('[HealthMonitor] Stopping');\n this._running = false;\n if (this._intervalId) {\n clearInterval(this._intervalId);\n this._intervalId = null;\n }\n }\n\n /**\n * Pause health checks temporarily.\n */\n pause(): void {\n this._paused = true;\n // Clear any pending timeout timers to prevent leaks\n this._pendingTimers.forEach(clearTimeout);\n this._pendingTimers.clear();\n this._updateHealth({\n ...this._health,\n status: 'disconnected'\n });\n }\n\n /**\n * Resume health checks.\n */\n resume(): void {\n this._paused = false;\n // Perform immediate check on resume\n this._checkHealth().catch(err => {\n this.logger.warn('[HealthMonitor] Resume check error:', err);\n });\n }\n\n /**\n * Dispose the monitor and clear all resources.\n */\n dispose(): void {\n this.stop();\n // Clear any pending timeout timers to prevent leaks\n this._pendingTimers.forEach(clearTimeout);\n this._pendingTimers.clear();\n this._listeners.clear();\n }\n\n // ─── Getters ───────────────────────────────────────────────────────────────\n\n /**\n * Get current connection health.\n */\n getHealth(): ConnectionHealth {\n return {\n ...this._health\n };\n }\n\n /**\n * Check if the monitor is running.\n */\n isRunning(): boolean {\n return this._running;\n }\n\n // ─── Manual Checks ─────────────────────────────────────────────────────────\n\n /**\n * Perform an immediate health check.\n * @returns The result of the health check\n */\n async checkNow(): Promise<HealthCheckResult> {\n return this._checkHealth();\n }\n\n /**\n * Record a reconnection attempt.\n */\n recordReconnectAttempt(): void {\n this._updateHealth({\n ...this._health,\n reconnectAttempts: this._health.reconnectAttempts + 1\n });\n }\n\n /**\n * Reset reconnection attempts counter (call on successful connection).\n */\n resetReconnectAttempts(): void {\n if (this._health.reconnectAttempts > 0) {\n this._updateHealth({\n ...this._health,\n reconnectAttempts: 0\n });\n }\n }\n\n // ─── Subscriptions ─────────────────────────────────────────────────────────\n\n /**\n * Subscribe to health changes.\n * @returns Unsubscribe function\n */\n onHealthUpdate(listener: (health: ConnectionHealth) => void): Unsubscribe {\n this._listeners.add(listener);\n listener(this.getHealth());\n return () => {\n this._listeners.delete(listener);\n };\n }\n\n // ─── Private Methods ───────────────────────────────────────────────────────\n\n private async _checkHealth(): Promise<HealthCheckResult> {\n if (!this._db || this._paused) {\n return {\n success: false,\n error: new Error('Database not available or paused'),\n timestamp: new Date()\n };\n }\n const startTime = Date.now();\n const timestamp = new Date();\n try {\n // Execute a simple query with timeout\n await this._withTimeout(this._db.get('SELECT 1'), this.checkTimeoutMs);\n const latencyMs = Date.now() - startTime;\n\n // Determine status based on latency\n const status: ConnectionHealth['status'] = latencyMs < this.degradedThresholdMs ? 'healthy' : 'degraded';\n this._updateHealth({\n status,\n latency: latencyMs,\n lastHealthCheck: timestamp,\n consecutiveFailures: 0,\n reconnectAttempts: this._health.reconnectAttempts\n });\n return {\n success: true,\n latencyMs,\n timestamp\n };\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n this.logger.warn('[HealthMonitor] Health check failed:', error.message);\n const consecutiveFailures = this._health.consecutiveFailures + 1;\n const status: ConnectionHealth['status'] = consecutiveFailures >= this.maxConsecutiveFailures ? 'disconnected' : 'degraded';\n this._updateHealth({\n status,\n latency: null,\n lastHealthCheck: timestamp,\n consecutiveFailures,\n reconnectAttempts: this._health.reconnectAttempts\n });\n return {\n success: false,\n error,\n timestamp\n };\n }\n }\n private _updateHealth(health: ConnectionHealth): void {\n const changed = this._hasHealthChanged(health);\n this._health = health;\n if (changed) {\n this._notifyListeners();\n }\n }\n private _hasHealthChanged(newHealth: ConnectionHealth): boolean {\n const old = this._health;\n return old.status !== newHealth.status || old.latency !== newHealth.latency || old.consecutiveFailures !== newHealth.consecutiveFailures || old.reconnectAttempts !== newHealth.reconnectAttempts;\n }\n private _notifyListeners(): void {\n const health = this.getHealth();\n\n // Call main callback\n this.onHealthChange?.(health);\n\n // Call all listeners\n for (const listener of this._listeners) {\n try {\n listener(health);\n } catch (err) {\n this.logger.warn('[HealthMonitor] Listener error:', err);\n }\n }\n }\n private _withTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this._pendingTimers.delete(timer);\n reject(new Error(`Health check timeout after ${timeoutMs}ms`));\n }, timeoutMs);\n this._pendingTimers.add(timer);\n promise.then(result => {\n this._pendingTimers.delete(timer);\n clearTimeout(timer);\n resolve(result);\n }, error => {\n this._pendingTimers.delete(timer);\n clearTimeout(timer);\n reject(error);\n });\n });\n }\n}"],"mappings":"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","names":[]}