@pol-studios/powersync 1.0.24 → 1.0.25
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.
- package/dist/{chunk-YVX3A36I.js → chunk-VB737IVN.js} +30 -38
- package/dist/{chunk-YVX3A36I.js.map → chunk-VB737IVN.js.map} +1 -1
- package/dist/generator/cli.js +6 -1
- package/dist/generator/index.d.ts +1 -0
- package/dist/generator/index.js +9 -1
- package/dist/generator/index.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.native.js +1 -1
- package/dist/index.web.js +1 -1
- package/dist/provider/index.js +1 -1
- package/package.json +2 -2
|
@@ -1265,7 +1265,7 @@ function DefaultErrorRecoveryUI(t0) {
|
|
|
1265
1265
|
return t6;
|
|
1266
1266
|
}
|
|
1267
1267
|
function OfflineDataProvider(t0) {
|
|
1268
|
-
const $ = _c(
|
|
1268
|
+
const $ = _c(103);
|
|
1269
1269
|
const {
|
|
1270
1270
|
config,
|
|
1271
1271
|
children,
|
|
@@ -1617,7 +1617,7 @@ function OfflineDataProvider(t0) {
|
|
|
1617
1617
|
useEffect3(t29, t30);
|
|
1618
1618
|
let t31;
|
|
1619
1619
|
let t32;
|
|
1620
|
-
if ($[72] !== backgroundSync || $[73] !== children || $[74] !== dataLayer || $[75] !== effectiveSyncStatus || $[76] !== errorFallback || $[77] !== handleBackgroundSyncSystemReady || $[78] !== handlePowerSyncError || $[79] !== handleRetry || $[80] !== initError || $[81] !==
|
|
1620
|
+
if ($[72] !== backgroundSync || $[73] !== children || $[74] !== dataLayer || $[75] !== effectiveSyncStatus || $[76] !== errorFallback || $[77] !== handleBackgroundSyncSystemReady || $[78] !== handlePowerSyncError || $[79] !== handleRetry || $[80] !== initError || $[81] !== onReady || $[82] !== platform.logger || $[83] !== powerSyncConfig || $[84] !== powerSyncInstance || $[85] !== powerSyncUrl || $[86] !== queryClient || $[87] !== renderError || $[88] !== renderInitError || $[89] !== retryKey || $[90] !== skipConflictProvider || $[91] !== skipStorageQueueProvider || $[92] !== supabaseClient || $[93] !== syncControl) {
|
|
1621
1621
|
t32 = /* @__PURE__ */ Symbol.for("react.early_return_sentinel");
|
|
1622
1622
|
bb1: {
|
|
1623
1623
|
const renderContent = () => {
|
|
@@ -1647,24 +1647,17 @@ function OfflineDataProvider(t0) {
|
|
|
1647
1647
|
}, children }) }, retryKey) });
|
|
1648
1648
|
};
|
|
1649
1649
|
let t33;
|
|
1650
|
-
if ($[
|
|
1651
|
-
t33 = (content) => /* @__PURE__ */ jsx3(DataLayerProvider, { config: dataLayer.config, powerSyncInstance, supabaseClient, queryClient, powerSyncSyncStatus: effectiveSyncStatus, syncControl,
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
$[
|
|
1658
|
-
$[
|
|
1659
|
-
$[99] = onError;
|
|
1660
|
-
$[100] = platform.logger;
|
|
1661
|
-
$[101] = powerSyncInstance;
|
|
1662
|
-
$[102] = queryClient;
|
|
1663
|
-
$[103] = supabaseClient;
|
|
1664
|
-
$[104] = syncControl;
|
|
1665
|
-
$[105] = t33;
|
|
1650
|
+
if ($[96] !== dataLayer.config || $[97] !== effectiveSyncStatus || $[98] !== powerSyncInstance || $[99] !== queryClient || $[100] !== supabaseClient || $[101] !== syncControl) {
|
|
1651
|
+
t33 = (content) => /* @__PURE__ */ jsx3(DataLayerProvider, { config: dataLayer.config, powerSyncInstance, supabaseClient, queryClient, powerSyncSyncStatus: effectiveSyncStatus, syncControl, children: content });
|
|
1652
|
+
$[96] = dataLayer.config;
|
|
1653
|
+
$[97] = effectiveSyncStatus;
|
|
1654
|
+
$[98] = powerSyncInstance;
|
|
1655
|
+
$[99] = queryClient;
|
|
1656
|
+
$[100] = supabaseClient;
|
|
1657
|
+
$[101] = syncControl;
|
|
1658
|
+
$[102] = t33;
|
|
1666
1659
|
} else {
|
|
1667
|
-
t33 = $[
|
|
1660
|
+
t33 = $[102];
|
|
1668
1661
|
}
|
|
1669
1662
|
const renderWithDataLayer = t33;
|
|
1670
1663
|
if (dataLayer && !dataLayer.skip) {
|
|
@@ -1682,25 +1675,24 @@ function OfflineDataProvider(t0) {
|
|
|
1682
1675
|
$[78] = handlePowerSyncError;
|
|
1683
1676
|
$[79] = handleRetry;
|
|
1684
1677
|
$[80] = initError;
|
|
1685
|
-
$[81] =
|
|
1686
|
-
$[82] =
|
|
1687
|
-
$[83] =
|
|
1688
|
-
$[84] =
|
|
1689
|
-
$[85] =
|
|
1690
|
-
$[86] =
|
|
1691
|
-
$[87] =
|
|
1692
|
-
$[88] =
|
|
1693
|
-
$[89] =
|
|
1694
|
-
$[90] =
|
|
1695
|
-
$[91] =
|
|
1696
|
-
$[92] =
|
|
1697
|
-
$[93] =
|
|
1698
|
-
$[94] =
|
|
1699
|
-
$[95] =
|
|
1700
|
-
$[96] = t32;
|
|
1678
|
+
$[81] = onReady;
|
|
1679
|
+
$[82] = platform.logger;
|
|
1680
|
+
$[83] = powerSyncConfig;
|
|
1681
|
+
$[84] = powerSyncInstance;
|
|
1682
|
+
$[85] = powerSyncUrl;
|
|
1683
|
+
$[86] = queryClient;
|
|
1684
|
+
$[87] = renderError;
|
|
1685
|
+
$[88] = renderInitError;
|
|
1686
|
+
$[89] = retryKey;
|
|
1687
|
+
$[90] = skipConflictProvider;
|
|
1688
|
+
$[91] = skipStorageQueueProvider;
|
|
1689
|
+
$[92] = supabaseClient;
|
|
1690
|
+
$[93] = syncControl;
|
|
1691
|
+
$[94] = t31;
|
|
1692
|
+
$[95] = t32;
|
|
1701
1693
|
} else {
|
|
1702
|
-
t31 = $[
|
|
1703
|
-
t32 = $[
|
|
1694
|
+
t31 = $[94];
|
|
1695
|
+
t32 = $[95];
|
|
1704
1696
|
}
|
|
1705
1697
|
if (t32 !== /* @__PURE__ */ Symbol.for("react.early_return_sentinel")) {
|
|
1706
1698
|
return t32;
|
|
@@ -1717,4 +1709,4 @@ export {
|
|
|
1717
1709
|
ProviderBridge,
|
|
1718
1710
|
OfflineDataProvider
|
|
1719
1711
|
};
|
|
1720
|
-
//# sourceMappingURL=chunk-
|
|
1712
|
+
//# sourceMappingURL=chunk-VB737IVN.js.map
|
|
@@ -1 +1 @@
|
|
|
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, type CreateAttachmentQueueOptions } from '../attachments/pol-attachment-queue';\nimport type { AttachmentStorageAdapter, PowerSyncDBInterface } from '../attachments/types';\nimport { SupabaseStorageAdapter } from '../storage/SupabaseStorageAdapter';\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 remote storage adapter from Supabase client\n // Pass compression config for Supabase image transform on download\n const remoteStorage = new SupabaseStorageAdapter({\n client: supabaseClient,\n defaultBucket: attachmentConfig.bucket,\n logger,\n imageTransform: attachmentConfig.compression ? {\n enabled: attachmentConfig.compression.enabled ?? true,\n width: attachmentConfig.compression.maxWidth,\n quality: attachmentConfig.compression.quality ? Math.round(attachmentConfig.compression.quality * 100) : undefined\n } : undefined\n }, platform.fileSystem);\n\n // Build queue options from AttachmentConfig\n // SupabaseStorageAdapter implements both SupabaseStorage interface (for download())\n // and AttachmentStorageAdapter compatibility (via downloadFile() wrapper method).\n // The cast is safe because AttachmentStorageAdapter only uses downloadFile().\n const queueOptions: CreateAttachmentQueueOptions = {\n ...attachmentConfig,\n remoteStorage: remoteStorage as AttachmentStorageAdapter\n };\n\n // Create PolAttachmentQueue (extends AbstractAttachmentQueue from @powersync/attachments)\n // PowerSync database types vary between packages but are structurally compatible.\n // AbstractPowerSyncDatabase from @powersync/common matches our AbstractPowerSyncDatabase.\n const queue = createPolAttachmentQueue(db as PowerSyncDBInterface, platform, queueOptions);\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, supabaseClient]);\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 * @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 * watchIds: (db, onUpdate) => {\n * db.watch('SELECT storagePath as id FROM photos', [], {\n * onResult: (r) => onUpdate(r.rows._array.map(x => x.id)),\n * });\n * },\n * skipDownload: async ({ ids }) => {\n * // Return IDs to skip downloading (e.g., videos)\n * return ids.filter(id => id.endsWith('.mp4'));\n * },\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';\nimport { DataLayerProvider } from '@pol-studios/db';\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 { createNativePlatformAdapter } from '../platform/index.native';\nimport type { LoggerAdapter, PlatformAdapter } from '../platform/types';\nimport { ProviderBridge } from './ProviderBridge';\nimport { createSupabaseUploadHandler } from '../storage/upload/index.native';\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(106);\n const {\n config,\n children,\n dataLayer,\n backgroundSync,\n skipConflictProvider: t1,\n skipStorageQueueProvider: t2,\n storageBackend,\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 t10;\n let t5;\n let t6;\n let t7;\n let t8;\n let t9;\n if ($[2] !== platform.logger) {\n t5 = async () => {\n platform.logger.warn(\"Sync not available: Use useSyncControl from PowerSync context\");\n };\n t6 = async () => {\n platform.logger.warn(\"Live sync not available: Use useSyncControl from PowerSync context\");\n };\n t7 = () => {\n platform.logger.warn(\"Live sync not available: Use useSyncControl from PowerSync context\");\n };\n t8 = async () => {\n platform.logger.warn(\"Scope control not available: Use useSyncControl from PowerSync context\");\n };\n t9 = async () => {\n platform.logger.warn(\"Retry not available: Use useSyncControl from PowerSync context\");\n };\n t10 = () => {\n platform.logger.warn(\"Clear failed uploads not available: Use useSyncControl from PowerSync context\");\n };\n $[2] = platform.logger;\n $[3] = t10;\n $[4] = t5;\n $[5] = t6;\n $[6] = t7;\n $[7] = t8;\n $[8] = t9;\n } else {\n t10 = $[3];\n t5 = $[4];\n t6 = $[5];\n t7 = $[6];\n t8 = $[7];\n t9 = $[8];\n }\n let t11;\n if ($[9] === Symbol.for(\"react.memo_cache_sentinel\")) {\n t11 = [];\n $[9] = t11;\n } else {\n t11 = $[9];\n }\n let t12;\n let t13;\n if ($[10] !== platform.logger) {\n t12 = () => {\n platform.logger.warn(\"Pause auto-retry not available: Use useSyncControl from PowerSync context\");\n };\n t13 = () => {\n platform.logger.warn(\"Resume auto-retry not available: Use useSyncControl from PowerSync context\");\n };\n $[10] = platform.logger;\n $[11] = t12;\n $[12] = t13;\n } else {\n t12 = $[11];\n t13 = $[12];\n }\n let t14;\n let t15;\n if ($[13] === Symbol.for(\"react.memo_cache_sentinel\")) {\n t14 = entry => {\n if (addPendingMutationRef.current) {\n addPendingMutationRef.current(entry as CrudEntry);\n }\n };\n t15 = id => {\n if (removePendingMutationRef.current) {\n removePendingMutationRef.current(id);\n }\n };\n $[13] = t14;\n $[14] = t15;\n } else {\n t14 = $[13];\n t15 = $[14];\n }\n let t16;\n if ($[15] !== t10 || $[16] !== t12 || $[17] !== t13 || $[18] !== t5 || $[19] !== t6 || $[20] !== t7 || $[21] !== t8 || $[22] !== t9) {\n t16 = {\n triggerSync: t5,\n startLiveSync: t6,\n stopLiveSync: t7,\n setScope: t8,\n retryFailedUploads: t9,\n clearFailedUploads: t10,\n failedUploads: t11,\n pauseAutoRetry: t12,\n resumeAutoRetry: t13,\n isAutoRetryPaused: false,\n addPendingMutation: t14,\n removePendingMutation: t15\n };\n $[15] = t10;\n $[16] = t12;\n $[17] = t13;\n $[18] = t5;\n $[19] = t6;\n $[20] = t7;\n $[21] = t8;\n $[22] = t9;\n $[23] = t16;\n } else {\n t16 = $[23];\n }\n const syncControl = t16;\n let t17;\n bb0: {\n if (!attachments) {\n t17 = undefined;\n break bb0;\n }\n let t18;\n if ($[24] !== attachments.bucket || $[25] !== storageBackend || $[26] !== supabaseClient) {\n t18 = supabaseClient ? createSupabaseUploadHandler(supabaseClient, {\n defaultBucket: attachments.bucket,\n resolver: storageBackend?.resolveBucket?.bind(storageBackend)\n }) : undefined;\n $[24] = attachments.bucket;\n $[25] = storageBackend;\n $[26] = supabaseClient;\n $[27] = t18;\n } else {\n t18 = $[27];\n }\n const nativeUploadHandler = t18;\n const t19 = storageBackend as unknown as import('../attachments/types').AttachmentStorageAdapter;\n let t20;\n if ($[28] !== attachments.bucket || $[29] !== attachments.compression || $[30] !== attachments.download || $[31] !== attachments.maxCacheBytes || $[32] !== attachments.onUploadComplete || $[33] !== attachments.onUploadFailed || $[34] !== attachments.skipDownload || $[35] !== attachments.watchIds || $[36] !== nativeUploadHandler || $[37] !== t19) {\n t20 = {\n bucket: attachments.bucket,\n watchIds: attachments.watchIds,\n skipDownload: attachments.skipDownload,\n onUploadComplete: attachments.onUploadComplete,\n onUploadFailed: attachments.onUploadFailed,\n maxCacheBytes: attachments.maxCacheBytes,\n compression: attachments.compression,\n download: attachments.download,\n remoteStorage: t19,\n uploadHandler: nativeUploadHandler\n };\n $[28] = attachments.bucket;\n $[29] = attachments.compression;\n $[30] = attachments.download;\n $[31] = attachments.maxCacheBytes;\n $[32] = attachments.onUploadComplete;\n $[33] = attachments.onUploadFailed;\n $[34] = attachments.skipDownload;\n $[35] = attachments.watchIds;\n $[36] = nativeUploadHandler;\n $[37] = t19;\n $[38] = t20;\n } else {\n t20 = $[38];\n }\n t17 = t20;\n }\n const attachmentConfig = t17;\n const t18 = powerSyncUrl ?? \"\";\n const t19 = syncConfig?.autoConnect ?? true;\n const t20 = syncConfig?.enableHealthMonitoring ?? true;\n const t21 = syncConfig?.enableMetrics ?? true;\n let t22;\n if ($[39] !== t19 || $[40] !== t20 || $[41] !== t21) {\n t22 = {\n autoConnect: t19,\n enableHealthMonitoring: t20,\n enableMetrics: t21\n };\n $[39] = t19;\n $[40] = t20;\n $[41] = t21;\n $[42] = t22;\n } else {\n t22 = $[42];\n }\n let t23;\n if ($[43] !== attachmentConfig || $[44] !== connectorConfig || $[45] !== dbFilename || $[46] !== platform || $[47] !== queryClient || $[48] !== schema || $[49] !== supabaseClient || $[50] !== t18 || $[51] !== t22) {\n t23 = {\n platform,\n schema,\n powerSyncUrl: t18,\n supabaseClient,\n queryClient,\n dbFilename,\n connector: connectorConfig,\n attachments: attachmentConfig,\n sync: t22\n };\n $[43] = attachmentConfig;\n $[44] = connectorConfig;\n $[45] = dbFilename;\n $[46] = platform;\n $[47] = queryClient;\n $[48] = schema;\n $[49] = supabaseClient;\n $[50] = t18;\n $[51] = t22;\n $[52] = t23;\n } else {\n t23 = $[52];\n }\n const powerSyncConfig = t23;\n let t24;\n if ($[53] !== onError || $[54] !== platform.logger) {\n t24 = 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 $[53] = onError;\n $[54] = platform.logger;\n $[55] = t24;\n } else {\n t24 = $[55];\n }\n const handlePowerSyncError = t24;\n let t25;\n if ($[56] !== platform.logger) {\n t25 = () => {\n platform.logger.info(\"Retrying PowerSync initialization...\");\n setInitError(null);\n setRetryKey(_temp);\n };\n $[56] = platform.logger;\n $[57] = t25;\n } else {\n t25 = $[57];\n }\n const handleRetry = t25;\n let t26;\n if ($[58] !== backgroundSync?.callbacks || $[59] !== onBackgroundSyncSystemReadyProp || $[60] !== platform.logger) {\n t26 = system => {\n backgroundSyncSystemRef.current = system;\n backgroundSync?.callbacks?.onSyncStart?.();\n onBackgroundSyncSystemReadyProp?.(system);\n platform.logger.info(\"[Background Sync] System ready\");\n };\n $[58] = backgroundSync?.callbacks;\n $[59] = onBackgroundSyncSystemReadyProp;\n $[60] = platform.logger;\n $[61] = t26;\n } else {\n t26 = $[61];\n }\n backgroundSync?.callbacks;\n const handleBackgroundSyncSystemReady = t26;\n let t27;\n if ($[62] !== renderError || $[63] !== renderInitError) {\n t27 = (error, retry) => {\n const customRenderer = renderInitError ?? renderError;\n if (customRenderer) {\n return customRenderer(error, retry);\n }\n return <DefaultErrorRecoveryUI error={error} onRetry={retry} />;\n };\n $[62] = renderError;\n $[63] = renderInitError;\n $[64] = t27;\n } else {\n t27 = $[64];\n }\n const errorFallback = t27;\n let t28;\n if ($[65] !== powerSyncSyncStatus || $[66] !== powerSyncUrl) {\n t28 = !powerSyncUrl ? {\n hasSynced: true,\n connected: true,\n connecting: false,\n isOnline: true\n } : powerSyncSyncStatus;\n $[65] = powerSyncSyncStatus;\n $[66] = powerSyncUrl;\n $[67] = t28;\n } else {\n t28 = $[67];\n }\n const effectiveSyncStatus = t28;\n let t29;\n let t30;\n if ($[68] !== effectiveSyncStatus || $[69] !== onSyncStatusChange) {\n t29 = () => {\n if (effectiveSyncStatus) {\n onSyncStatusChange?.(effectiveSyncStatus);\n }\n };\n t30 = [effectiveSyncStatus, onSyncStatusChange];\n $[68] = effectiveSyncStatus;\n $[69] = onSyncStatusChange;\n $[70] = t29;\n $[71] = t30;\n } else {\n t29 = $[70];\n t30 = $[71];\n }\n useEffect(t29, t30);\n let t31;\n let t32;\n if ($[72] !== backgroundSync || $[73] !== children || $[74] !== dataLayer || $[75] !== effectiveSyncStatus || $[76] !== errorFallback || $[77] !== handleBackgroundSyncSystemReady || $[78] !== handlePowerSyncError || $[79] !== handleRetry || $[80] !== initError || $[81] !== onError || $[82] !== onReady || $[83] !== platform.logger || $[84] !== powerSyncConfig || $[85] !== powerSyncInstance || $[86] !== powerSyncUrl || $[87] !== queryClient || $[88] !== renderError || $[89] !== renderInitError || $[90] !== retryKey || $[91] !== skipConflictProvider || $[92] !== skipStorageQueueProvider || $[93] !== supabaseClient || $[94] !== syncControl) {\n t32 = Symbol.for(\"react.early_return_sentinel\");\n bb1: {\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 unknown as import('./types').PowerSyncConfig} 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 t33;\n if ($[97] !== dataLayer.config || $[98] !== effectiveSyncStatus || $[99] !== onError || $[100] !== platform.logger || $[101] !== powerSyncInstance || $[102] !== queryClient || $[103] !== supabaseClient || $[104] !== syncControl) {\n t33 = content => <DataLayerProvider config={dataLayer.config as any} 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 $[97] = dataLayer.config;\n $[98] = effectiveSyncStatus;\n $[99] = onError;\n $[100] = platform.logger;\n $[101] = powerSyncInstance;\n $[102] = queryClient;\n $[103] = supabaseClient;\n $[104] = syncControl;\n $[105] = t33;\n } else {\n t33 = $[105];\n }\n const renderWithDataLayer = t33;\n if (dataLayer && !dataLayer.skip) {\n t32 = renderWithDataLayer(renderContent());\n break bb1;\n }\n t31 = renderContent();\n }\n $[72] = backgroundSync;\n $[73] = children;\n $[74] = dataLayer;\n $[75] = effectiveSyncStatus;\n $[76] = errorFallback;\n $[77] = handleBackgroundSyncSystemReady;\n $[78] = handlePowerSyncError;\n $[79] = handleRetry;\n $[80] = initError;\n $[81] = onError;\n $[82] = onReady;\n $[83] = platform.logger;\n $[84] = powerSyncConfig;\n $[85] = powerSyncInstance;\n $[86] = powerSyncUrl;\n $[87] = queryClient;\n $[88] = renderError;\n $[89] = renderInitError;\n $[90] = retryKey;\n $[91] = skipConflictProvider;\n $[92] = skipStorageQueueProvider;\n $[93] = supabaseClient;\n $[94] = syncControl;\n $[95] = t31;\n $[96] = t32;\n } else {\n t31 = $[95];\n t32 = $[96];\n }\n if (t32 !== Symbol.for(\"react.early_return_sentinel\")) {\n return t32;\n }\n return t31;\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';\nimport { StorageQueueProvider, ConflictProvider } from '@pol-studios/db';\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 content = <StorageQueueProvider attachmentQueue={attachmentQueue} isReady={attachmentQueueReady}>\n {content}\n </StorageQueueProvider>;\n }\n\n // Wrap with ConflictProvider if not skipped\n if (!skipConflictProvider) {\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","t18","t19","t20","useEffect"]}
|
|
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, type CreateAttachmentQueueOptions } from '../attachments/pol-attachment-queue';\nimport type { AttachmentStorageAdapter, PowerSyncDBInterface } from '../attachments/types';\nimport { SupabaseStorageAdapter } from '../storage/SupabaseStorageAdapter';\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 remote storage adapter from Supabase client\n // Pass compression config for Supabase image transform on download\n const remoteStorage = new SupabaseStorageAdapter({\n client: supabaseClient,\n defaultBucket: attachmentConfig.bucket,\n logger,\n imageTransform: attachmentConfig.compression ? {\n enabled: attachmentConfig.compression.enabled ?? true,\n width: attachmentConfig.compression.maxWidth,\n quality: attachmentConfig.compression.quality ? Math.round(attachmentConfig.compression.quality * 100) : undefined\n } : undefined\n }, platform.fileSystem);\n\n // Build queue options from AttachmentConfig\n // SupabaseStorageAdapter implements both SupabaseStorage interface (for download())\n // and AttachmentStorageAdapter compatibility (via downloadFile() wrapper method).\n // The cast is safe because AttachmentStorageAdapter only uses downloadFile().\n const queueOptions: CreateAttachmentQueueOptions = {\n ...attachmentConfig,\n remoteStorage: remoteStorage as AttachmentStorageAdapter\n };\n\n // Create PolAttachmentQueue (extends AbstractAttachmentQueue from @powersync/attachments)\n // PowerSync database types vary between packages but are structurally compatible.\n // AbstractPowerSyncDatabase from @powersync/common matches our AbstractPowerSyncDatabase.\n const queue = createPolAttachmentQueue(db as PowerSyncDBInterface, platform, queueOptions);\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, supabaseClient]);\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 * @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 * watchIds: (db, onUpdate) => {\n * db.watch('SELECT storagePath as id FROM photos', [], {\n * onResult: (r) => onUpdate(r.rows._array.map(x => x.id)),\n * });\n * },\n * skipDownload: async ({ ids }) => {\n * // Return IDs to skip downloading (e.g., videos)\n * return ids.filter(id => id.endsWith('.mp4'));\n * },\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';\nimport { DataLayerProvider } from '@pol-studios/db';\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 { createNativePlatformAdapter } from '../platform/index.native';\nimport type { LoggerAdapter, PlatformAdapter } from '../platform/types';\nimport { ProviderBridge } from './ProviderBridge';\nimport { createSupabaseUploadHandler } from '../storage/upload/index.native';\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(103);\n const {\n config,\n children,\n dataLayer,\n backgroundSync,\n skipConflictProvider: t1,\n skipStorageQueueProvider: t2,\n storageBackend,\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 t10;\n let t5;\n let t6;\n let t7;\n let t8;\n let t9;\n if ($[2] !== platform.logger) {\n t5 = async () => {\n platform.logger.warn(\"Sync not available: Use useSyncControl from PowerSync context\");\n };\n t6 = async () => {\n platform.logger.warn(\"Live sync not available: Use useSyncControl from PowerSync context\");\n };\n t7 = () => {\n platform.logger.warn(\"Live sync not available: Use useSyncControl from PowerSync context\");\n };\n t8 = async () => {\n platform.logger.warn(\"Scope control not available: Use useSyncControl from PowerSync context\");\n };\n t9 = async () => {\n platform.logger.warn(\"Retry not available: Use useSyncControl from PowerSync context\");\n };\n t10 = () => {\n platform.logger.warn(\"Clear failed uploads not available: Use useSyncControl from PowerSync context\");\n };\n $[2] = platform.logger;\n $[3] = t10;\n $[4] = t5;\n $[5] = t6;\n $[6] = t7;\n $[7] = t8;\n $[8] = t9;\n } else {\n t10 = $[3];\n t5 = $[4];\n t6 = $[5];\n t7 = $[6];\n t8 = $[7];\n t9 = $[8];\n }\n let t11;\n if ($[9] === Symbol.for(\"react.memo_cache_sentinel\")) {\n t11 = [];\n $[9] = t11;\n } else {\n t11 = $[9];\n }\n let t12;\n let t13;\n if ($[10] !== platform.logger) {\n t12 = () => {\n platform.logger.warn(\"Pause auto-retry not available: Use useSyncControl from PowerSync context\");\n };\n t13 = () => {\n platform.logger.warn(\"Resume auto-retry not available: Use useSyncControl from PowerSync context\");\n };\n $[10] = platform.logger;\n $[11] = t12;\n $[12] = t13;\n } else {\n t12 = $[11];\n t13 = $[12];\n }\n let t14;\n let t15;\n if ($[13] === Symbol.for(\"react.memo_cache_sentinel\")) {\n t14 = entry => {\n if (addPendingMutationRef.current) {\n addPendingMutationRef.current(entry as CrudEntry);\n }\n };\n t15 = id => {\n if (removePendingMutationRef.current) {\n removePendingMutationRef.current(id);\n }\n };\n $[13] = t14;\n $[14] = t15;\n } else {\n t14 = $[13];\n t15 = $[14];\n }\n let t16;\n if ($[15] !== t10 || $[16] !== t12 || $[17] !== t13 || $[18] !== t5 || $[19] !== t6 || $[20] !== t7 || $[21] !== t8 || $[22] !== t9) {\n t16 = {\n triggerSync: t5,\n startLiveSync: t6,\n stopLiveSync: t7,\n setScope: t8,\n retryFailedUploads: t9,\n clearFailedUploads: t10,\n failedUploads: t11,\n pauseAutoRetry: t12,\n resumeAutoRetry: t13,\n isAutoRetryPaused: false,\n addPendingMutation: t14,\n removePendingMutation: t15\n };\n $[15] = t10;\n $[16] = t12;\n $[17] = t13;\n $[18] = t5;\n $[19] = t6;\n $[20] = t7;\n $[21] = t8;\n $[22] = t9;\n $[23] = t16;\n } else {\n t16 = $[23];\n }\n const syncControl = t16;\n let t17;\n bb0: {\n if (!attachments) {\n t17 = undefined;\n break bb0;\n }\n let t18;\n if ($[24] !== attachments.bucket || $[25] !== storageBackend || $[26] !== supabaseClient) {\n t18 = supabaseClient ? createSupabaseUploadHandler(supabaseClient, {\n defaultBucket: attachments.bucket,\n resolver: storageBackend?.resolveBucket?.bind(storageBackend)\n }) : undefined;\n $[24] = attachments.bucket;\n $[25] = storageBackend;\n $[26] = supabaseClient;\n $[27] = t18;\n } else {\n t18 = $[27];\n }\n const nativeUploadHandler = t18;\n const t19 = storageBackend as unknown as import('../attachments/types').AttachmentStorageAdapter;\n let t20;\n if ($[28] !== attachments.bucket || $[29] !== attachments.compression || $[30] !== attachments.download || $[31] !== attachments.maxCacheBytes || $[32] !== attachments.onUploadComplete || $[33] !== attachments.onUploadFailed || $[34] !== attachments.skipDownload || $[35] !== attachments.watchIds || $[36] !== nativeUploadHandler || $[37] !== t19) {\n t20 = {\n bucket: attachments.bucket,\n watchIds: attachments.watchIds,\n skipDownload: attachments.skipDownload,\n onUploadComplete: attachments.onUploadComplete,\n onUploadFailed: attachments.onUploadFailed,\n maxCacheBytes: attachments.maxCacheBytes,\n compression: attachments.compression,\n download: attachments.download,\n remoteStorage: t19,\n uploadHandler: nativeUploadHandler\n };\n $[28] = attachments.bucket;\n $[29] = attachments.compression;\n $[30] = attachments.download;\n $[31] = attachments.maxCacheBytes;\n $[32] = attachments.onUploadComplete;\n $[33] = attachments.onUploadFailed;\n $[34] = attachments.skipDownload;\n $[35] = attachments.watchIds;\n $[36] = nativeUploadHandler;\n $[37] = t19;\n $[38] = t20;\n } else {\n t20 = $[38];\n }\n t17 = t20;\n }\n const attachmentConfig = t17;\n const t18 = powerSyncUrl ?? \"\";\n const t19 = syncConfig?.autoConnect ?? true;\n const t20 = syncConfig?.enableHealthMonitoring ?? true;\n const t21 = syncConfig?.enableMetrics ?? true;\n let t22;\n if ($[39] !== t19 || $[40] !== t20 || $[41] !== t21) {\n t22 = {\n autoConnect: t19,\n enableHealthMonitoring: t20,\n enableMetrics: t21\n };\n $[39] = t19;\n $[40] = t20;\n $[41] = t21;\n $[42] = t22;\n } else {\n t22 = $[42];\n }\n let t23;\n if ($[43] !== attachmentConfig || $[44] !== connectorConfig || $[45] !== dbFilename || $[46] !== platform || $[47] !== queryClient || $[48] !== schema || $[49] !== supabaseClient || $[50] !== t18 || $[51] !== t22) {\n t23 = {\n platform,\n schema,\n powerSyncUrl: t18,\n supabaseClient,\n queryClient,\n dbFilename,\n connector: connectorConfig,\n attachments: attachmentConfig,\n sync: t22\n };\n $[43] = attachmentConfig;\n $[44] = connectorConfig;\n $[45] = dbFilename;\n $[46] = platform;\n $[47] = queryClient;\n $[48] = schema;\n $[49] = supabaseClient;\n $[50] = t18;\n $[51] = t22;\n $[52] = t23;\n } else {\n t23 = $[52];\n }\n const powerSyncConfig = t23;\n let t24;\n if ($[53] !== onError || $[54] !== platform.logger) {\n t24 = 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 $[53] = onError;\n $[54] = platform.logger;\n $[55] = t24;\n } else {\n t24 = $[55];\n }\n const handlePowerSyncError = t24;\n let t25;\n if ($[56] !== platform.logger) {\n t25 = () => {\n platform.logger.info(\"Retrying PowerSync initialization...\");\n setInitError(null);\n setRetryKey(_temp);\n };\n $[56] = platform.logger;\n $[57] = t25;\n } else {\n t25 = $[57];\n }\n const handleRetry = t25;\n let t26;\n if ($[58] !== backgroundSync?.callbacks || $[59] !== onBackgroundSyncSystemReadyProp || $[60] !== platform.logger) {\n t26 = system => {\n backgroundSyncSystemRef.current = system;\n backgroundSync?.callbacks?.onSyncStart?.();\n onBackgroundSyncSystemReadyProp?.(system);\n platform.logger.info(\"[Background Sync] System ready\");\n };\n $[58] = backgroundSync?.callbacks;\n $[59] = onBackgroundSyncSystemReadyProp;\n $[60] = platform.logger;\n $[61] = t26;\n } else {\n t26 = $[61];\n }\n backgroundSync?.callbacks;\n const handleBackgroundSyncSystemReady = t26;\n let t27;\n if ($[62] !== renderError || $[63] !== renderInitError) {\n t27 = (error, retry) => {\n const customRenderer = renderInitError ?? renderError;\n if (customRenderer) {\n return customRenderer(error, retry);\n }\n return <DefaultErrorRecoveryUI error={error} onRetry={retry} />;\n };\n $[62] = renderError;\n $[63] = renderInitError;\n $[64] = t27;\n } else {\n t27 = $[64];\n }\n const errorFallback = t27;\n let t28;\n if ($[65] !== powerSyncSyncStatus || $[66] !== powerSyncUrl) {\n t28 = !powerSyncUrl ? {\n hasSynced: true,\n connected: true,\n connecting: false,\n isOnline: true\n } : powerSyncSyncStatus;\n $[65] = powerSyncSyncStatus;\n $[66] = powerSyncUrl;\n $[67] = t28;\n } else {\n t28 = $[67];\n }\n const effectiveSyncStatus = t28;\n let t29;\n let t30;\n if ($[68] !== effectiveSyncStatus || $[69] !== onSyncStatusChange) {\n t29 = () => {\n if (effectiveSyncStatus) {\n onSyncStatusChange?.(effectiveSyncStatus);\n }\n };\n t30 = [effectiveSyncStatus, onSyncStatusChange];\n $[68] = effectiveSyncStatus;\n $[69] = onSyncStatusChange;\n $[70] = t29;\n $[71] = t30;\n } else {\n t29 = $[70];\n t30 = $[71];\n }\n useEffect(t29, t30);\n let t31;\n let t32;\n if ($[72] !== backgroundSync || $[73] !== children || $[74] !== dataLayer || $[75] !== effectiveSyncStatus || $[76] !== errorFallback || $[77] !== handleBackgroundSyncSystemReady || $[78] !== handlePowerSyncError || $[79] !== handleRetry || $[80] !== initError || $[81] !== onReady || $[82] !== platform.logger || $[83] !== powerSyncConfig || $[84] !== powerSyncInstance || $[85] !== powerSyncUrl || $[86] !== queryClient || $[87] !== renderError || $[88] !== renderInitError || $[89] !== retryKey || $[90] !== skipConflictProvider || $[91] !== skipStorageQueueProvider || $[92] !== supabaseClient || $[93] !== syncControl) {\n t32 = Symbol.for(\"react.early_return_sentinel\");\n bb1: {\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 unknown as import('./types').PowerSyncConfig} 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 t33;\n if ($[96] !== dataLayer.config || $[97] !== effectiveSyncStatus || $[98] !== powerSyncInstance || $[99] !== queryClient || $[100] !== supabaseClient || $[101] !== syncControl) {\n t33 = content => <DataLayerProvider config={dataLayer.config as any} powerSyncInstance={powerSyncInstance} supabaseClient={supabaseClient} queryClient={queryClient} powerSyncSyncStatus={effectiveSyncStatus} syncControl={syncControl}>{content}</DataLayerProvider>;\n $[96] = dataLayer.config;\n $[97] = effectiveSyncStatus;\n $[98] = powerSyncInstance;\n $[99] = queryClient;\n $[100] = supabaseClient;\n $[101] = syncControl;\n $[102] = t33;\n } else {\n t33 = $[102];\n }\n const renderWithDataLayer = t33;\n if (dataLayer && !dataLayer.skip) {\n t32 = renderWithDataLayer(renderContent());\n break bb1;\n }\n t31 = renderContent();\n }\n $[72] = backgroundSync;\n $[73] = children;\n $[74] = dataLayer;\n $[75] = effectiveSyncStatus;\n $[76] = errorFallback;\n $[77] = handleBackgroundSyncSystemReady;\n $[78] = handlePowerSyncError;\n $[79] = handleRetry;\n $[80] = initError;\n $[81] = onReady;\n $[82] = platform.logger;\n $[83] = powerSyncConfig;\n $[84] = powerSyncInstance;\n $[85] = powerSyncUrl;\n $[86] = queryClient;\n $[87] = renderError;\n $[88] = renderInitError;\n $[89] = retryKey;\n $[90] = skipConflictProvider;\n $[91] = skipStorageQueueProvider;\n $[92] = supabaseClient;\n $[93] = syncControl;\n $[94] = t31;\n $[95] = t32;\n } else {\n t31 = $[94];\n t32 = $[95];\n }\n if (t32 !== Symbol.for(\"react.early_return_sentinel\")) {\n return t32;\n }\n return t31;\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';\nimport { StorageQueueProvider, ConflictProvider } from '@pol-studios/db';\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 content = <StorageQueueProvider attachmentQueue={attachmentQueue} isReady={attachmentQueueReady}>\n {content}\n </StorageQueueProvider>;\n }\n\n // Wrap with ConflictProvider if not skipped\n if (!skipConflictProvider) {\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","t18","t19","t20","useEffect"]}
|
package/dist/generator/cli.js
CHANGED
|
@@ -439,7 +439,10 @@ function getUploadOrder(graph) {
|
|
|
439
439
|
// src/generator/generator.ts
|
|
440
440
|
function mapTypeToPowerSync(tsType, columnName, decimalPatterns) {
|
|
441
441
|
const cleanType = tsType.trim().replace(/\s*\|\s*null/g, "");
|
|
442
|
-
if (cleanType.includes("Json")
|
|
442
|
+
if (cleanType.includes("Json")) {
|
|
443
|
+
return { type: "column.text", isJson: true };
|
|
444
|
+
}
|
|
445
|
+
if (cleanType.includes("unknown") || cleanType.includes("{")) {
|
|
443
446
|
return null;
|
|
444
447
|
}
|
|
445
448
|
if (cleanType.includes("[]")) {
|
|
@@ -474,6 +477,8 @@ function generateColumnDefs(table, decimalPatterns) {
|
|
|
474
477
|
comment = " // boolean stored as 0/1";
|
|
475
478
|
} else if (mapping.isEnum) {
|
|
476
479
|
comment = " // enum stored as text";
|
|
480
|
+
} else if (mapping.isJson) {
|
|
481
|
+
comment = " // JSON stored as text";
|
|
477
482
|
}
|
|
478
483
|
columnDefs.push(` ${columnName}: ${mapping.type},${comment}`);
|
|
479
484
|
}
|
package/dist/generator/index.js
CHANGED
|
@@ -482,7 +482,13 @@ function formatDependencyGraph(graph) {
|
|
|
482
482
|
// src/generator/generator.ts
|
|
483
483
|
function mapTypeToPowerSync(tsType, columnName, decimalPatterns) {
|
|
484
484
|
const cleanType = tsType.trim().replace(/\s*\|\s*null/g, "");
|
|
485
|
-
if (cleanType.includes("Json")
|
|
485
|
+
if (cleanType.includes("Json")) {
|
|
486
|
+
return {
|
|
487
|
+
type: "column.text",
|
|
488
|
+
isJson: true
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
if (cleanType.includes("unknown") || cleanType.includes("{")) {
|
|
486
492
|
return null;
|
|
487
493
|
}
|
|
488
494
|
if (cleanType.includes("[]")) {
|
|
@@ -529,6 +535,8 @@ function generateColumnDefs(table, decimalPatterns) {
|
|
|
529
535
|
comment = " // boolean stored as 0/1";
|
|
530
536
|
} else if (mapping.isEnum) {
|
|
531
537
|
comment = " // enum stored as text";
|
|
538
|
+
} else if (mapping.isJson) {
|
|
539
|
+
comment = " // JSON stored as text";
|
|
532
540
|
}
|
|
533
541
|
columnDefs.push(` ${columnName}: ${mapping.type},${comment}`);
|
|
534
542
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/generator/config.ts","../../src/generator/generator.ts","../../src/generator/parser.ts","../../src/generator/templates.ts","../../src/generator/fk-dependencies.ts"],"sourcesContent":["/**\n * Configuration types and helpers for PowerSync schema generator\n */\n\nexport interface TableConfig {\n /** Table name (PascalCase as it appears in database.types.ts) */\n name: string;\n /** Schema name (defaults to 'public') */\n schema?: string;\n /** Enable ps_crud timestamp tracking for optimistic UI updates */\n trackMetadata?: boolean;\n /**\n * Sync the primary key column (normally skipped as PowerSync handles it internally).\n *\n * Use this for tables with integer PKs that are referenced by FKs in other tables.\n * Example: `Group.id` is referenced by `UserGroup.groupId`, so Group needs `syncPrimaryKey: true`\n * to ensure the integer ID is available for client-side joins.\n */\n syncPrimaryKey?: boolean;\n /** @deprecated Use `syncPrimaryKey` instead */\n includeId?: boolean;\n /** Columns to skip for this specific table (in addition to global skipColumns) */\n skipColumns?: string[];\n /** Only include these columns (overrides skipColumns if specified) */\n onlyColumns?: string[];\n /** Alias for the table in PowerSync schema (for conflicting names across schemas) */\n alias?: string;\n /** Table is local-only (not synced through PowerSync) */\n localOnly?: boolean;\n}\nexport interface GeneratorConfig {\n /** Path to Supabase-generated database.types.ts file */\n typesPath: string;\n /** Output path for generated PowerSync schema */\n outputPath: string;\n /** Tables to include in the PowerSync schema */\n tables: TableConfig[];\n /** Columns to always skip (in addition to defaults like 'id') */\n skipColumns?: string[];\n /** Column name patterns that should use column.real for decimal values */\n decimalPatterns?: string[];\n /** Additional schemas to track (besides 'public' which is the default) */\n schemas?: string[];\n /** Generate indexes for FK and common columns (default: true) */\n autoIndexes?: boolean;\n /** Additional columns to index (exact column names) */\n indexColumns?: string[];\n /** Column patterns that should be indexed (regex patterns) */\n indexPatterns?: string[];\n}\n\n/**\n * Define a PowerSync generator configuration with type safety\n */\nexport function defineConfig(config: GeneratorConfig): GeneratorConfig {\n return config;\n}\n\n/**\n * Default columns that are skipped during generation\n */\nexport const DEFAULT_SKIP_COLUMNS = ['id',\n// PowerSync handles id automatically\n// Legacy numeric ID columns - typically not needed after UUID migration\n'legacyId'];\n\n/**\n * Default column name patterns that indicate decimal values\n */\nexport const DEFAULT_DECIMAL_PATTERNS = ['hours', 'watts', 'voltage', 'rate', 'amount', 'price', 'cost', 'total'];\n\n/**\n * Default column patterns that should be indexed\n * These are regex patterns matched against column names\n */\nexport const DEFAULT_INDEX_PATTERNS = ['Id$',\n// FK columns ending in Id (e.g., projectId, userId)\n'^createdAt$', '^updatedAt$', '^status$', '^type$'];\n\n/**\n * Required authentication/access control tables for offline auth\n * These tables are needed for proper offline access control\n */\nexport interface RequiredAuthTable {\n /** Table name (PascalCase) */\n name: string;\n /** Schema name */\n schema: string;\n /** Whether this table requires syncPrimaryKey to be true */\n requiresSyncPrimaryKey?: boolean;\n}\nexport const REQUIRED_AUTH_TABLES: RequiredAuthTable[] = [{\n name: 'UserAccess',\n schema: 'core'\n}, {\n name: 'UserGroup',\n schema: 'core'\n}, {\n name: 'GroupAccessKey',\n schema: 'core',\n requiresSyncPrimaryKey: true\n}, {\n name: 'Group',\n schema: 'core',\n requiresSyncPrimaryKey: true\n}];","/**\n * PowerSync schema generator\n *\n * Converts Supabase database.types.ts into PowerSync schema definitions\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { GeneratorConfig, TableConfig } from './config.js';\nimport { DEFAULT_SKIP_COLUMNS, DEFAULT_DECIMAL_PATTERNS, DEFAULT_INDEX_PATTERNS, REQUIRED_AUTH_TABLES } from './config.js';\nimport { parseTypesFile, type ParsedTable } from './parser.js';\nimport { generateTableDefinition, generateLocalOnlyTableDefinition, generateOutputFile, generateIndexDefinitions, type IndexDefinition } from './templates.js';\nimport { detectFKDependencies, type DependencyGraph } from './fk-dependencies.js';\nexport interface ColumnMapping {\n type: 'column.text' | 'column.integer' | 'column.real';\n isEnum?: boolean;\n isBoolean?: boolean;\n}\nexport interface GenerateResult {\n success: boolean;\n tablesGenerated: number;\n outputPath: string;\n errors: string[];\n warnings: string[];\n /** Generated output (included when dryRun is true) */\n output?: string;\n /** Number of indexes generated */\n indexesGenerated?: number;\n /** FK dependency graph (when detected) */\n dependencyGraph?: DependencyGraph;\n}\n\n/**\n * Map TypeScript types to PowerSync column types\n */\nexport function mapTypeToPowerSync(tsType: string, columnName: string, decimalPatterns: string[]): ColumnMapping | null {\n // Clean up the type (remove nullability)\n const cleanType = tsType.trim().replace(/\\s*\\|\\s*null/g, '');\n\n // Skip complex types that can't be stored in SQLite\n if (cleanType.includes('Json') || cleanType.includes('unknown') || cleanType.includes('{')) {\n return null;\n }\n\n // Array types - skip\n if (cleanType.includes('[]')) {\n return null;\n }\n\n // Boolean -> integer (0/1)\n if (cleanType === 'boolean') {\n return {\n type: 'column.integer',\n isBoolean: true\n };\n }\n\n // Number types\n if (cleanType === 'number') {\n // Use real for columns that might have decimals\n if (decimalPatterns.some(pattern => columnName.toLowerCase().includes(pattern.toLowerCase()))) {\n return {\n type: 'column.real'\n };\n }\n return {\n type: 'column.integer'\n };\n }\n\n // String types\n if (cleanType === 'string') {\n return {\n type: 'column.text'\n };\n }\n\n // Enum types (Database[\"schema\"][\"Enums\"][\"EnumName\"]) -> store as text\n if (cleanType.includes('Database[') && cleanType.includes('Enums')) {\n return {\n type: 'column.text',\n isEnum: true\n };\n }\n\n // Default to text for unknown types (likely enums or other string-like types)\n return {\n type: 'column.text'\n };\n}\n\n/**\n * Generate column definitions for a table\n */\nexport function generateColumnDefs(table: ParsedTable, decimalPatterns: string[]): string[] {\n const columnDefs: string[] = [];\n for (const [columnName, tsType] of table.columns) {\n const mapping = mapTypeToPowerSync(tsType, columnName, decimalPatterns);\n if (mapping) {\n // Add comment for boolean and enum columns\n let comment = '';\n if (mapping.isBoolean) {\n comment = ' // boolean stored as 0/1';\n } else if (mapping.isEnum) {\n comment = ' // enum stored as text';\n }\n columnDefs.push(` ${columnName}: ${mapping.type},${comment}`);\n }\n }\n return columnDefs;\n}\n\n/**\n * Validate that required auth tables are included in config\n * Returns warnings for missing tables or misconfigured tables\n */\nexport function validateAuthTables(tables: TableConfig[]): string[] {\n const warnings: string[] = [];\n for (const authTable of REQUIRED_AUTH_TABLES) {\n const configTable = tables.find(t => t.name === authTable.name && (t.schema ?? 'public') === authTable.schema);\n if (!configTable) {\n warnings.push(`Missing required auth table: ${authTable.schema}.${authTable.name} - offline access control may not work correctly`);\n } else if (authTable.requiresSyncPrimaryKey && !configTable.syncPrimaryKey) {\n warnings.push(`Auth table ${authTable.schema}.${authTable.name} should have syncPrimaryKey: true for proper FK references`);\n }\n }\n return warnings;\n}\n\n/**\n * Validate FK references to ensure all referenced tables are in the config\n * Returns warnings for missing FK targets\n */\nexport function validateFKReferences(dependencyGraph: DependencyGraph, configuredTables: Set<string>): string[] {\n const warnings: string[] = [];\n for (const fk of dependencyGraph.fkRelationships) {\n if (!configuredTables.has(fk.referencedTable)) {\n warnings.push(`FK reference ${fk.table}.${fk.column} references table '${fk.referencedTable}' which is not in the config`);\n }\n }\n return warnings;\n}\n\n/**\n * Generate PowerSync schema from configuration\n */\nexport async function generateSchema(config: GeneratorConfig, options?: {\n cwd?: string;\n verbose?: boolean;\n dryRun?: boolean;\n}): Promise<GenerateResult> {\n const cwd = options?.cwd ?? process.cwd();\n const verbose = options?.verbose ?? false;\n const dryRun = options?.dryRun ?? false;\n const result: GenerateResult = {\n success: false,\n tablesGenerated: 0,\n outputPath: '',\n errors: [],\n warnings: []\n };\n\n // Resolve paths relative to cwd\n const typesPath = path.isAbsolute(config.typesPath) ? config.typesPath : path.resolve(cwd, config.typesPath);\n const outputPath = path.isAbsolute(config.outputPath) ? config.outputPath : path.resolve(cwd, config.outputPath);\n result.outputPath = outputPath;\n\n // Validate required auth tables\n const authWarnings = validateAuthTables(config.tables);\n result.warnings.push(...authWarnings);\n\n // Check if types file exists\n if (!fs.existsSync(typesPath)) {\n result.errors.push(`Types file not found: ${typesPath}`);\n return result;\n }\n\n // Read types file\n if (verbose) {\n console.log(`Reading types from: ${typesPath}`);\n }\n const typesContent = fs.readFileSync(typesPath, 'utf-8');\n\n // Build skip columns set\n const skipColumns = new Set([...DEFAULT_SKIP_COLUMNS, ...(config.skipColumns ?? [])]);\n\n // Build decimal patterns\n const decimalPatterns = [...DEFAULT_DECIMAL_PATTERNS, ...(config.decimalPatterns ?? [])];\n\n // Parse tables from types file\n const parsedTables = parseTypesFile(typesContent, config.tables, skipColumns);\n\n // Check for tables that weren't found\n for (const tableConfig of config.tables) {\n const found = parsedTables.some(t => t.name === tableConfig.name);\n if (!found) {\n result.warnings.push(`Table '${tableConfig.name}' not found in schema '${tableConfig.schema ?? 'public'}'`);\n }\n }\n if (parsedTables.length === 0) {\n result.errors.push('No tables were parsed successfully');\n return result;\n }\n\n // Build index patterns (auto-indexes enabled by default)\n const autoIndexes = config.autoIndexes ?? true;\n const indexPatterns = autoIndexes ? [...DEFAULT_INDEX_PATTERNS, ...(config.indexPatterns ?? [])] : config.indexPatterns ?? [];\n const indexColumns = config.indexColumns ?? [];\n\n // Detect FK dependencies\n const dependencyGraph = detectFKDependencies(parsedTables);\n result.dependencyGraph = dependencyGraph;\n\n // Validate FK references - warn if any FK targets a table not in config\n const configuredTableNames = new Set(config.tables.map(t => t.name));\n const fkWarnings = validateFKReferences(dependencyGraph, configuredTableNames);\n result.warnings.push(...fkWarnings);\n if (verbose && dependencyGraph.fkRelationships.length > 0) {\n console.log(`\\nFK Dependencies detected: ${dependencyGraph.fkRelationships.length}`);\n for (const fk of dependencyGraph.fkRelationships) {\n console.log(` ${fk.table}.${fk.column} -> ${fk.referencedTable}`);\n }\n console.log(`\\nRecommended upload order:`);\n dependencyGraph.uploadOrder.forEach((table, i) => {\n console.log(` ${i + 1}. ${table}`);\n });\n console.log('');\n }\n\n // Generate table definitions - separate synced and local-only tables\n const syncedTableDefs: string[] = [];\n const localOnlyTableDefs: string[] = [];\n let totalIndexes = 0;\n for (const table of parsedTables) {\n const isLocalOnly = table.config.localOnly ?? false;\n const tableAlias = table.config.alias;\n if (verbose) {\n const syncPK = table.config.syncPrimaryKey || table.config.includeId;\n const flags = [table.config.trackMetadata ? '[trackMetadata]' : '', syncPK ? '[syncPrimaryKey]' : '', isLocalOnly ? '[localOnly]' : '', tableAlias ? `[alias: ${tableAlias}]` : ''].filter(Boolean).join(' ');\n console.log(`Processing ${table.schema}.${table.name} (${table.columns.size} columns)${flags ? ' ' + flags : ''}`);\n }\n const columnDefs = generateColumnDefs(table, decimalPatterns);\n if (columnDefs.length === 0) {\n result.warnings.push(`Table '${table.name}' has no syncable columns`);\n continue;\n }\n\n // Generate indexes for this table (use alias for index naming if provided)\n const effectiveTableName = tableAlias ?? table.name;\n const columnNames = [...table.columns.keys()];\n const indexes = indexPatterns.length > 0 || indexColumns.length > 0 ? generateIndexDefinitions(effectiveTableName, columnNames, indexPatterns, indexColumns) : [];\n totalIndexes += indexes.length;\n if (verbose && indexes.length > 0) {\n console.log(` Indexes: ${indexes.map(i => i.name).join(', ')}`);\n }\n\n // Generate table definition based on localOnly flag\n if (isLocalOnly) {\n localOnlyTableDefs.push(generateLocalOnlyTableDefinition(table, columnDefs, indexes));\n } else {\n syncedTableDefs.push(generateTableDefinition(table, columnDefs, indexes));\n }\n }\n\n // Combine synced and local-only table definitions\n const tableDefs = [...syncedTableDefs, ...localOnlyTableDefs];\n result.indexesGenerated = totalIndexes;\n\n // Collect unique schemas\n const schemas = [...new Set(config.tables.map(t => t.schema ?? 'public'))];\n\n // Generate output file content\n const relativePath = path.relative(cwd, typesPath);\n // Filter tables that were successfully generated (check for both name and alias)\n const generatedTables = parsedTables.filter(t => {\n const effectiveName = t.config.alias ?? t.name;\n return tableDefs.some(def => def.includes(`const ${effectiveName} =`));\n });\n const output = generateOutputFile(generatedTables, tableDefs, schemas, relativePath);\n\n // If dry-run, return output without writing\n if (dryRun) {\n result.success = true;\n result.tablesGenerated = tableDefs.length;\n result.output = output;\n return result;\n }\n\n // Ensure output directory exists\n const outputDir = path.dirname(outputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, {\n recursive: true\n });\n }\n\n // Write output file\n fs.writeFileSync(outputPath, output);\n result.success = true;\n result.tablesGenerated = tableDefs.length;\n return result;\n}","/**\n * Parser for Supabase database.types.ts files\n *\n * Extracts table definitions and column types from the generated TypeScript types\n */\n\nimport type { TableConfig } from './config.js';\nexport interface ColumnInfo {\n name: string;\n tsType: string;\n isNullable: boolean;\n}\nexport interface ParsedTable {\n name: string;\n schema: string;\n columns: Map<string, string>;\n config: TableConfig;\n}\nexport interface ParseOptions {\n /** Columns to skip */\n skipColumns: Set<string>;\n /**\n * Include the id column (normally skipped).\n * Use for tables with integer PKs referenced by FKs in other tables.\n */\n syncPrimaryKey?: boolean;\n /** @deprecated Use `syncPrimaryKey` instead */\n includeId?: boolean;\n /** Only include these columns (overrides skipColumns if specified) */\n onlyColumns?: string[];\n}\n\n/**\n * Parse the Row type from a table definition and extract columns\n */\nexport function parseRowType(tableContent: string, options: ParseOptions): Map<string, string> {\n const columns = new Map<string, string>();\n\n // Find the Row block - handles nested braces in type definitions\n const rowMatch = tableContent.match(/Row:\\s*\\{([^}]+(?:\\{[^}]*\\}[^}]*)*)\\}/s);\n if (!rowMatch) return columns;\n const rowContent = rowMatch[1];\n\n // syncPrimaryKey takes precedence, with includeId as fallback for backwards compat\n const includePrimaryKey = options.syncPrimaryKey ?? options.includeId ?? false;\n\n // If onlyColumns is specified, use it as a whitelist (overrides skipColumns)\n const onlyColumnsSet = options.onlyColumns ? new Set(options.onlyColumns) : null;\n\n // Parse each column: \"columnName: type\" or \"columnName?: type\"\n const columnRegex = /(\\w+)\\??:\\s*([^,\\n]+)/g;\n let match;\n while ((match = columnRegex.exec(rowContent)) !== null) {\n const [, columnName, columnType] = match;\n\n // Determine if column should be included\n let shouldInclude: boolean;\n if (onlyColumnsSet) {\n // onlyColumns mode: only include explicitly listed columns\n // Exception: include 'id' if syncPrimaryKey is true\n shouldInclude = onlyColumnsSet.has(columnName) || includePrimaryKey && columnName === 'id';\n } else {\n // skipColumns mode: include unless explicitly skipped\n // Exception: include 'id' if syncPrimaryKey is true\n const isSkipped = options.skipColumns.has(columnName);\n shouldInclude = !isSkipped || includePrimaryKey && columnName === 'id';\n }\n if (shouldInclude) {\n columns.set(columnName, columnType.trim());\n }\n }\n return columns;\n}\n\n/**\n * Escape special regex characters in a string\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Extract a table definition from the database.types.ts content\n *\n * Uses bracket-counting to properly handle nested arrays in Relationships\n * (e.g., columns: [\"parentId\"] inside relationship objects)\n */\nexport function extractTableDef(content: string, tableName: string, schema: string): string | null {\n // Escape special characters in schema and table names for regex safety\n const escapedSchema = escapeRegex(schema);\n const escapedTableName = escapeRegex(tableName);\n\n // Find the schema section\n const schemaRegex = new RegExp(`${escapedSchema}:\\\\s*\\\\{[\\\\s\\\\S]*?Tables:\\\\s*\\\\{`, 'g');\n const schemaMatch = schemaRegex.exec(content);\n if (!schemaMatch) return null;\n const startIndex = schemaMatch.index;\n const searchContent = content.slice(startIndex);\n\n // Find the start of this specific table\n // Use negative lookbehind (?<![A-Za-z]) to avoid matching table names that are\n // substrings of other names (e.g., \"Tag\" in \"CommentTag\")\n const tableStartRegex = new RegExp(`(?<![A-Za-z])${escapedTableName}:\\\\s*\\\\{`, 'g');\n const tableStartMatch = tableStartRegex.exec(searchContent);\n if (!tableStartMatch) return null;\n\n // Use bracket counting to find the matching closing brace\n const tableStartIndex = tableStartMatch.index;\n const openBraceIndex = tableStartMatch.index + tableStartMatch[0].length - 1;\n let braceCount = 1;\n let i = openBraceIndex + 1;\n while (i < searchContent.length && braceCount > 0) {\n const char = searchContent[i];\n if (char === '{') braceCount++;else if (char === '}') braceCount--;\n i++;\n }\n if (braceCount !== 0) return null;\n return searchContent.slice(tableStartIndex, i);\n}\n\n/**\n * Parse a database.types.ts file and extract specified tables\n */\nexport function parseTypesFile(content: string, tables: TableConfig[], globalSkipColumns: Set<string>): ParsedTable[] {\n const parsedTables: ParsedTable[] = [];\n for (const tableConfig of tables) {\n const {\n name,\n schema = 'public',\n syncPrimaryKey,\n includeId,\n skipColumns: tableSkipColumns,\n onlyColumns\n } = tableConfig;\n const tableDef = extractTableDef(content, name, schema);\n if (!tableDef) {\n continue;\n }\n\n // Merge global and per-table skipColumns\n const mergedSkipColumns = new Set([...globalSkipColumns, ...(tableSkipColumns ?? [])]);\n const columns = parseRowType(tableDef, {\n skipColumns: mergedSkipColumns,\n syncPrimaryKey,\n includeId,\n onlyColumns\n });\n if (columns.size > 0) {\n parsedTables.push({\n name,\n schema,\n columns,\n config: tableConfig\n });\n }\n }\n return parsedTables;\n}\n\n/**\n * Get all available schemas from the types file\n */\nexport function getAvailableSchemas(content: string): string[] {\n const schemas: string[] = [];\n const schemaRegex = /(\\w+):\\s*\\{[\\s\\S]*?Tables:\\s*\\{/g;\n let match;\n while ((match = schemaRegex.exec(content)) !== null) {\n schemas.push(match[1]);\n }\n return schemas;\n}\n\n/**\n * Get all table names in a schema\n */\nexport function getTablesInSchema(content: string, schema: string): string[] {\n const tables: string[] = [];\n\n // Find the schema section\n const schemaRegex = new RegExp(`${schema}:\\\\s*\\\\{[\\\\s\\\\S]*?Tables:\\\\s*\\\\{([\\\\s\\\\S]*?)\\\\}\\\\s*Views:`, 'g');\n const schemaMatch = schemaRegex.exec(content);\n if (!schemaMatch) return tables;\n const tablesContent = schemaMatch[1];\n\n // Find table names (they're at the start of each table definition)\n const tableNameRegex = /^\\s*(\\w+):\\s*\\{/gm;\n let match;\n while ((match = tableNameRegex.exec(tablesContent)) !== null) {\n tables.push(match[1]);\n }\n return tables;\n}","/**\n * Output templates for PowerSync schema generation\n */\n\nimport type { ParsedTable } from './parser.js';\nexport interface IndexDefinition {\n name: string;\n columns: string[];\n}\n\n/**\n * Convert table name to snake_case for index naming\n */\nfunction toSnakeCase(str: string): string {\n return str.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase();\n}\n\n/**\n * Generate index definitions for a table based on column patterns\n *\n * @param tableName - The table name (PascalCase)\n * @param columns - Array of column names in the table\n * @param indexPatterns - Regex patterns to match against column names\n * @param additionalColumns - Specific column names to always index\n * @returns Array of index definitions\n */\nexport function generateIndexDefinitions(tableName: string, columns: string[], indexPatterns: string[], additionalColumns: string[] = []): IndexDefinition[] {\n const indexes: IndexDefinition[] = [];\n const snakeTableName = toSnakeCase(tableName);\n\n // Combine pattern matching and explicit columns\n const columnsToIndex = new Set<string>();\n\n // Pre-compile regex patterns with error handling\n const compiledPatterns: RegExp[] = [];\n for (const pattern of indexPatterns) {\n try {\n compiledPatterns.push(new RegExp(pattern));\n } catch {\n console.warn(`Warning: Invalid index pattern regex \"${pattern}\" - skipping`);\n }\n }\n\n // Match columns against patterns\n for (const column of columns) {\n // Skip 'id' column - it's the primary key and already indexed\n if (column === 'id') continue;\n for (const regex of compiledPatterns) {\n if (regex.test(column)) {\n columnsToIndex.add(column);\n break;\n }\n }\n }\n\n // Add explicitly specified columns (if they exist in the table)\n for (const column of additionalColumns) {\n if (columns.includes(column) && column !== 'id') {\n columnsToIndex.add(column);\n }\n }\n\n // Create index definitions\n for (const column of columnsToIndex) {\n const snakeColumn = toSnakeCase(column);\n indexes.push({\n name: `idx_${snakeTableName}_${snakeColumn}`,\n columns: [column]\n });\n }\n\n // Sort by index name for deterministic output\n indexes.sort((a, b) => a.name.localeCompare(b.name));\n return indexes;\n}\n\n/**\n * File header template\n */\nexport function generateHeader(typesPath: string): string {\n return `/**\n * PowerSync Schema Definition\n *\n * AUTO-GENERATED from ${typesPath}\n * Run: npx @pol-studios/powersync generate-schema\n *\n * DO NOT EDIT MANUALLY - changes will be overwritten\n */\n\nimport { column, Schema, Table } from \"@powersync/react-native\";\n`;\n}\n\n/**\n * Format indexes object for output (PowerSync SDK v1.32.0+ format)\n * Changed from array format [{ name, columns }] to object format { name: columns }\n */\nfunction formatIndexes(indexes: IndexDefinition[]): string {\n if (indexes.length === 0) return '';\n const indexLines = indexes.map(idx => {\n const columnsStr = idx.columns.map(c => `'${c}'`).join(', ');\n return ` '${idx.name}': [${columnsStr}],`;\n });\n return `indexes: {\\n${indexLines.join('\\n')}\\n }`;\n}\n\n/**\n * Generate the table definition for a parsed table\n */\nexport function generateTableDefinition(table: ParsedTable, columnDefs: string[], indexes: IndexDefinition[] = []): string {\n // Use alias if provided, otherwise use table name\n const effectiveName = table.config.alias ?? table.name;\n if (columnDefs.length === 0) {\n return `// ${effectiveName} - no syncable columns found`;\n }\n\n // Build options object\n const optionsParts: string[] = [];\n if (table.config.trackMetadata) {\n optionsParts.push('trackMetadata: true');\n }\n if (indexes.length > 0) {\n optionsParts.push(formatIndexes(indexes));\n }\n const optionsStr = optionsParts.length > 0 ? `, {\\n ${optionsParts.join(',\\n ')}\\n}` : '';\n return `const ${effectiveName} = new Table({\n${columnDefs.join('\\n')}\n}${optionsStr});`;\n}\n\n/**\n * Generate the table definition for a local-only table (not synced through PowerSync)\n */\nexport function generateLocalOnlyTableDefinition(table: ParsedTable, columnDefs: string[], indexes: IndexDefinition[] = []): string {\n // Use alias if provided, otherwise use table name\n const effectiveName = table.config.alias ?? table.name;\n if (columnDefs.length === 0) {\n return `// ${effectiveName} - no syncable columns found`;\n }\n\n // Build options object - always include localOnly: true\n const optionsParts: string[] = ['localOnly: true'];\n if (indexes.length > 0) {\n optionsParts.push(formatIndexes(indexes));\n }\n const optionsStr = `, {\\n ${optionsParts.join(',\\n ')}\\n}`;\n return `// Local-only table (not synced)\nconst ${effectiveName} = new Table({\n${columnDefs.join('\\n')}\n}${optionsStr});`;\n}\n\n/**\n * Generate the schema export section\n */\nexport function generateSchemaExport(tables: ParsedTable[]): string {\n // Use alias if provided, otherwise use table name\n const tableNames = tables.map(t => t.config.alias ?? t.name);\n return `// ============================================================================\n// SCHEMA EXPORT\n// ============================================================================\n\n// NOTE: photo_attachments is NOT included here.\n// The AttachmentQueue from @powersync/attachments creates and manages\n// its own internal SQLite table (not a view) during queue.init().\n// This allows INSERT/UPDATE operations to work correctly.\n\nexport const AppSchema = new Schema({\n${tableNames.map(name => ` ${name},`).join('\\n')}\n});\n\nexport type Database = (typeof AppSchema)[\"types\"];`;\n}\n\n/**\n * Generate schema mapping utilities\n */\nexport function generateSchemaMapping(tables: ParsedTable[], schemas: string[]): string {\n // Group tables by non-public schemas (use alias if provided)\n const schemaGroups = new Map<string, string[]>();\n for (const schema of schemas) {\n if (schema !== 'public') {\n schemaGroups.set(schema, []);\n }\n }\n for (const table of tables) {\n const effectiveName = table.config.alias ?? table.name;\n if (table.schema !== 'public' && schemaGroups.has(table.schema)) {\n schemaGroups.get(table.schema)!.push(effectiveName);\n }\n }\n const sections: string[] = [`// ============================================================================\n// SCHEMA MAPPING FOR CONNECTOR\n// ============================================================================`];\n\n // Generate constants for each non-public schema\n for (const [schema, tableNames] of schemaGroups) {\n if (tableNames.length > 0) {\n const constName = `${schema.toUpperCase()}_SCHEMA_TABLES`;\n sections.push(`\n// Tables in the '${schema}' schema (need .schema('${schema}') in Supabase queries)\nexport const ${constName} = new Set([\n${tableNames.map(name => ` \"${name}\",`).join('\\n')}\n]);`);\n }\n }\n\n // Generate helper function\n const schemaChecks = Array.from(schemaGroups.entries()).filter(([, names]) => names.length > 0).map(([schema]) => {\n const constName = `${schema.toUpperCase()}_SCHEMA_TABLES`;\n return ` if (${constName}.has(tableName)) return \"${schema}\";`;\n });\n if (schemaChecks.length > 0) {\n sections.push(`\n/**\n * Get the Supabase schema for a table\n */\nexport function getTableSchema(tableName: string): ${schemas.map(s => `\"${s}\"`).join(' | ')} {\n${schemaChecks.join('\\n')}\n return \"public\";\n}`);\n } else {\n sections.push(`\n/**\n * Get the Supabase schema for a table\n */\nexport function getTableSchema(tableName: string): \"public\" {\n return \"public\";\n}`);\n }\n return sections.join('\\n');\n}\n\n/**\n * Generate the FK detection utility (helpful for consumers)\n */\nexport function generateFKUtility(): string {\n return `\n// ============================================================================\n// FOREIGN KEY UTILITIES\n// ============================================================================\n\n/**\n * Check if a column name represents a foreign key reference\n * Convention: columns ending in 'Id' are foreign keys (e.g., projectId -> Project table)\n */\nexport function isForeignKeyColumn(columnName: string): boolean {\n return columnName.endsWith('Id') && columnName !== 'id';\n}\n\n/**\n * Get the referenced table name from a foreign key column\n * e.g., 'projectId' -> 'Project', 'equipmentFixtureUnitId' -> 'EquipmentFixtureUnit'\n */\nexport function getForeignKeyTable(columnName: string): string | null {\n if (!isForeignKeyColumn(columnName)) return null;\n // Remove 'Id' suffix and capitalize first letter\n const baseName = columnName.slice(0, -2);\n return baseName.charAt(0).toUpperCase() + baseName.slice(1);\n}`;\n}\n\n/**\n * Generate complete output file\n */\nexport function generateOutputFile(tables: ParsedTable[], tableDefs: string[], schemas: string[], typesPath: string): string {\n return `${generateHeader(typesPath)}\n\n// ============================================================================\n// TABLE DEFINITIONS\n// ============================================================================\n\n${tableDefs.join('\\n\\n')}\n\n${generateSchemaExport(tables)}\n\n${generateSchemaMapping(tables, ['public', ...schemas.filter(s => s !== 'public')])}\n${generateFKUtility()}\n`;\n}","/**\n * Foreign Key Dependency Detection\n *\n * Analyzes parsed tables to detect FK relationships and determine\n * optimal upload order for offline-first sync.\n */\n\nimport type { ParsedTable } from './parser.js';\nexport interface FKDependency {\n /** Table containing the FK column */\n table: string;\n /** FK column name (e.g., 'projectId') */\n column: string;\n /** Referenced table name (e.g., 'Project') */\n referencedTable: string;\n}\nexport interface DependencyGraph {\n /** Map of table -> tables it depends on (has FK references to) */\n dependencies: Map<string, string[]>;\n /** Map of table -> tables that depend on it (have FKs referencing this table) */\n dependents: Map<string, string[]>;\n /** Topologically sorted table names for optimal upload order */\n uploadOrder: string[];\n /** All detected FK relationships */\n fkRelationships: FKDependency[];\n}\n\n/**\n * Convert a FK column name to its referenced table name\n * Convention: columns ending in 'Id' reference the PascalCase table\n * e.g., projectId -> Project, equipmentUnitId -> EquipmentUnit\n */\nexport function fkColumnToTableName(columnName: string): string | null {\n if (!columnName.endsWith('Id') || columnName === 'id') {\n return null;\n }\n // Remove 'Id' suffix and capitalize first letter\n const baseName = columnName.slice(0, -2);\n return baseName.charAt(0).toUpperCase() + baseName.slice(1);\n}\n\n/**\n * Detect FK dependencies from parsed tables\n *\n * Uses naming convention: columns ending in 'Id' reference the PascalCase table\n * Only considers references to tables that are in the provided list (ignores external references)\n */\nexport function detectFKDependencies(tables: ParsedTable[]): DependencyGraph {\n const tableNames = new Set(tables.map(t => t.name));\n const dependencies = new Map<string, string[]>();\n const dependents = new Map<string, string[]>();\n const fkRelationships: FKDependency[] = [];\n\n // Initialize maps for all tables\n for (const table of tables) {\n dependencies.set(table.name, []);\n dependents.set(table.name, []);\n }\n\n // Detect FK relationships\n for (const table of tables) {\n for (const [columnName] of table.columns) {\n const referencedTable = fkColumnToTableName(columnName);\n\n // Only track references to tables in our schema\n if (referencedTable && tableNames.has(referencedTable)) {\n // This table depends on the referenced table\n const tableDeps = dependencies.get(table.name) || [];\n if (!tableDeps.includes(referencedTable)) {\n tableDeps.push(referencedTable);\n dependencies.set(table.name, tableDeps);\n }\n\n // The referenced table has this table as a dependent\n const refDeps = dependents.get(referencedTable) || [];\n if (!refDeps.includes(table.name)) {\n refDeps.push(table.name);\n dependents.set(referencedTable, refDeps);\n }\n\n // Record the FK relationship\n fkRelationships.push({\n table: table.name,\n column: columnName,\n referencedTable\n });\n }\n }\n }\n\n // Calculate upload order via topological sort\n const uploadOrder = getUploadOrder({\n dependencies\n });\n return {\n dependencies,\n dependents,\n uploadOrder,\n fkRelationships\n };\n}\n\n/**\n * Get optimal upload order using Kahn's topological sort algorithm\n *\n * Tables with no dependencies are uploaded first, then tables that depend on them, etc.\n * This ensures that when a row references another table, the referenced row exists first.\n */\nexport function getUploadOrder(graph: Pick<DependencyGraph, 'dependencies'>): string[] {\n const result: string[] = [];\n const inDegree = new Map<string, number>();\n const adjList = new Map<string, string[]>();\n\n // Initialize in-degree (number of dependencies) for each table\n for (const [table, deps] of graph.dependencies) {\n inDegree.set(table, deps.length);\n adjList.set(table, []);\n }\n\n // Build adjacency list (reverse of dependencies - who depends on this table)\n for (const [table, deps] of graph.dependencies) {\n for (const dep of deps) {\n const list = adjList.get(dep) || [];\n list.push(table);\n adjList.set(dep, list);\n }\n }\n\n // Start with tables that have no dependencies\n const queue: string[] = [];\n for (const [table, degree] of inDegree) {\n if (degree === 0) {\n queue.push(table);\n }\n }\n\n // Sort queue alphabetically for deterministic output\n queue.sort();\n\n // Process queue\n while (queue.length > 0) {\n const table = queue.shift()!;\n result.push(table);\n\n // Reduce in-degree for all tables that depend on this one\n const dependentTables = adjList.get(table) || [];\n for (const dependent of dependentTables) {\n const newDegree = (inDegree.get(dependent) || 0) - 1;\n inDegree.set(dependent, newDegree);\n if (newDegree === 0) {\n queue.push(dependent);\n // Keep queue sorted for deterministic output\n queue.sort();\n }\n }\n }\n\n // Check for cycles (if result doesn't include all tables)\n if (result.length < graph.dependencies.size) {\n // There's a cycle - just append remaining tables alphabetically\n const remaining = [...graph.dependencies.keys()].filter(t => !result.includes(t)).sort();\n result.push(...remaining);\n }\n return result;\n}\n\n/**\n * Get tables that have no dependencies (root tables)\n * These are typically reference/lookup tables like User, Project, etc.\n */\nexport function getRootTables(graph: DependencyGraph): string[] {\n const roots: string[] = [];\n for (const [table, deps] of graph.dependencies) {\n if (deps.length === 0) {\n roots.push(table);\n }\n }\n return roots.sort();\n}\n\n/**\n * Get tables that have no dependents (leaf tables)\n * These are typically transaction/event tables that reference other tables\n */\nexport function getLeafTables(graph: DependencyGraph): string[] {\n const leaves: string[] = [];\n for (const [table, deps] of graph.dependents) {\n if (deps.length === 0) {\n leaves.push(table);\n }\n }\n return leaves.sort();\n}\n\n/**\n * Format the dependency graph as a human-readable string\n */\nexport function formatDependencyGraph(graph: DependencyGraph): string {\n const lines: string[] = [];\n lines.push('FK Dependencies:');\n for (const fk of graph.fkRelationships) {\n lines.push(` ${fk.table}.${fk.column} -> ${fk.referencedTable}`);\n }\n if (graph.fkRelationships.length === 0) {\n lines.push(' (none detected)');\n }\n lines.push('');\n lines.push('Upload Order (topological):');\n graph.uploadOrder.forEach((table, i) => {\n const deps = graph.dependencies.get(table) || [];\n const depStr = deps.length > 0 ? ` (depends on: ${deps.join(', ')})` : ' (root)';\n lines.push(` ${i + 1}. ${table}${depStr}`);\n });\n return lines.join('\\n');\n}"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/generator/config.ts","../../src/generator/generator.ts","../../src/generator/parser.ts","../../src/generator/templates.ts","../../src/generator/fk-dependencies.ts"],"sourcesContent":["/**\n * Configuration types and helpers for PowerSync schema generator\n */\n\nexport interface TableConfig {\n /** Table name (PascalCase as it appears in database.types.ts) */\n name: string;\n /** Schema name (defaults to 'public') */\n schema?: string;\n /** Enable ps_crud timestamp tracking for optimistic UI updates */\n trackMetadata?: boolean;\n /**\n * Sync the primary key column (normally skipped as PowerSync handles it internally).\n *\n * Use this for tables with integer PKs that are referenced by FKs in other tables.\n * Example: `Group.id` is referenced by `UserGroup.groupId`, so Group needs `syncPrimaryKey: true`\n * to ensure the integer ID is available for client-side joins.\n */\n syncPrimaryKey?: boolean;\n /** @deprecated Use `syncPrimaryKey` instead */\n includeId?: boolean;\n /** Columns to skip for this specific table (in addition to global skipColumns) */\n skipColumns?: string[];\n /** Only include these columns (overrides skipColumns if specified) */\n onlyColumns?: string[];\n /** Alias for the table in PowerSync schema (for conflicting names across schemas) */\n alias?: string;\n /** Table is local-only (not synced through PowerSync) */\n localOnly?: boolean;\n}\nexport interface GeneratorConfig {\n /** Path to Supabase-generated database.types.ts file */\n typesPath: string;\n /** Output path for generated PowerSync schema */\n outputPath: string;\n /** Tables to include in the PowerSync schema */\n tables: TableConfig[];\n /** Columns to always skip (in addition to defaults like 'id') */\n skipColumns?: string[];\n /** Column name patterns that should use column.real for decimal values */\n decimalPatterns?: string[];\n /** Additional schemas to track (besides 'public' which is the default) */\n schemas?: string[];\n /** Generate indexes for FK and common columns (default: true) */\n autoIndexes?: boolean;\n /** Additional columns to index (exact column names) */\n indexColumns?: string[];\n /** Column patterns that should be indexed (regex patterns) */\n indexPatterns?: string[];\n}\n\n/**\n * Define a PowerSync generator configuration with type safety\n */\nexport function defineConfig(config: GeneratorConfig): GeneratorConfig {\n return config;\n}\n\n/**\n * Default columns that are skipped during generation\n */\nexport const DEFAULT_SKIP_COLUMNS = ['id',\n// PowerSync handles id automatically\n// Legacy numeric ID columns - typically not needed after UUID migration\n'legacyId'];\n\n/**\n * Default column name patterns that indicate decimal values\n */\nexport const DEFAULT_DECIMAL_PATTERNS = ['hours', 'watts', 'voltage', 'rate', 'amount', 'price', 'cost', 'total'];\n\n/**\n * Default column patterns that should be indexed\n * These are regex patterns matched against column names\n */\nexport const DEFAULT_INDEX_PATTERNS = ['Id$',\n// FK columns ending in Id (e.g., projectId, userId)\n'^createdAt$', '^updatedAt$', '^status$', '^type$'];\n\n/**\n * Required authentication/access control tables for offline auth\n * These tables are needed for proper offline access control\n */\nexport interface RequiredAuthTable {\n /** Table name (PascalCase) */\n name: string;\n /** Schema name */\n schema: string;\n /** Whether this table requires syncPrimaryKey to be true */\n requiresSyncPrimaryKey?: boolean;\n}\nexport const REQUIRED_AUTH_TABLES: RequiredAuthTable[] = [{\n name: 'UserAccess',\n schema: 'core'\n}, {\n name: 'UserGroup',\n schema: 'core'\n}, {\n name: 'GroupAccessKey',\n schema: 'core',\n requiresSyncPrimaryKey: true\n}, {\n name: 'Group',\n schema: 'core',\n requiresSyncPrimaryKey: true\n}];","/**\n * PowerSync schema generator\n *\n * Converts Supabase database.types.ts into PowerSync schema definitions\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { GeneratorConfig, TableConfig } from './config.js';\nimport { DEFAULT_SKIP_COLUMNS, DEFAULT_DECIMAL_PATTERNS, DEFAULT_INDEX_PATTERNS, REQUIRED_AUTH_TABLES } from './config.js';\nimport { parseTypesFile, type ParsedTable } from './parser.js';\nimport { generateTableDefinition, generateLocalOnlyTableDefinition, generateOutputFile, generateIndexDefinitions, type IndexDefinition } from './templates.js';\nimport { detectFKDependencies, type DependencyGraph } from './fk-dependencies.js';\nexport interface ColumnMapping {\n type: 'column.text' | 'column.integer' | 'column.real';\n isEnum?: boolean;\n isBoolean?: boolean;\n isJson?: boolean;\n}\nexport interface GenerateResult {\n success: boolean;\n tablesGenerated: number;\n outputPath: string;\n errors: string[];\n warnings: string[];\n /** Generated output (included when dryRun is true) */\n output?: string;\n /** Number of indexes generated */\n indexesGenerated?: number;\n /** FK dependency graph (when detected) */\n dependencyGraph?: DependencyGraph;\n}\n\n/**\n * Map TypeScript types to PowerSync column types\n */\nexport function mapTypeToPowerSync(tsType: string, columnName: string, decimalPatterns: string[]): ColumnMapping | null {\n // Clean up the type (remove nullability)\n const cleanType = tsType.trim().replace(/\\s*\\|\\s*null/g, '');\n\n // JSON types -> store as TEXT (will be parsed/stringified by type-transformer)\n if (cleanType.includes('Json')) {\n return {\n type: 'column.text',\n isJson: true\n };\n }\n\n // Skip complex types that can't be stored in SQLite\n if (cleanType.includes('unknown') || cleanType.includes('{')) {\n return null;\n }\n\n // Array types - skip\n if (cleanType.includes('[]')) {\n return null;\n }\n\n // Boolean -> integer (0/1)\n if (cleanType === 'boolean') {\n return {\n type: 'column.integer',\n isBoolean: true\n };\n }\n\n // Number types\n if (cleanType === 'number') {\n // Use real for columns that might have decimals\n if (decimalPatterns.some(pattern => columnName.toLowerCase().includes(pattern.toLowerCase()))) {\n return {\n type: 'column.real'\n };\n }\n return {\n type: 'column.integer'\n };\n }\n\n // String types\n if (cleanType === 'string') {\n return {\n type: 'column.text'\n };\n }\n\n // Enum types (Database[\"schema\"][\"Enums\"][\"EnumName\"]) -> store as text\n if (cleanType.includes('Database[') && cleanType.includes('Enums')) {\n return {\n type: 'column.text',\n isEnum: true\n };\n }\n\n // Default to text for unknown types (likely enums or other string-like types)\n return {\n type: 'column.text'\n };\n}\n\n/**\n * Generate column definitions for a table\n */\nexport function generateColumnDefs(table: ParsedTable, decimalPatterns: string[]): string[] {\n const columnDefs: string[] = [];\n for (const [columnName, tsType] of table.columns) {\n const mapping = mapTypeToPowerSync(tsType, columnName, decimalPatterns);\n if (mapping) {\n // Add comment for boolean, enum, and json columns\n let comment = '';\n if (mapping.isBoolean) {\n comment = ' // boolean stored as 0/1';\n } else if (mapping.isEnum) {\n comment = ' // enum stored as text';\n } else if (mapping.isJson) {\n comment = ' // JSON stored as text';\n }\n columnDefs.push(` ${columnName}: ${mapping.type},${comment}`);\n }\n }\n return columnDefs;\n}\n\n/**\n * Validate that required auth tables are included in config\n * Returns warnings for missing tables or misconfigured tables\n */\nexport function validateAuthTables(tables: TableConfig[]): string[] {\n const warnings: string[] = [];\n for (const authTable of REQUIRED_AUTH_TABLES) {\n const configTable = tables.find(t => t.name === authTable.name && (t.schema ?? 'public') === authTable.schema);\n if (!configTable) {\n warnings.push(`Missing required auth table: ${authTable.schema}.${authTable.name} - offline access control may not work correctly`);\n } else if (authTable.requiresSyncPrimaryKey && !configTable.syncPrimaryKey) {\n warnings.push(`Auth table ${authTable.schema}.${authTable.name} should have syncPrimaryKey: true for proper FK references`);\n }\n }\n return warnings;\n}\n\n/**\n * Validate FK references to ensure all referenced tables are in the config\n * Returns warnings for missing FK targets\n */\nexport function validateFKReferences(dependencyGraph: DependencyGraph, configuredTables: Set<string>): string[] {\n const warnings: string[] = [];\n for (const fk of dependencyGraph.fkRelationships) {\n if (!configuredTables.has(fk.referencedTable)) {\n warnings.push(`FK reference ${fk.table}.${fk.column} references table '${fk.referencedTable}' which is not in the config`);\n }\n }\n return warnings;\n}\n\n/**\n * Generate PowerSync schema from configuration\n */\nexport async function generateSchema(config: GeneratorConfig, options?: {\n cwd?: string;\n verbose?: boolean;\n dryRun?: boolean;\n}): Promise<GenerateResult> {\n const cwd = options?.cwd ?? process.cwd();\n const verbose = options?.verbose ?? false;\n const dryRun = options?.dryRun ?? false;\n const result: GenerateResult = {\n success: false,\n tablesGenerated: 0,\n outputPath: '',\n errors: [],\n warnings: []\n };\n\n // Resolve paths relative to cwd\n const typesPath = path.isAbsolute(config.typesPath) ? config.typesPath : path.resolve(cwd, config.typesPath);\n const outputPath = path.isAbsolute(config.outputPath) ? config.outputPath : path.resolve(cwd, config.outputPath);\n result.outputPath = outputPath;\n\n // Validate required auth tables\n const authWarnings = validateAuthTables(config.tables);\n result.warnings.push(...authWarnings);\n\n // Check if types file exists\n if (!fs.existsSync(typesPath)) {\n result.errors.push(`Types file not found: ${typesPath}`);\n return result;\n }\n\n // Read types file\n if (verbose) {\n console.log(`Reading types from: ${typesPath}`);\n }\n const typesContent = fs.readFileSync(typesPath, 'utf-8');\n\n // Build skip columns set\n const skipColumns = new Set([...DEFAULT_SKIP_COLUMNS, ...(config.skipColumns ?? [])]);\n\n // Build decimal patterns\n const decimalPatterns = [...DEFAULT_DECIMAL_PATTERNS, ...(config.decimalPatterns ?? [])];\n\n // Parse tables from types file\n const parsedTables = parseTypesFile(typesContent, config.tables, skipColumns);\n\n // Check for tables that weren't found\n for (const tableConfig of config.tables) {\n const found = parsedTables.some(t => t.name === tableConfig.name);\n if (!found) {\n result.warnings.push(`Table '${tableConfig.name}' not found in schema '${tableConfig.schema ?? 'public'}'`);\n }\n }\n if (parsedTables.length === 0) {\n result.errors.push('No tables were parsed successfully');\n return result;\n }\n\n // Build index patterns (auto-indexes enabled by default)\n const autoIndexes = config.autoIndexes ?? true;\n const indexPatterns = autoIndexes ? [...DEFAULT_INDEX_PATTERNS, ...(config.indexPatterns ?? [])] : config.indexPatterns ?? [];\n const indexColumns = config.indexColumns ?? [];\n\n // Detect FK dependencies\n const dependencyGraph = detectFKDependencies(parsedTables);\n result.dependencyGraph = dependencyGraph;\n\n // Validate FK references - warn if any FK targets a table not in config\n const configuredTableNames = new Set(config.tables.map(t => t.name));\n const fkWarnings = validateFKReferences(dependencyGraph, configuredTableNames);\n result.warnings.push(...fkWarnings);\n if (verbose && dependencyGraph.fkRelationships.length > 0) {\n console.log(`\\nFK Dependencies detected: ${dependencyGraph.fkRelationships.length}`);\n for (const fk of dependencyGraph.fkRelationships) {\n console.log(` ${fk.table}.${fk.column} -> ${fk.referencedTable}`);\n }\n console.log(`\\nRecommended upload order:`);\n dependencyGraph.uploadOrder.forEach((table, i) => {\n console.log(` ${i + 1}. ${table}`);\n });\n console.log('');\n }\n\n // Generate table definitions - separate synced and local-only tables\n const syncedTableDefs: string[] = [];\n const localOnlyTableDefs: string[] = [];\n let totalIndexes = 0;\n for (const table of parsedTables) {\n const isLocalOnly = table.config.localOnly ?? false;\n const tableAlias = table.config.alias;\n if (verbose) {\n const syncPK = table.config.syncPrimaryKey || table.config.includeId;\n const flags = [table.config.trackMetadata ? '[trackMetadata]' : '', syncPK ? '[syncPrimaryKey]' : '', isLocalOnly ? '[localOnly]' : '', tableAlias ? `[alias: ${tableAlias}]` : ''].filter(Boolean).join(' ');\n console.log(`Processing ${table.schema}.${table.name} (${table.columns.size} columns)${flags ? ' ' + flags : ''}`);\n }\n const columnDefs = generateColumnDefs(table, decimalPatterns);\n if (columnDefs.length === 0) {\n result.warnings.push(`Table '${table.name}' has no syncable columns`);\n continue;\n }\n\n // Generate indexes for this table (use alias for index naming if provided)\n const effectiveTableName = tableAlias ?? table.name;\n const columnNames = [...table.columns.keys()];\n const indexes = indexPatterns.length > 0 || indexColumns.length > 0 ? generateIndexDefinitions(effectiveTableName, columnNames, indexPatterns, indexColumns) : [];\n totalIndexes += indexes.length;\n if (verbose && indexes.length > 0) {\n console.log(` Indexes: ${indexes.map(i => i.name).join(', ')}`);\n }\n\n // Generate table definition based on localOnly flag\n if (isLocalOnly) {\n localOnlyTableDefs.push(generateLocalOnlyTableDefinition(table, columnDefs, indexes));\n } else {\n syncedTableDefs.push(generateTableDefinition(table, columnDefs, indexes));\n }\n }\n\n // Combine synced and local-only table definitions\n const tableDefs = [...syncedTableDefs, ...localOnlyTableDefs];\n result.indexesGenerated = totalIndexes;\n\n // Collect unique schemas\n const schemas = [...new Set(config.tables.map(t => t.schema ?? 'public'))];\n\n // Generate output file content\n const relativePath = path.relative(cwd, typesPath);\n // Filter tables that were successfully generated (check for both name and alias)\n const generatedTables = parsedTables.filter(t => {\n const effectiveName = t.config.alias ?? t.name;\n return tableDefs.some(def => def.includes(`const ${effectiveName} =`));\n });\n const output = generateOutputFile(generatedTables, tableDefs, schemas, relativePath);\n\n // If dry-run, return output without writing\n if (dryRun) {\n result.success = true;\n result.tablesGenerated = tableDefs.length;\n result.output = output;\n return result;\n }\n\n // Ensure output directory exists\n const outputDir = path.dirname(outputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, {\n recursive: true\n });\n }\n\n // Write output file\n fs.writeFileSync(outputPath, output);\n result.success = true;\n result.tablesGenerated = tableDefs.length;\n return result;\n}","/**\n * Parser for Supabase database.types.ts files\n *\n * Extracts table definitions and column types from the generated TypeScript types\n */\n\nimport type { TableConfig } from './config.js';\nexport interface ColumnInfo {\n name: string;\n tsType: string;\n isNullable: boolean;\n}\nexport interface ParsedTable {\n name: string;\n schema: string;\n columns: Map<string, string>;\n config: TableConfig;\n}\nexport interface ParseOptions {\n /** Columns to skip */\n skipColumns: Set<string>;\n /**\n * Include the id column (normally skipped).\n * Use for tables with integer PKs referenced by FKs in other tables.\n */\n syncPrimaryKey?: boolean;\n /** @deprecated Use `syncPrimaryKey` instead */\n includeId?: boolean;\n /** Only include these columns (overrides skipColumns if specified) */\n onlyColumns?: string[];\n}\n\n/**\n * Parse the Row type from a table definition and extract columns\n */\nexport function parseRowType(tableContent: string, options: ParseOptions): Map<string, string> {\n const columns = new Map<string, string>();\n\n // Find the Row block - handles nested braces in type definitions\n const rowMatch = tableContent.match(/Row:\\s*\\{([^}]+(?:\\{[^}]*\\}[^}]*)*)\\}/s);\n if (!rowMatch) return columns;\n const rowContent = rowMatch[1];\n\n // syncPrimaryKey takes precedence, with includeId as fallback for backwards compat\n const includePrimaryKey = options.syncPrimaryKey ?? options.includeId ?? false;\n\n // If onlyColumns is specified, use it as a whitelist (overrides skipColumns)\n const onlyColumnsSet = options.onlyColumns ? new Set(options.onlyColumns) : null;\n\n // Parse each column: \"columnName: type\" or \"columnName?: type\"\n const columnRegex = /(\\w+)\\??:\\s*([^,\\n]+)/g;\n let match;\n while ((match = columnRegex.exec(rowContent)) !== null) {\n const [, columnName, columnType] = match;\n\n // Determine if column should be included\n let shouldInclude: boolean;\n if (onlyColumnsSet) {\n // onlyColumns mode: only include explicitly listed columns\n // Exception: include 'id' if syncPrimaryKey is true\n shouldInclude = onlyColumnsSet.has(columnName) || includePrimaryKey && columnName === 'id';\n } else {\n // skipColumns mode: include unless explicitly skipped\n // Exception: include 'id' if syncPrimaryKey is true\n const isSkipped = options.skipColumns.has(columnName);\n shouldInclude = !isSkipped || includePrimaryKey && columnName === 'id';\n }\n if (shouldInclude) {\n columns.set(columnName, columnType.trim());\n }\n }\n return columns;\n}\n\n/**\n * Escape special regex characters in a string\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Extract a table definition from the database.types.ts content\n *\n * Uses bracket-counting to properly handle nested arrays in Relationships\n * (e.g., columns: [\"parentId\"] inside relationship objects)\n */\nexport function extractTableDef(content: string, tableName: string, schema: string): string | null {\n // Escape special characters in schema and table names for regex safety\n const escapedSchema = escapeRegex(schema);\n const escapedTableName = escapeRegex(tableName);\n\n // Find the schema section\n const schemaRegex = new RegExp(`${escapedSchema}:\\\\s*\\\\{[\\\\s\\\\S]*?Tables:\\\\s*\\\\{`, 'g');\n const schemaMatch = schemaRegex.exec(content);\n if (!schemaMatch) return null;\n const startIndex = schemaMatch.index;\n const searchContent = content.slice(startIndex);\n\n // Find the start of this specific table\n // Use negative lookbehind (?<![A-Za-z]) to avoid matching table names that are\n // substrings of other names (e.g., \"Tag\" in \"CommentTag\")\n const tableStartRegex = new RegExp(`(?<![A-Za-z])${escapedTableName}:\\\\s*\\\\{`, 'g');\n const tableStartMatch = tableStartRegex.exec(searchContent);\n if (!tableStartMatch) return null;\n\n // Use bracket counting to find the matching closing brace\n const tableStartIndex = tableStartMatch.index;\n const openBraceIndex = tableStartMatch.index + tableStartMatch[0].length - 1;\n let braceCount = 1;\n let i = openBraceIndex + 1;\n while (i < searchContent.length && braceCount > 0) {\n const char = searchContent[i];\n if (char === '{') braceCount++;else if (char === '}') braceCount--;\n i++;\n }\n if (braceCount !== 0) return null;\n return searchContent.slice(tableStartIndex, i);\n}\n\n/**\n * Parse a database.types.ts file and extract specified tables\n */\nexport function parseTypesFile(content: string, tables: TableConfig[], globalSkipColumns: Set<string>): ParsedTable[] {\n const parsedTables: ParsedTable[] = [];\n for (const tableConfig of tables) {\n const {\n name,\n schema = 'public',\n syncPrimaryKey,\n includeId,\n skipColumns: tableSkipColumns,\n onlyColumns\n } = tableConfig;\n const tableDef = extractTableDef(content, name, schema);\n if (!tableDef) {\n continue;\n }\n\n // Merge global and per-table skipColumns\n const mergedSkipColumns = new Set([...globalSkipColumns, ...(tableSkipColumns ?? [])]);\n const columns = parseRowType(tableDef, {\n skipColumns: mergedSkipColumns,\n syncPrimaryKey,\n includeId,\n onlyColumns\n });\n if (columns.size > 0) {\n parsedTables.push({\n name,\n schema,\n columns,\n config: tableConfig\n });\n }\n }\n return parsedTables;\n}\n\n/**\n * Get all available schemas from the types file\n */\nexport function getAvailableSchemas(content: string): string[] {\n const schemas: string[] = [];\n const schemaRegex = /(\\w+):\\s*\\{[\\s\\S]*?Tables:\\s*\\{/g;\n let match;\n while ((match = schemaRegex.exec(content)) !== null) {\n schemas.push(match[1]);\n }\n return schemas;\n}\n\n/**\n * Get all table names in a schema\n */\nexport function getTablesInSchema(content: string, schema: string): string[] {\n const tables: string[] = [];\n\n // Find the schema section\n const schemaRegex = new RegExp(`${schema}:\\\\s*\\\\{[\\\\s\\\\S]*?Tables:\\\\s*\\\\{([\\\\s\\\\S]*?)\\\\}\\\\s*Views:`, 'g');\n const schemaMatch = schemaRegex.exec(content);\n if (!schemaMatch) return tables;\n const tablesContent = schemaMatch[1];\n\n // Find table names (they're at the start of each table definition)\n const tableNameRegex = /^\\s*(\\w+):\\s*\\{/gm;\n let match;\n while ((match = tableNameRegex.exec(tablesContent)) !== null) {\n tables.push(match[1]);\n }\n return tables;\n}","/**\n * Output templates for PowerSync schema generation\n */\n\nimport type { ParsedTable } from './parser.js';\nexport interface IndexDefinition {\n name: string;\n columns: string[];\n}\n\n/**\n * Convert table name to snake_case for index naming\n */\nfunction toSnakeCase(str: string): string {\n return str.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase();\n}\n\n/**\n * Generate index definitions for a table based on column patterns\n *\n * @param tableName - The table name (PascalCase)\n * @param columns - Array of column names in the table\n * @param indexPatterns - Regex patterns to match against column names\n * @param additionalColumns - Specific column names to always index\n * @returns Array of index definitions\n */\nexport function generateIndexDefinitions(tableName: string, columns: string[], indexPatterns: string[], additionalColumns: string[] = []): IndexDefinition[] {\n const indexes: IndexDefinition[] = [];\n const snakeTableName = toSnakeCase(tableName);\n\n // Combine pattern matching and explicit columns\n const columnsToIndex = new Set<string>();\n\n // Pre-compile regex patterns with error handling\n const compiledPatterns: RegExp[] = [];\n for (const pattern of indexPatterns) {\n try {\n compiledPatterns.push(new RegExp(pattern));\n } catch {\n console.warn(`Warning: Invalid index pattern regex \"${pattern}\" - skipping`);\n }\n }\n\n // Match columns against patterns\n for (const column of columns) {\n // Skip 'id' column - it's the primary key and already indexed\n if (column === 'id') continue;\n for (const regex of compiledPatterns) {\n if (regex.test(column)) {\n columnsToIndex.add(column);\n break;\n }\n }\n }\n\n // Add explicitly specified columns (if they exist in the table)\n for (const column of additionalColumns) {\n if (columns.includes(column) && column !== 'id') {\n columnsToIndex.add(column);\n }\n }\n\n // Create index definitions\n for (const column of columnsToIndex) {\n const snakeColumn = toSnakeCase(column);\n indexes.push({\n name: `idx_${snakeTableName}_${snakeColumn}`,\n columns: [column]\n });\n }\n\n // Sort by index name for deterministic output\n indexes.sort((a, b) => a.name.localeCompare(b.name));\n return indexes;\n}\n\n/**\n * File header template\n */\nexport function generateHeader(typesPath: string): string {\n return `/**\n * PowerSync Schema Definition\n *\n * AUTO-GENERATED from ${typesPath}\n * Run: npx @pol-studios/powersync generate-schema\n *\n * DO NOT EDIT MANUALLY - changes will be overwritten\n */\n\nimport { column, Schema, Table } from \"@powersync/react-native\";\n`;\n}\n\n/**\n * Format indexes object for output (PowerSync SDK v1.32.0+ format)\n * Changed from array format [{ name, columns }] to object format { name: columns }\n */\nfunction formatIndexes(indexes: IndexDefinition[]): string {\n if (indexes.length === 0) return '';\n const indexLines = indexes.map(idx => {\n const columnsStr = idx.columns.map(c => `'${c}'`).join(', ');\n return ` '${idx.name}': [${columnsStr}],`;\n });\n return `indexes: {\\n${indexLines.join('\\n')}\\n }`;\n}\n\n/**\n * Generate the table definition for a parsed table\n */\nexport function generateTableDefinition(table: ParsedTable, columnDefs: string[], indexes: IndexDefinition[] = []): string {\n // Use alias if provided, otherwise use table name\n const effectiveName = table.config.alias ?? table.name;\n if (columnDefs.length === 0) {\n return `// ${effectiveName} - no syncable columns found`;\n }\n\n // Build options object\n const optionsParts: string[] = [];\n if (table.config.trackMetadata) {\n optionsParts.push('trackMetadata: true');\n }\n if (indexes.length > 0) {\n optionsParts.push(formatIndexes(indexes));\n }\n const optionsStr = optionsParts.length > 0 ? `, {\\n ${optionsParts.join(',\\n ')}\\n}` : '';\n return `const ${effectiveName} = new Table({\n${columnDefs.join('\\n')}\n}${optionsStr});`;\n}\n\n/**\n * Generate the table definition for a local-only table (not synced through PowerSync)\n */\nexport function generateLocalOnlyTableDefinition(table: ParsedTable, columnDefs: string[], indexes: IndexDefinition[] = []): string {\n // Use alias if provided, otherwise use table name\n const effectiveName = table.config.alias ?? table.name;\n if (columnDefs.length === 0) {\n return `// ${effectiveName} - no syncable columns found`;\n }\n\n // Build options object - always include localOnly: true\n const optionsParts: string[] = ['localOnly: true'];\n if (indexes.length > 0) {\n optionsParts.push(formatIndexes(indexes));\n }\n const optionsStr = `, {\\n ${optionsParts.join(',\\n ')}\\n}`;\n return `// Local-only table (not synced)\nconst ${effectiveName} = new Table({\n${columnDefs.join('\\n')}\n}${optionsStr});`;\n}\n\n/**\n * Generate the schema export section\n */\nexport function generateSchemaExport(tables: ParsedTable[]): string {\n // Use alias if provided, otherwise use table name\n const tableNames = tables.map(t => t.config.alias ?? t.name);\n return `// ============================================================================\n// SCHEMA EXPORT\n// ============================================================================\n\n// NOTE: photo_attachments is NOT included here.\n// The AttachmentQueue from @powersync/attachments creates and manages\n// its own internal SQLite table (not a view) during queue.init().\n// This allows INSERT/UPDATE operations to work correctly.\n\nexport const AppSchema = new Schema({\n${tableNames.map(name => ` ${name},`).join('\\n')}\n});\n\nexport type Database = (typeof AppSchema)[\"types\"];`;\n}\n\n/**\n * Generate schema mapping utilities\n */\nexport function generateSchemaMapping(tables: ParsedTable[], schemas: string[]): string {\n // Group tables by non-public schemas (use alias if provided)\n const schemaGroups = new Map<string, string[]>();\n for (const schema of schemas) {\n if (schema !== 'public') {\n schemaGroups.set(schema, []);\n }\n }\n for (const table of tables) {\n const effectiveName = table.config.alias ?? table.name;\n if (table.schema !== 'public' && schemaGroups.has(table.schema)) {\n schemaGroups.get(table.schema)!.push(effectiveName);\n }\n }\n const sections: string[] = [`// ============================================================================\n// SCHEMA MAPPING FOR CONNECTOR\n// ============================================================================`];\n\n // Generate constants for each non-public schema\n for (const [schema, tableNames] of schemaGroups) {\n if (tableNames.length > 0) {\n const constName = `${schema.toUpperCase()}_SCHEMA_TABLES`;\n sections.push(`\n// Tables in the '${schema}' schema (need .schema('${schema}') in Supabase queries)\nexport const ${constName} = new Set([\n${tableNames.map(name => ` \"${name}\",`).join('\\n')}\n]);`);\n }\n }\n\n // Generate helper function\n const schemaChecks = Array.from(schemaGroups.entries()).filter(([, names]) => names.length > 0).map(([schema]) => {\n const constName = `${schema.toUpperCase()}_SCHEMA_TABLES`;\n return ` if (${constName}.has(tableName)) return \"${schema}\";`;\n });\n if (schemaChecks.length > 0) {\n sections.push(`\n/**\n * Get the Supabase schema for a table\n */\nexport function getTableSchema(tableName: string): ${schemas.map(s => `\"${s}\"`).join(' | ')} {\n${schemaChecks.join('\\n')}\n return \"public\";\n}`);\n } else {\n sections.push(`\n/**\n * Get the Supabase schema for a table\n */\nexport function getTableSchema(tableName: string): \"public\" {\n return \"public\";\n}`);\n }\n return sections.join('\\n');\n}\n\n/**\n * Generate the FK detection utility (helpful for consumers)\n */\nexport function generateFKUtility(): string {\n return `\n// ============================================================================\n// FOREIGN KEY UTILITIES\n// ============================================================================\n\n/**\n * Check if a column name represents a foreign key reference\n * Convention: columns ending in 'Id' are foreign keys (e.g., projectId -> Project table)\n */\nexport function isForeignKeyColumn(columnName: string): boolean {\n return columnName.endsWith('Id') && columnName !== 'id';\n}\n\n/**\n * Get the referenced table name from a foreign key column\n * e.g., 'projectId' -> 'Project', 'equipmentFixtureUnitId' -> 'EquipmentFixtureUnit'\n */\nexport function getForeignKeyTable(columnName: string): string | null {\n if (!isForeignKeyColumn(columnName)) return null;\n // Remove 'Id' suffix and capitalize first letter\n const baseName = columnName.slice(0, -2);\n return baseName.charAt(0).toUpperCase() + baseName.slice(1);\n}`;\n}\n\n/**\n * Generate complete output file\n */\nexport function generateOutputFile(tables: ParsedTable[], tableDefs: string[], schemas: string[], typesPath: string): string {\n return `${generateHeader(typesPath)}\n\n// ============================================================================\n// TABLE DEFINITIONS\n// ============================================================================\n\n${tableDefs.join('\\n\\n')}\n\n${generateSchemaExport(tables)}\n\n${generateSchemaMapping(tables, ['public', ...schemas.filter(s => s !== 'public')])}\n${generateFKUtility()}\n`;\n}","/**\n * Foreign Key Dependency Detection\n *\n * Analyzes parsed tables to detect FK relationships and determine\n * optimal upload order for offline-first sync.\n */\n\nimport type { ParsedTable } from './parser.js';\nexport interface FKDependency {\n /** Table containing the FK column */\n table: string;\n /** FK column name (e.g., 'projectId') */\n column: string;\n /** Referenced table name (e.g., 'Project') */\n referencedTable: string;\n}\nexport interface DependencyGraph {\n /** Map of table -> tables it depends on (has FK references to) */\n dependencies: Map<string, string[]>;\n /** Map of table -> tables that depend on it (have FKs referencing this table) */\n dependents: Map<string, string[]>;\n /** Topologically sorted table names for optimal upload order */\n uploadOrder: string[];\n /** All detected FK relationships */\n fkRelationships: FKDependency[];\n}\n\n/**\n * Convert a FK column name to its referenced table name\n * Convention: columns ending in 'Id' reference the PascalCase table\n * e.g., projectId -> Project, equipmentUnitId -> EquipmentUnit\n */\nexport function fkColumnToTableName(columnName: string): string | null {\n if (!columnName.endsWith('Id') || columnName === 'id') {\n return null;\n }\n // Remove 'Id' suffix and capitalize first letter\n const baseName = columnName.slice(0, -2);\n return baseName.charAt(0).toUpperCase() + baseName.slice(1);\n}\n\n/**\n * Detect FK dependencies from parsed tables\n *\n * Uses naming convention: columns ending in 'Id' reference the PascalCase table\n * Only considers references to tables that are in the provided list (ignores external references)\n */\nexport function detectFKDependencies(tables: ParsedTable[]): DependencyGraph {\n const tableNames = new Set(tables.map(t => t.name));\n const dependencies = new Map<string, string[]>();\n const dependents = new Map<string, string[]>();\n const fkRelationships: FKDependency[] = [];\n\n // Initialize maps for all tables\n for (const table of tables) {\n dependencies.set(table.name, []);\n dependents.set(table.name, []);\n }\n\n // Detect FK relationships\n for (const table of tables) {\n for (const [columnName] of table.columns) {\n const referencedTable = fkColumnToTableName(columnName);\n\n // Only track references to tables in our schema\n if (referencedTable && tableNames.has(referencedTable)) {\n // This table depends on the referenced table\n const tableDeps = dependencies.get(table.name) || [];\n if (!tableDeps.includes(referencedTable)) {\n tableDeps.push(referencedTable);\n dependencies.set(table.name, tableDeps);\n }\n\n // The referenced table has this table as a dependent\n const refDeps = dependents.get(referencedTable) || [];\n if (!refDeps.includes(table.name)) {\n refDeps.push(table.name);\n dependents.set(referencedTable, refDeps);\n }\n\n // Record the FK relationship\n fkRelationships.push({\n table: table.name,\n column: columnName,\n referencedTable\n });\n }\n }\n }\n\n // Calculate upload order via topological sort\n const uploadOrder = getUploadOrder({\n dependencies\n });\n return {\n dependencies,\n dependents,\n uploadOrder,\n fkRelationships\n };\n}\n\n/**\n * Get optimal upload order using Kahn's topological sort algorithm\n *\n * Tables with no dependencies are uploaded first, then tables that depend on them, etc.\n * This ensures that when a row references another table, the referenced row exists first.\n */\nexport function getUploadOrder(graph: Pick<DependencyGraph, 'dependencies'>): string[] {\n const result: string[] = [];\n const inDegree = new Map<string, number>();\n const adjList = new Map<string, string[]>();\n\n // Initialize in-degree (number of dependencies) for each table\n for (const [table, deps] of graph.dependencies) {\n inDegree.set(table, deps.length);\n adjList.set(table, []);\n }\n\n // Build adjacency list (reverse of dependencies - who depends on this table)\n for (const [table, deps] of graph.dependencies) {\n for (const dep of deps) {\n const list = adjList.get(dep) || [];\n list.push(table);\n adjList.set(dep, list);\n }\n }\n\n // Start with tables that have no dependencies\n const queue: string[] = [];\n for (const [table, degree] of inDegree) {\n if (degree === 0) {\n queue.push(table);\n }\n }\n\n // Sort queue alphabetically for deterministic output\n queue.sort();\n\n // Process queue\n while (queue.length > 0) {\n const table = queue.shift()!;\n result.push(table);\n\n // Reduce in-degree for all tables that depend on this one\n const dependentTables = adjList.get(table) || [];\n for (const dependent of dependentTables) {\n const newDegree = (inDegree.get(dependent) || 0) - 1;\n inDegree.set(dependent, newDegree);\n if (newDegree === 0) {\n queue.push(dependent);\n // Keep queue sorted for deterministic output\n queue.sort();\n }\n }\n }\n\n // Check for cycles (if result doesn't include all tables)\n if (result.length < graph.dependencies.size) {\n // There's a cycle - just append remaining tables alphabetically\n const remaining = [...graph.dependencies.keys()].filter(t => !result.includes(t)).sort();\n result.push(...remaining);\n }\n return result;\n}\n\n/**\n * Get tables that have no dependencies (root tables)\n * These are typically reference/lookup tables like User, Project, etc.\n */\nexport function getRootTables(graph: DependencyGraph): string[] {\n const roots: string[] = [];\n for (const [table, deps] of graph.dependencies) {\n if (deps.length === 0) {\n roots.push(table);\n }\n }\n return roots.sort();\n}\n\n/**\n * Get tables that have no dependents (leaf tables)\n * These are typically transaction/event tables that reference other tables\n */\nexport function getLeafTables(graph: DependencyGraph): string[] {\n const leaves: string[] = [];\n for (const [table, deps] of graph.dependents) {\n if (deps.length === 0) {\n leaves.push(table);\n }\n }\n return leaves.sort();\n}\n\n/**\n * Format the dependency graph as a human-readable string\n */\nexport function formatDependencyGraph(graph: DependencyGraph): string {\n const lines: string[] = [];\n lines.push('FK Dependencies:');\n for (const fk of graph.fkRelationships) {\n lines.push(` ${fk.table}.${fk.column} -> ${fk.referencedTable}`);\n }\n if (graph.fkRelationships.length === 0) {\n lines.push(' (none detected)');\n }\n lines.push('');\n lines.push('Upload Order (topological):');\n graph.uploadOrder.forEach((table, i) => {\n const deps = graph.dependencies.get(table) || [];\n const depStr = deps.length > 0 ? ` (depends on: ${deps.join(', ')})` : ' (root)';\n lines.push(` ${i + 1}. ${table}${depStr}`);\n });\n return lines.join('\\n');\n}"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
package/dist/index.native.js
CHANGED
package/dist/index.web.js
CHANGED
package/dist/provider/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pol-studios/powersync",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.25",
|
|
4
4
|
"description": "Enterprise PowerSync integration for offline-first applications",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
"commander": "^12.0.0",
|
|
142
142
|
"jiti": "^2.4.0",
|
|
143
143
|
"picocolors": "^1.0.0",
|
|
144
|
-
"@pol-studios/db": "1.0.
|
|
144
|
+
"@pol-studios/db": "1.0.59"
|
|
145
145
|
},
|
|
146
146
|
"peerDependencies": {
|
|
147
147
|
"@powersync/react-native": ">=1.0.8",
|