@pol-studios/powersync 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/attachments/index.js +1 -1
  2. package/dist/{chunk-PANEMMTU.js → chunk-3AYXHQ4W.js} +17 -11
  3. package/dist/chunk-3AYXHQ4W.js.map +1 -0
  4. package/dist/{chunk-BJ36QDFN.js → chunk-7EMDVIZX.js} +1 -1
  5. package/dist/chunk-7EMDVIZX.js.map +1 -0
  6. package/dist/{chunk-MB2RC3NS.js → chunk-C2RSTGDC.js} +129 -89
  7. package/dist/chunk-C2RSTGDC.js.map +1 -0
  8. package/dist/{chunk-NPNBGCRC.js → chunk-EJ23MXPQ.js} +1 -1
  9. package/dist/{chunk-NPNBGCRC.js.map → chunk-EJ23MXPQ.js.map} +1 -1
  10. package/dist/{chunk-CHRTN5PF.js → chunk-FPTDATY5.js} +1 -1
  11. package/dist/chunk-FPTDATY5.js.map +1 -0
  12. package/dist/chunk-GMFDCVMZ.js +1285 -0
  13. package/dist/chunk-GMFDCVMZ.js.map +1 -0
  14. package/dist/chunk-OLHGI472.js +1 -0
  15. package/dist/chunk-OLHGI472.js.map +1 -0
  16. package/dist/{chunk-CFCK2LHI.js → chunk-OTJXIRWX.js} +45 -40
  17. package/dist/chunk-OTJXIRWX.js.map +1 -0
  18. package/dist/{chunk-GBGATW2S.js → chunk-V6LJ6MR2.js} +86 -95
  19. package/dist/chunk-V6LJ6MR2.js.map +1 -0
  20. package/dist/connector/index.d.ts +1 -1
  21. package/dist/connector/index.js +2 -2
  22. package/dist/core/index.js +2 -2
  23. package/dist/{index-D952Qr38.d.ts → index-Cb-NI0Ct.d.ts} +9 -2
  24. package/dist/index.d.ts +2 -2
  25. package/dist/index.js +8 -9
  26. package/dist/index.native.d.ts +1 -1
  27. package/dist/index.native.js +9 -10
  28. package/dist/index.web.d.ts +1 -1
  29. package/dist/index.web.js +9 -10
  30. package/dist/platform/index.js.map +1 -1
  31. package/dist/platform/index.native.js +1 -1
  32. package/dist/platform/index.web.js +1 -1
  33. package/dist/provider/index.d.ts +6 -1
  34. package/dist/provider/index.js +6 -6
  35. package/dist/sync/index.js +3 -3
  36. package/package.json +3 -1
  37. package/dist/chunk-42IJ25Q4.js +0 -45
  38. package/dist/chunk-42IJ25Q4.js.map +0 -1
  39. package/dist/chunk-BJ36QDFN.js.map +0 -1
  40. package/dist/chunk-CFCK2LHI.js.map +0 -1
  41. package/dist/chunk-CHRTN5PF.js.map +0 -1
  42. package/dist/chunk-GBGATW2S.js.map +0 -1
  43. package/dist/chunk-H7HZMI4H.js +0 -925
  44. package/dist/chunk-H7HZMI4H.js.map +0 -1
  45. package/dist/chunk-MB2RC3NS.js.map +0 -1
  46. package/dist/chunk-PANEMMTU.js.map +0 -1
@@ -0,0 +1,1285 @@
1
+ import {
2
+ AttachmentQueue
3
+ } from "./chunk-V6LJ6MR2.js";
4
+ import {
5
+ DEFAULT_CONNECTION_HEALTH,
6
+ DEFAULT_SYNC_METRICS,
7
+ DEFAULT_SYNC_STATUS,
8
+ HealthMonitor,
9
+ MetricsCollector,
10
+ SyncStatusTracker
11
+ } from "./chunk-OTJXIRWX.js";
12
+ import {
13
+ SupabaseConnector
14
+ } from "./chunk-C2RSTGDC.js";
15
+ import {
16
+ createSyncError,
17
+ extractEntityIds,
18
+ extractTableNames
19
+ } from "./chunk-FPTDATY5.js";
20
+
21
+ // src/provider/context.ts
22
+ import { createContext } from "react";
23
+ var PowerSyncContext = createContext(null);
24
+ PowerSyncContext.displayName = "PowerSyncContext";
25
+ var SyncStatusContext = createContext(null);
26
+ SyncStatusContext.displayName = "SyncStatusContext";
27
+ var ConnectionHealthContext = createContext(null);
28
+ ConnectionHealthContext.displayName = "ConnectionHealthContext";
29
+ var SyncMetricsContext = createContext(null);
30
+ SyncMetricsContext.displayName = "SyncMetricsContext";
31
+ var AttachmentQueueContext = createContext(null);
32
+ AttachmentQueueContext.displayName = "AttachmentQueueContext";
33
+
34
+ // src/provider/PowerSyncProvider.tsx
35
+ import { useEffect, useState, useRef, useMemo, useCallback } from "react";
36
+
37
+ // src/conflicts/conflict-bus.ts
38
+ var ConflictBus = class {
39
+ conflictListeners = /* @__PURE__ */ new Set();
40
+ resolutionListeners = /* @__PURE__ */ new Set();
41
+ /**
42
+ * Subscribe to conflict detection events.
43
+ * @returns Unsubscribe function
44
+ */
45
+ onConflict(listener) {
46
+ this.conflictListeners.add(listener);
47
+ return () => this.conflictListeners.delete(listener);
48
+ }
49
+ /**
50
+ * Subscribe to resolution events.
51
+ * @returns Unsubscribe function
52
+ */
53
+ onResolution(listener) {
54
+ this.resolutionListeners.add(listener);
55
+ return () => this.resolutionListeners.delete(listener);
56
+ }
57
+ /**
58
+ * Emit a conflict detection event (called by connector).
59
+ */
60
+ emitConflict(conflict) {
61
+ this.conflictListeners.forEach((listener) => listener(conflict));
62
+ }
63
+ /**
64
+ * Emit a resolution event (called by UI/ConflictContext).
65
+ */
66
+ emitResolution(table, recordId, resolution) {
67
+ this.resolutionListeners.forEach((listener) => listener(table, recordId, resolution));
68
+ }
69
+ /**
70
+ * Clear all listeners (for cleanup).
71
+ */
72
+ destroy() {
73
+ this.conflictListeners.clear();
74
+ this.resolutionListeners.clear();
75
+ }
76
+ };
77
+
78
+ // src/provider/PowerSyncProvider.tsx
79
+ import { jsx } from "react/jsx-runtime";
80
+ function PowerSyncProvider({
81
+ config,
82
+ children,
83
+ onReady,
84
+ onError,
85
+ onSyncStatusChange
86
+ }) {
87
+ const {
88
+ platform,
89
+ schema,
90
+ powerSyncUrl,
91
+ supabaseClient,
92
+ dbFilename = "powersync.db",
93
+ connector: connectorConfig,
94
+ attachments: attachmentConfig,
95
+ sync: syncConfig
96
+ } = config;
97
+ const logger = platform.logger;
98
+ const mergedSyncConfig = {
99
+ autoConnect: syncConfig?.autoConnect ?? true,
100
+ syncInterval: syncConfig?.syncInterval ?? 0,
101
+ enableHealthMonitoring: syncConfig?.enableHealthMonitoring ?? true,
102
+ enableMetrics: syncConfig?.enableMetrics ?? true
103
+ };
104
+ const [db, setDb] = useState(null);
105
+ const [connector, setConnector] = useState(null);
106
+ const [attachmentQueue, setAttachmentQueue] = useState(null);
107
+ const [isReady, setIsReady] = useState(false);
108
+ const [isInitializing, setIsInitializing] = useState(true);
109
+ const [error, setError] = useState(null);
110
+ const [session, setSession] = useState(null);
111
+ const conflictBusRef = useRef(null);
112
+ if (!conflictBusRef.current) {
113
+ conflictBusRef.current = new ConflictBus();
114
+ }
115
+ const conflictBus = conflictBusRef.current;
116
+ const [syncStatus, setSyncStatus] = useState(DEFAULT_SYNC_STATUS);
117
+ const [pendingMutations, setPendingMutations] = useState([]);
118
+ const [syncModeState, setSyncModeState] = useState({
119
+ loaded: false,
120
+ mode: "push-pull"
121
+ });
122
+ const [lastSyncedAt, setLastSyncedAt] = useState(null);
123
+ const [connectionError, setConnectionError] = useState(null);
124
+ const [failedTransactions, setFailedTransactions] = useState([]);
125
+ const [completedTransactions, setCompletedTransactions] = useState([]);
126
+ const [connectionHealth, setConnectionHealth] = useState(DEFAULT_CONNECTION_HEALTH);
127
+ const [syncMetrics, setSyncMetrics] = useState(DEFAULT_SYNC_METRICS);
128
+ const statusTrackerRef = useRef(null);
129
+ const metricsCollectorRef = useRef(null);
130
+ const healthMonitorRef = useRef(null);
131
+ const attachmentQueueRef = useRef(null);
132
+ const listenerUnsubscribeRef = useRef(null);
133
+ const wasSyncingRef = useRef(false);
134
+ const initializingRef = useRef(false);
135
+ const dbClosedRef = useRef(false);
136
+ const connectorRef = useRef(null);
137
+ useEffect(() => {
138
+ const statusTracker = new SyncStatusTracker(platform.storage, logger, {
139
+ onStatusChange: (status) => {
140
+ setSyncStatus(status);
141
+ setLastSyncedAt(status.lastSyncedAt);
142
+ onSyncStatusChange?.(status);
143
+ }
144
+ });
145
+ statusTrackerRef.current = statusTracker;
146
+ const metricsCollector = new MetricsCollector(platform.storage, logger, {
147
+ onMetricsChange: setSyncMetrics
148
+ });
149
+ metricsCollectorRef.current = metricsCollector;
150
+ const healthMonitor = new HealthMonitor(logger, {
151
+ onHealthChange: setConnectionHealth
152
+ });
153
+ healthMonitorRef.current = healthMonitor;
154
+ const initPromise = Promise.all([statusTracker.init(), metricsCollector.init()]);
155
+ const timeoutPromise = new Promise((resolve) => {
156
+ setTimeout(() => {
157
+ logger.warn("[PowerSyncProvider] Sync mode state load timed out, using default (push-pull)");
158
+ resolve([void 0, void 0]);
159
+ }, 5e3);
160
+ });
161
+ Promise.race([initPromise, timeoutPromise]).then(() => {
162
+ logger.info("[PowerSyncProvider] Sync mode state loaded:", {
163
+ mode: statusTracker.getSyncMode()
164
+ });
165
+ setSyncModeState({
166
+ loaded: true,
167
+ mode: statusTracker.getSyncMode()
168
+ });
169
+ });
170
+ return () => {
171
+ statusTracker.dispose();
172
+ metricsCollector.dispose();
173
+ healthMonitor.dispose();
174
+ };
175
+ }, [platform, logger, onSyncStatusChange]);
176
+ useEffect(() => {
177
+ logger.debug("[PowerSyncProvider] Setting up auth listener");
178
+ supabaseClient.auth.getSession().then(({
179
+ data: {
180
+ session: initialSession
181
+ }
182
+ }) => {
183
+ logger.debug("[PowerSyncProvider] Initial session:", !!initialSession);
184
+ setSession(initialSession);
185
+ });
186
+ const {
187
+ data: {
188
+ subscription
189
+ }
190
+ } = supabaseClient.auth.onAuthStateChange((_event, newSession) => {
191
+ logger.debug("[PowerSyncProvider] Auth state changed, hasSession:", !!newSession);
192
+ setSession(newSession);
193
+ });
194
+ return () => {
195
+ subscription.unsubscribe();
196
+ };
197
+ }, [supabaseClient, logger]);
198
+ useEffect(() => {
199
+ if (initializingRef.current) {
200
+ logger.debug("[PowerSyncProvider] Already initializing, skipping...");
201
+ return;
202
+ }
203
+ initializingRef.current = true;
204
+ const controller = {
205
+ cancelled: false
206
+ };
207
+ const initDatabase = async () => {
208
+ try {
209
+ logger.info("[PowerSyncProvider] Initializing database...");
210
+ const database = await platform.createDatabase({
211
+ dbFilename,
212
+ schema
213
+ });
214
+ if (controller.cancelled) {
215
+ logger.debug("[PowerSyncProvider] Init cancelled, closing database...");
216
+ await database.close();
217
+ initializingRef.current = false;
218
+ return;
219
+ }
220
+ logger.info("[PowerSyncProvider] Database initialized");
221
+ setDb(database);
222
+ setIsReady(true);
223
+ setIsInitializing(false);
224
+ healthMonitorRef.current?.setDatabase(database);
225
+ if (mergedSyncConfig.enableHealthMonitoring) {
226
+ healthMonitorRef.current?.start();
227
+ }
228
+ onReady?.();
229
+ } catch (err) {
230
+ const initError = err instanceof Error ? err : new Error(String(err));
231
+ logger.error("[PowerSyncProvider] Initialization failed:", initError);
232
+ if (!controller.cancelled) {
233
+ setError(initError);
234
+ setIsInitializing(false);
235
+ onError?.(initError);
236
+ }
237
+ initializingRef.current = false;
238
+ }
239
+ };
240
+ initDatabase();
241
+ return () => {
242
+ controller.cancelled = true;
243
+ initializingRef.current = false;
244
+ };
245
+ }, [platform, dbFilename, schema, logger, mergedSyncConfig.enableHealthMonitoring, onReady, onError]);
246
+ useEffect(() => {
247
+ if (__DEV__) {
248
+ console.log("[PowerSyncProvider] Connect effect triggered:", {
249
+ hasDb: !!db,
250
+ hasSession: !!session,
251
+ autoConnect: mergedSyncConfig.autoConnect,
252
+ syncModeState
253
+ });
254
+ }
255
+ logger.info("[PowerSyncProvider] Connect effect - db:", !!db, "session:", !!session, "autoConnect:", mergedSyncConfig.autoConnect, "syncModeLoaded:", syncModeState.loaded, "syncMode:", syncModeState.mode);
256
+ if (!db) {
257
+ logger.debug("[PowerSyncProvider] Connect effect - waiting for db");
258
+ return;
259
+ }
260
+ if (!session) {
261
+ logger.debug("[PowerSyncProvider] Connect effect - no session");
262
+ return;
263
+ }
264
+ if (!mergedSyncConfig.autoConnect) {
265
+ logger.debug("[PowerSyncProvider] Connect effect - autoConnect disabled");
266
+ return;
267
+ }
268
+ if (!syncModeState.loaded) {
269
+ logger.info("[PowerSyncProvider] Waiting for sync mode state to load...");
270
+ return;
271
+ }
272
+ if (syncModeState.mode === "offline") {
273
+ logger.debug("[PowerSyncProvider] Skipping connect - offline mode");
274
+ return;
275
+ }
276
+ const connectPowerSync = async () => {
277
+ try {
278
+ setConnectionError(null);
279
+ connectorRef.current?.destroy();
280
+ const statusTracker_0 = statusTrackerRef.current;
281
+ const newConnector = new SupabaseConnector({
282
+ supabaseClient,
283
+ powerSyncUrl,
284
+ schemaRouter: connectorConfig?.schemaRouter,
285
+ crudHandler: connectorConfig?.crudHandler,
286
+ logger,
287
+ // Conflict detection - enabled by default
288
+ conflictDetection: {
289
+ enabled: true
290
+ },
291
+ conflictBus,
292
+ // Check if uploads should be performed based on sync mode
293
+ shouldUpload: () => statusTrackerRef.current?.shouldUpload() ?? true,
294
+ // Clear failures when transaction succeeds
295
+ onTransactionSuccess: (entries) => {
296
+ if (!statusTracker_0) return;
297
+ const entityIds = extractEntityIds(entries);
298
+ entityIds.forEach((id) => {
299
+ const failures = statusTracker_0.getFailuresForEntity(id);
300
+ failures.forEach((f) => statusTracker_0.clearFailure(f.id));
301
+ });
302
+ setFailedTransactions(statusTracker_0.getFailedTransactions());
303
+ },
304
+ // Record failures when transaction fails
305
+ onTransactionFailure: (entries_0, error_0, classified) => {
306
+ if (!statusTracker_0) return;
307
+ statusTracker_0.recordTransactionFailure(entries_0, createSyncError(classified, error_0.message), classified.isPermanent, extractEntityIds(entries_0), extractTableNames(entries_0));
308
+ setFailedTransactions(statusTracker_0.getFailedTransactions());
309
+ },
310
+ // Record completed transactions
311
+ onTransactionComplete: (entries_1) => {
312
+ if (!statusTracker_0) return;
313
+ statusTracker_0.recordTransactionComplete(entries_1);
314
+ setCompletedTransactions(statusTracker_0.getCompletedTransactions());
315
+ }
316
+ });
317
+ setConnector(newConnector);
318
+ connectorRef.current = newConnector;
319
+ if (db.connected) {
320
+ logger.debug("[PowerSyncProvider] Already connected, reconnecting...");
321
+ await db.disconnect();
322
+ }
323
+ logger.info("[PowerSyncProvider] Connecting to PowerSync...");
324
+ await db.connect(newConnector);
325
+ logger.info("[PowerSyncProvider] Connected successfully");
326
+ healthMonitorRef.current?.resetReconnectAttempts();
327
+ } catch (err_0) {
328
+ const connectError = err_0 instanceof Error ? err_0 : new Error(String(err_0));
329
+ logger.error("[PowerSyncProvider] Connection failed:", connectError);
330
+ setConnectionError(connectError);
331
+ healthMonitorRef.current?.recordReconnectAttempt();
332
+ }
333
+ };
334
+ connectPowerSync();
335
+ }, [db, session, powerSyncUrl, supabaseClient, connectorConfig, conflictBus, mergedSyncConfig.autoConnect, syncModeState, logger]);
336
+ useEffect(() => {
337
+ if (!db) return;
338
+ const initialStatus = db.currentStatus;
339
+ if (initialStatus) {
340
+ statusTrackerRef.current?.handleStatusChange(initialStatus);
341
+ }
342
+ const unsubscribe = db.registerListener({
343
+ statusChanged: (status_0) => {
344
+ statusTrackerRef.current?.handleStatusChange(status_0);
345
+ const dataFlow = status_0.dataFlowStatus;
346
+ const isDownloading = dataFlow?.downloading ?? false;
347
+ const progress = status_0.downloadProgress;
348
+ if (isDownloading && !wasSyncingRef.current) {
349
+ metricsCollectorRef.current?.markSyncStart();
350
+ }
351
+ if (!isDownloading && wasSyncingRef.current) {
352
+ const duration = metricsCollectorRef.current?.markSyncEnd();
353
+ if (duration !== null && duration !== void 0) {
354
+ metricsCollectorRef.current?.recordSync({
355
+ durationMs: duration,
356
+ success: true,
357
+ operationsDownloaded: progress?.totalOperations ?? 0
358
+ });
359
+ }
360
+ }
361
+ wasSyncingRef.current = isDownloading;
362
+ }
363
+ });
364
+ listenerUnsubscribeRef.current = unsubscribe;
365
+ return () => {
366
+ unsubscribe();
367
+ listenerUnsubscribeRef.current = null;
368
+ };
369
+ }, [db]);
370
+ const prevPendingCountRef = useRef(0);
371
+ const parseCrudRow = useCallback((row) => {
372
+ try {
373
+ const parsed = JSON.parse(row.data);
374
+ const opMap = {
375
+ "PUT": "PUT",
376
+ "PATCH": "PATCH",
377
+ "DELETE": "DELETE"
378
+ };
379
+ const op = opMap[parsed.op] ?? "PUT";
380
+ const entityId = parsed.data?.id ?? parsed.id ?? row.id;
381
+ return {
382
+ id: entityId,
383
+ clientId: parseInt(row.id, 10) || 0,
384
+ op,
385
+ table: parsed.type ?? "unknown",
386
+ opData: parsed.data ?? void 0,
387
+ // Ensure null becomes undefined
388
+ transactionId: row.tx_id ?? void 0
389
+ };
390
+ } catch (e) {
391
+ logger.warn("[PowerSyncProvider] Failed to parse CRUD entry:", e, row);
392
+ return null;
393
+ }
394
+ }, [logger]);
395
+ useEffect(() => {
396
+ if (!db) return;
397
+ const abortController = new AbortController();
398
+ db.watch("SELECT COUNT(*) as count FROM ps_crud", [], {
399
+ onResult: async (results) => {
400
+ if (dbClosedRef.current) {
401
+ logger.debug("[PowerSyncProvider] Skipping watch callback - database is closed");
402
+ return;
403
+ }
404
+ const count = results.rows?._array?.[0]?.count ?? 0;
405
+ const prevCount = prevPendingCountRef.current;
406
+ prevPendingCountRef.current = count;
407
+ let mutations = [];
408
+ if (count > 0) {
409
+ try {
410
+ if (dbClosedRef.current) {
411
+ logger.debug("[PowerSyncProvider] Skipping getAll - database is closed");
412
+ return;
413
+ }
414
+ const rows = await db.getAll("SELECT id, tx_id, data FROM ps_crud ORDER BY id ASC");
415
+ mutations = rows.map(parseCrudRow).filter((entry) => entry !== null);
416
+ } catch (e_0) {
417
+ const errorMessage = e_0 instanceof Error ? e_0.message : String(e_0);
418
+ if (errorMessage.includes("not open") || errorMessage.includes("closed")) {
419
+ logger.debug("[PowerSyncProvider] Database closed during CRUD fetch, ignoring");
420
+ return;
421
+ }
422
+ logger.warn("[PowerSyncProvider] Failed to fetch CRUD entries:", e_0);
423
+ }
424
+ }
425
+ if (dbClosedRef.current) {
426
+ return;
427
+ }
428
+ statusTrackerRef.current?.updatePendingMutations(mutations);
429
+ setPendingMutations(mutations);
430
+ if (prevCount > 0 && count === 0) {
431
+ logger.debug("[PowerSyncProvider] All pending uploads complete, clearing force flag");
432
+ statusTrackerRef.current?.clearForceNextUpload();
433
+ }
434
+ },
435
+ onError: (error_1) => {
436
+ const errorMessage_0 = error_1.message ?? "";
437
+ if (errorMessage_0.includes("not open") || errorMessage_0.includes("closed") || dbClosedRef.current) {
438
+ logger.debug("[PowerSyncProvider] Watch error during database close, ignoring");
439
+ return;
440
+ }
441
+ logger.warn("[PowerSyncProvider] Error watching ps_crud:", error_1);
442
+ }
443
+ }, {
444
+ signal: abortController.signal,
445
+ throttleMs: 100
446
+ // Debounce to avoid excessive updates during bulk operations
447
+ });
448
+ return () => {
449
+ abortController.abort();
450
+ };
451
+ }, [db, logger, parseCrudRow]);
452
+ useEffect(() => {
453
+ if (!db || !attachmentConfig || attachmentQueueRef.current) {
454
+ return;
455
+ }
456
+ const initAttachmentQueue = async () => {
457
+ try {
458
+ logger.info("[PowerSyncProvider] Initializing attachment queue...");
459
+ const queue = new AttachmentQueue({
460
+ powersync: db,
461
+ platform,
462
+ config: attachmentConfig
463
+ });
464
+ await queue.init();
465
+ attachmentQueueRef.current = queue;
466
+ setAttachmentQueue(queue);
467
+ logger.info("[PowerSyncProvider] Attachment queue initialized");
468
+ } catch (err_1) {
469
+ logger.error("[PowerSyncProvider] Attachment queue initialization failed:", err_1);
470
+ }
471
+ };
472
+ initAttachmentQueue();
473
+ return () => {
474
+ attachmentQueueRef.current?.dispose();
475
+ attachmentQueueRef.current = null;
476
+ };
477
+ }, [db, attachmentConfig, platform, logger]);
478
+ useEffect(() => {
479
+ if (db) {
480
+ dbClosedRef.current = false;
481
+ }
482
+ return () => {
483
+ logger.info("[PowerSyncProvider] Cleaning up...");
484
+ dbClosedRef.current = true;
485
+ connectorRef.current?.destroy();
486
+ connectorRef.current = null;
487
+ listenerUnsubscribeRef.current?.();
488
+ attachmentQueueRef.current?.dispose();
489
+ healthMonitorRef.current?.stop();
490
+ conflictBusRef.current?.destroy();
491
+ if (db) {
492
+ (async () => {
493
+ try {
494
+ await db.disconnect();
495
+ await db.close();
496
+ } catch (err_2) {
497
+ const errorMessage_1 = err_2 instanceof Error ? err_2.message : String(err_2);
498
+ if (!errorMessage_1.includes("not open") && !errorMessage_1.includes("closed")) {
499
+ logger.warn("[PowerSyncProvider] Error during cleanup:", err_2);
500
+ }
501
+ }
502
+ })();
503
+ }
504
+ };
505
+ }, [db, logger]);
506
+ const clearFailure = useCallback((failureId) => {
507
+ const tracker = statusTrackerRef.current;
508
+ if (!tracker) {
509
+ logger.warn("[PowerSyncProvider] Cannot clear failure - tracker not initialized");
510
+ return;
511
+ }
512
+ tracker.clearFailure(failureId);
513
+ setFailedTransactions(tracker.getFailedTransactions());
514
+ }, [logger]);
515
+ const clearAllFailures = useCallback(() => {
516
+ const tracker_0 = statusTrackerRef.current;
517
+ if (!tracker_0) {
518
+ logger.warn("[PowerSyncProvider] Cannot clear failures - tracker not initialized");
519
+ return;
520
+ }
521
+ tracker_0.clearAllFailures();
522
+ setFailedTransactions(tracker_0.getFailedTransactions());
523
+ }, [logger]);
524
+ const clearCompletedHistory = useCallback(() => {
525
+ const tracker_1 = statusTrackerRef.current;
526
+ if (!tracker_1) {
527
+ logger.warn("[PowerSyncProvider] Cannot clear completed history - tracker not initialized");
528
+ return;
529
+ }
530
+ tracker_1.clearCompletedHistory();
531
+ setCompletedTransactions(tracker_1.getCompletedTransactions());
532
+ }, [logger]);
533
+ const setSyncMode = useCallback(async (mode) => {
534
+ const tracker_2 = statusTrackerRef.current;
535
+ if (!tracker_2) {
536
+ logger.warn("[PowerSyncProvider] Cannot set sync mode - tracker not initialized");
537
+ return;
538
+ }
539
+ await tracker_2.setSyncMode(mode);
540
+ setSyncModeState({
541
+ loaded: true,
542
+ mode
543
+ });
544
+ }, [logger]);
545
+ const setForceNextUpload = useCallback((force) => {
546
+ const tracker_3 = statusTrackerRef.current;
547
+ if (!tracker_3) {
548
+ logger.warn("[PowerSyncProvider] Cannot set force upload - tracker not initialized");
549
+ return;
550
+ }
551
+ tracker_3.setForceNextUpload(force);
552
+ }, [logger]);
553
+ const discardPendingMutation = useCallback(async (clientId) => {
554
+ if (!db || !connector) {
555
+ logger.warn("[PowerSync] Cannot discard - not initialized");
556
+ return;
557
+ }
558
+ if (syncStatus.uploading) {
559
+ throw new Error("Cannot discard while upload is in progress");
560
+ }
561
+ logger.info("[PowerSync] Discarding pending mutation:", clientId);
562
+ await db.disconnect();
563
+ try {
564
+ await db.execute("DELETE FROM ps_crud WHERE id = ?", [clientId]);
565
+ logger.info("[PowerSync] Mutation discarded successfully");
566
+ } finally {
567
+ await db.connect(connector);
568
+ }
569
+ }, [db, connector, syncStatus.uploading, logger]);
570
+ const discardAllPendingMutations = useCallback(async () => {
571
+ if (!db || !connector) {
572
+ logger.warn("[PowerSync] Cannot discard all - not initialized");
573
+ return;
574
+ }
575
+ if (syncStatus.uploading) {
576
+ throw new Error("Cannot discard while upload is in progress");
577
+ }
578
+ logger.info("[PowerSync] Discarding all pending mutations");
579
+ await db.disconnect();
580
+ try {
581
+ await db.execute("DELETE FROM ps_crud");
582
+ logger.info("[PowerSync] All mutations discarded successfully");
583
+ } finally {
584
+ await db.connect(connector);
585
+ }
586
+ }, [db, connector, syncStatus.uploading, logger]);
587
+ const powerSyncContextValue = useMemo(() => ({
588
+ db,
589
+ connector,
590
+ attachmentQueue,
591
+ isReady,
592
+ isInitializing,
593
+ error,
594
+ schema,
595
+ platform,
596
+ conflictBus
597
+ }), [db, connector, attachmentQueue, isReady, isInitializing, error, schema, platform, conflictBus]);
598
+ const syncStatusContextValue = useMemo(() => ({
599
+ status: syncStatus,
600
+ pendingMutations,
601
+ pendingCount: pendingMutations.length,
602
+ // Expose uploading/downloading directly from syncStatus for reliable activity detection
603
+ isUploading: syncStatus.uploading,
604
+ isDownloading: syncStatus.downloading,
605
+ isPaused: syncModeState.mode === "offline",
606
+ syncMode: syncModeState.mode,
607
+ lastSyncedAt,
608
+ // Connection error for consumers to display
609
+ connectionError,
610
+ // Failed transaction fields
611
+ failedTransactions,
612
+ hasUploadErrors: failedTransactions.length > 0,
613
+ permanentErrorCount: failedTransactions.filter((f_0) => f_0.isPermanent).length,
614
+ // Clear failure functions
615
+ clearFailure,
616
+ clearAllFailures,
617
+ // Completed transaction fields
618
+ completedTransactions,
619
+ clearCompletedHistory,
620
+ // Sync mode control functions
621
+ setSyncMode,
622
+ setForceNextUpload,
623
+ // Discard mutation functions
624
+ discardPendingMutation,
625
+ discardAllPendingMutations
626
+ }), [syncStatus, pendingMutations, syncModeState.mode, lastSyncedAt, connectionError, failedTransactions, clearFailure, clearAllFailures, completedTransactions, clearCompletedHistory, setSyncMode, setForceNextUpload, discardPendingMutation, discardAllPendingMutations]);
627
+ const connectionHealthContextValue = useMemo(() => ({
628
+ health: connectionHealth
629
+ }), [connectionHealth]);
630
+ const syncMetricsContextValue = useMemo(() => ({
631
+ metrics: syncMetrics
632
+ }), [syncMetrics]);
633
+ return /* @__PURE__ */ jsx(PowerSyncContext.Provider, { value: powerSyncContextValue, children: /* @__PURE__ */ jsx(SyncStatusContext.Provider, { value: syncStatusContextValue, children: /* @__PURE__ */ jsx(ConnectionHealthContext.Provider, { value: connectionHealthContextValue, children: /* @__PURE__ */ jsx(SyncMetricsContext.Provider, { value: syncMetricsContextValue, children: /* @__PURE__ */ jsx(AttachmentQueueContext.Provider, { value: attachmentQueue, children }) }) }) }) });
634
+ }
635
+
636
+ // src/provider/hooks.ts
637
+ import { c as _c } from "react/compiler-runtime";
638
+ import { useContext, useRef as useRef2, useState as useState2, useEffect as useEffect2 } from "react";
639
+ function usePowerSync() {
640
+ const context = useContext(PowerSyncContext);
641
+ if (!context) {
642
+ throw new Error("usePowerSync must be used within a PowerSyncProvider");
643
+ }
644
+ return context;
645
+ }
646
+ function useSyncStatus() {
647
+ const context = useContext(SyncStatusContext);
648
+ if (!context) {
649
+ throw new Error("useSyncStatus must be used within a PowerSyncProvider");
650
+ }
651
+ return context;
652
+ }
653
+ function useSyncControl() {
654
+ const $ = _c(35);
655
+ const {
656
+ db,
657
+ connector,
658
+ platform
659
+ } = usePowerSync();
660
+ const {
661
+ setSyncMode: setContextSyncMode,
662
+ setForceNextUpload
663
+ } = useSyncStatus();
664
+ const scopeRef = useRef2(null);
665
+ let t0;
666
+ if ($[0] !== connector || $[1] !== db || $[2] !== platform || $[3] !== setContextSyncMode) {
667
+ t0 = async (mode) => {
668
+ await setContextSyncMode(mode);
669
+ if (mode === "offline") {
670
+ if (db?.connected) {
671
+ platform.logger.info("[useSyncControl] Mode changed to offline - disconnecting");
672
+ await db.disconnect();
673
+ }
674
+ } else {
675
+ if (db && connector && !db.connected) {
676
+ platform.logger.info("[useSyncControl] Mode changed to", mode, "- reconnecting");
677
+ await db.connect(connector);
678
+ }
679
+ }
680
+ };
681
+ $[0] = connector;
682
+ $[1] = db;
683
+ $[2] = platform;
684
+ $[3] = setContextSyncMode;
685
+ $[4] = t0;
686
+ } else {
687
+ t0 = $[4];
688
+ }
689
+ const setSyncMode = t0;
690
+ let t1;
691
+ if ($[5] !== connector || $[6] !== db || $[7] !== platform || $[8] !== setForceNextUpload) {
692
+ t1 = async () => {
693
+ if (!db || !connector) {
694
+ platform.logger.warn("[useSyncControl] Cannot sync - database not initialized");
695
+ return;
696
+ }
697
+ setForceNextUpload(true);
698
+ platform.logger.info("[useSyncControl] Sync Now triggered - forcing full sync");
699
+ if (db.connected) {
700
+ await db.disconnect();
701
+ }
702
+ await db.connect(connector);
703
+ platform.logger.info("[useSyncControl] Connected, sync should start automatically");
704
+ };
705
+ $[5] = connector;
706
+ $[6] = db;
707
+ $[7] = platform;
708
+ $[8] = setForceNextUpload;
709
+ $[9] = t1;
710
+ } else {
711
+ t1 = $[9];
712
+ }
713
+ const syncNow = t1;
714
+ let t2;
715
+ if ($[10] !== connector || $[11] !== db || $[12] !== platform || $[13] !== setContextSyncMode) {
716
+ t2 = async () => {
717
+ if (!db || !connector) {
718
+ platform.logger.warn("[useSyncControl] Cannot trigger sync - not initialized");
719
+ return;
720
+ }
721
+ await setContextSyncMode("push-pull");
722
+ if (db.connected) {
723
+ platform.logger.info("[useSyncControl] Disconnecting to force fresh sync...");
724
+ await db.disconnect();
725
+ }
726
+ platform.logger.info("[useSyncControl] Connecting...");
727
+ await db.connect(connector);
728
+ platform.logger.info("[useSyncControl] Connected, sync should start automatically");
729
+ };
730
+ $[10] = connector;
731
+ $[11] = db;
732
+ $[12] = platform;
733
+ $[13] = setContextSyncMode;
734
+ $[14] = t2;
735
+ } else {
736
+ t2 = $[14];
737
+ }
738
+ const triggerSync = t2;
739
+ let t3;
740
+ if ($[15] !== platform || $[16] !== setSyncMode) {
741
+ t3 = async () => {
742
+ await setSyncMode("offline");
743
+ platform.logger.info("[useSyncControl] Sync paused");
744
+ };
745
+ $[15] = platform;
746
+ $[16] = setSyncMode;
747
+ $[17] = t3;
748
+ } else {
749
+ t3 = $[17];
750
+ }
751
+ const pause = t3;
752
+ let t4;
753
+ if ($[18] !== platform || $[19] !== setSyncMode) {
754
+ t4 = async () => {
755
+ await setSyncMode("push-pull");
756
+ platform.logger.info("[useSyncControl] Sync resumed");
757
+ };
758
+ $[18] = platform;
759
+ $[19] = setSyncMode;
760
+ $[20] = t4;
761
+ } else {
762
+ t4 = $[20];
763
+ }
764
+ const resume = t4;
765
+ let t5;
766
+ if ($[21] !== db || $[22] !== platform) {
767
+ t5 = async () => {
768
+ if (!db) {
769
+ platform.logger.warn("[useSyncControl] Cannot disconnect - not initialized");
770
+ return;
771
+ }
772
+ platform.logger.info("[useSyncControl] Disconnecting...");
773
+ await db.disconnect();
774
+ platform.logger.info("[useSyncControl] Disconnected");
775
+ };
776
+ $[21] = db;
777
+ $[22] = platform;
778
+ $[23] = t5;
779
+ } else {
780
+ t5 = $[23];
781
+ }
782
+ const disconnect = t5;
783
+ let t6;
784
+ if ($[24] !== connector || $[25] !== platform) {
785
+ t6 = (scope) => {
786
+ scopeRef.current = scope;
787
+ if (connector && scope) {
788
+ connector.setActiveProjectIds(scope.ids);
789
+ platform.logger.info("[useSyncControl] Scope set:", scope);
790
+ }
791
+ };
792
+ $[24] = connector;
793
+ $[25] = platform;
794
+ $[26] = t6;
795
+ } else {
796
+ t6 = $[26];
797
+ }
798
+ const setScope = t6;
799
+ let t7;
800
+ if ($[27] !== disconnect || $[28] !== pause || $[29] !== resume || $[30] !== setScope || $[31] !== setSyncMode || $[32] !== syncNow || $[33] !== triggerSync) {
801
+ t7 = {
802
+ triggerSync,
803
+ syncNow,
804
+ pause,
805
+ resume,
806
+ disconnect,
807
+ setScope,
808
+ setSyncMode
809
+ };
810
+ $[27] = disconnect;
811
+ $[28] = pause;
812
+ $[29] = resume;
813
+ $[30] = setScope;
814
+ $[31] = setSyncMode;
815
+ $[32] = syncNow;
816
+ $[33] = triggerSync;
817
+ $[34] = t7;
818
+ } else {
819
+ t7 = $[34];
820
+ }
821
+ return t7;
822
+ }
823
+ function useSyncMode() {
824
+ const $ = _c(5);
825
+ const {
826
+ syncMode
827
+ } = useSyncStatus();
828
+ const {
829
+ setSyncMode
830
+ } = useSyncControl();
831
+ const t0 = syncMode === "push-pull";
832
+ const t1 = syncMode !== "offline";
833
+ let t2;
834
+ if ($[0] !== setSyncMode || $[1] !== syncMode || $[2] !== t0 || $[3] !== t1) {
835
+ t2 = {
836
+ mode: syncMode,
837
+ setMode: setSyncMode,
838
+ canUpload: t0,
839
+ canDownload: t1
840
+ };
841
+ $[0] = setSyncMode;
842
+ $[1] = syncMode;
843
+ $[2] = t0;
844
+ $[3] = t1;
845
+ $[4] = t2;
846
+ } else {
847
+ t2 = $[4];
848
+ }
849
+ return t2;
850
+ }
851
+ function useConnectionHealth() {
852
+ const context = useContext(ConnectionHealthContext);
853
+ if (!context) {
854
+ throw new Error("useConnectionHealth must be used within a PowerSyncProvider");
855
+ }
856
+ return context.health;
857
+ }
858
+ function useSyncMetrics() {
859
+ const context = useContext(SyncMetricsContext);
860
+ if (!context) {
861
+ throw new Error("useSyncMetrics must be used within a PowerSyncProvider");
862
+ }
863
+ return context.metrics;
864
+ }
865
+ function useAttachmentQueue() {
866
+ return useContext(AttachmentQueueContext);
867
+ }
868
+ function useDatabase() {
869
+ const {
870
+ db,
871
+ isReady,
872
+ error
873
+ } = usePowerSync();
874
+ if (error) {
875
+ throw error;
876
+ }
877
+ if (!isReady || !db) {
878
+ throw new Error("PowerSync database is not ready");
879
+ }
880
+ return db;
881
+ }
882
+ function usePlatform() {
883
+ const {
884
+ platform
885
+ } = usePowerSync();
886
+ return platform;
887
+ }
888
+ function useOnlineStatus() {
889
+ const $ = _c(4);
890
+ const {
891
+ platform
892
+ } = usePowerSync();
893
+ const [isOnline, setIsOnline] = useState2(true);
894
+ let t0;
895
+ if ($[0] !== platform.network) {
896
+ t0 = () => {
897
+ platform.network.isConnected().then(setIsOnline);
898
+ const unsubscribe = platform.network.addConnectionListener(setIsOnline);
899
+ return unsubscribe;
900
+ };
901
+ $[0] = platform.network;
902
+ $[1] = t0;
903
+ } else {
904
+ t0 = $[1];
905
+ }
906
+ let t1;
907
+ if ($[2] !== platform) {
908
+ t1 = [platform];
909
+ $[2] = platform;
910
+ $[3] = t1;
911
+ } else {
912
+ t1 = $[3];
913
+ }
914
+ useEffect2(t0, t1);
915
+ return isOnline;
916
+ }
917
+ function usePendingMutations() {
918
+ const $ = _c(3);
919
+ const {
920
+ pendingMutations,
921
+ pendingCount
922
+ } = useSyncStatus();
923
+ let t0;
924
+ if ($[0] !== pendingCount || $[1] !== pendingMutations) {
925
+ t0 = {
926
+ mutations: pendingMutations,
927
+ count: pendingCount
928
+ };
929
+ $[0] = pendingCount;
930
+ $[1] = pendingMutations;
931
+ $[2] = t0;
932
+ } else {
933
+ t0 = $[2];
934
+ }
935
+ return t0;
936
+ }
937
+ function useIsSyncing() {
938
+ const {
939
+ status
940
+ } = useSyncStatus();
941
+ return status.uploading || status.downloading;
942
+ }
943
+ function useDownloadProgress() {
944
+ const {
945
+ status
946
+ } = useSyncStatus();
947
+ return status.downloadProgress;
948
+ }
949
+ var recentlySyncedEntities = /* @__PURE__ */ new Map();
950
+ var SYNCED_DISPLAY_DURATION_MS = 3e3;
951
+ function useEntitySyncStatus(entityId) {
952
+ const $ = _c(27);
953
+ const {
954
+ pendingMutations,
955
+ clearFailure,
956
+ failedTransactions
957
+ } = useSyncStatus();
958
+ const [, forceUpdate] = useState2(0);
959
+ let t0;
960
+ bb0: {
961
+ if (!entityId) {
962
+ let t13;
963
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
964
+ t13 = [];
965
+ $[0] = t13;
966
+ } else {
967
+ t13 = $[0];
968
+ }
969
+ t0 = t13;
970
+ break bb0;
971
+ }
972
+ let t12;
973
+ if ($[1] !== entityId || $[2] !== pendingMutations) {
974
+ let t22;
975
+ if ($[4] !== entityId) {
976
+ t22 = (entry) => entry.id === entityId || String(entry.opData?.id) === entityId;
977
+ $[4] = entityId;
978
+ $[5] = t22;
979
+ } else {
980
+ t22 = $[5];
981
+ }
982
+ t12 = pendingMutations.filter(t22);
983
+ $[1] = entityId;
984
+ $[2] = pendingMutations;
985
+ $[3] = t12;
986
+ } else {
987
+ t12 = $[3];
988
+ }
989
+ t0 = t12;
990
+ }
991
+ const entityPendingMutations = t0;
992
+ let t1;
993
+ bb1: {
994
+ if (!entityId) {
995
+ t1 = null;
996
+ break bb1;
997
+ }
998
+ let t22;
999
+ if ($[6] !== entityId || $[7] !== failedTransactions) {
1000
+ t22 = failedTransactions.find((ft) => ft.affectedEntityIds.includes(entityId)) ?? null;
1001
+ $[6] = entityId;
1002
+ $[7] = failedTransactions;
1003
+ $[8] = t22;
1004
+ } else {
1005
+ t22 = $[8];
1006
+ }
1007
+ t1 = t22;
1008
+ }
1009
+ const failedTransaction = t1;
1010
+ const wasSyncingRef = useRef2(false);
1011
+ const isCurrentlySyncing = entityPendingMutations.length > 0;
1012
+ let t2;
1013
+ if ($[9] !== entityId || $[10] !== failedTransaction || $[11] !== forceUpdate || $[12] !== isCurrentlySyncing) {
1014
+ t2 = () => {
1015
+ if (!entityId) {
1016
+ return;
1017
+ }
1018
+ if (wasSyncingRef.current && !isCurrentlySyncing && !failedTransaction) {
1019
+ recentlySyncedEntities.set(entityId, Date.now());
1020
+ const timer = setTimeout(() => {
1021
+ const syncedAt = recentlySyncedEntities.get(entityId);
1022
+ if (syncedAt && Date.now() - syncedAt >= SYNCED_DISPLAY_DURATION_MS) {
1023
+ recentlySyncedEntities.delete(entityId);
1024
+ forceUpdate(_temp);
1025
+ }
1026
+ }, SYNCED_DISPLAY_DURATION_MS);
1027
+ return () => clearTimeout(timer);
1028
+ }
1029
+ wasSyncingRef.current = isCurrentlySyncing;
1030
+ };
1031
+ $[9] = entityId;
1032
+ $[10] = failedTransaction;
1033
+ $[11] = forceUpdate;
1034
+ $[12] = isCurrentlySyncing;
1035
+ $[13] = t2;
1036
+ } else {
1037
+ t2 = $[13];
1038
+ }
1039
+ let t3;
1040
+ if ($[14] !== entityId || $[15] !== failedTransaction || $[16] !== isCurrentlySyncing) {
1041
+ t3 = [entityId, isCurrentlySyncing, failedTransaction];
1042
+ $[14] = entityId;
1043
+ $[15] = failedTransaction;
1044
+ $[16] = isCurrentlySyncing;
1045
+ $[17] = t3;
1046
+ } else {
1047
+ t3 = $[17];
1048
+ }
1049
+ useEffect2(t2, t3);
1050
+ let t4;
1051
+ bb2: {
1052
+ if (!entityId) {
1053
+ t4 = "idle";
1054
+ break bb2;
1055
+ }
1056
+ if (failedTransaction) {
1057
+ t4 = "error";
1058
+ break bb2;
1059
+ }
1060
+ if (entityPendingMutations.length > 0) {
1061
+ t4 = "syncing";
1062
+ break bb2;
1063
+ }
1064
+ const syncedAt_0 = recentlySyncedEntities.get(entityId);
1065
+ if (syncedAt_0 && Date.now() - syncedAt_0 < SYNCED_DISPLAY_DURATION_MS) {
1066
+ t4 = "synced";
1067
+ break bb2;
1068
+ }
1069
+ t4 = "idle";
1070
+ }
1071
+ const state = t4;
1072
+ const error = failedTransaction?.error ?? null;
1073
+ let t5;
1074
+ if ($[18] !== clearFailure || $[19] !== failedTransaction) {
1075
+ t5 = () => {
1076
+ if (failedTransaction) {
1077
+ clearFailure(failedTransaction.id);
1078
+ }
1079
+ };
1080
+ $[18] = clearFailure;
1081
+ $[19] = failedTransaction;
1082
+ $[20] = t5;
1083
+ } else {
1084
+ t5 = $[20];
1085
+ }
1086
+ const dismiss = t5;
1087
+ let t6;
1088
+ if ($[21] !== dismiss || $[22] !== entityPendingMutations.length || $[23] !== error || $[24] !== failedTransaction || $[25] !== state) {
1089
+ t6 = {
1090
+ state,
1091
+ error,
1092
+ pendingOperations: entityPendingMutations.length,
1093
+ failedTransaction,
1094
+ dismiss
1095
+ };
1096
+ $[21] = dismiss;
1097
+ $[22] = entityPendingMutations.length;
1098
+ $[23] = error;
1099
+ $[24] = failedTransaction;
1100
+ $[25] = state;
1101
+ $[26] = t6;
1102
+ } else {
1103
+ t6 = $[26];
1104
+ }
1105
+ return t6;
1106
+ }
1107
+ function _temp(n) {
1108
+ return n + 1;
1109
+ }
1110
+ function useUploadStatus() {
1111
+ const $ = _c(12);
1112
+ const {
1113
+ pendingCount,
1114
+ clearAllFailures,
1115
+ failedTransactions,
1116
+ hasUploadErrors,
1117
+ permanentErrorCount
1118
+ } = useSyncStatus();
1119
+ const {
1120
+ triggerSync
1121
+ } = useSyncControl();
1122
+ let t0;
1123
+ if ($[0] !== triggerSync) {
1124
+ t0 = async () => {
1125
+ await triggerSync();
1126
+ };
1127
+ $[0] = triggerSync;
1128
+ $[1] = t0;
1129
+ } else {
1130
+ t0 = $[1];
1131
+ }
1132
+ const retryAll = t0;
1133
+ let t1;
1134
+ if ($[2] !== clearAllFailures) {
1135
+ t1 = () => {
1136
+ clearAllFailures();
1137
+ };
1138
+ $[2] = clearAllFailures;
1139
+ $[3] = t1;
1140
+ } else {
1141
+ t1 = $[3];
1142
+ }
1143
+ const dismissAll = t1;
1144
+ const t2 = permanentErrorCount > 0;
1145
+ let t3;
1146
+ if ($[4] !== dismissAll || $[5] !== failedTransactions || $[6] !== hasUploadErrors || $[7] !== pendingCount || $[8] !== permanentErrorCount || $[9] !== retryAll || $[10] !== t2) {
1147
+ t3 = {
1148
+ pendingCount,
1149
+ failedCount: failedTransactions.length,
1150
+ permanentFailureCount: permanentErrorCount,
1151
+ hasErrors: hasUploadErrors,
1152
+ hasPermanentErrors: t2,
1153
+ failedTransactions,
1154
+ retryAll,
1155
+ dismissAll
1156
+ };
1157
+ $[4] = dismissAll;
1158
+ $[5] = failedTransactions;
1159
+ $[6] = hasUploadErrors;
1160
+ $[7] = pendingCount;
1161
+ $[8] = permanentErrorCount;
1162
+ $[9] = retryAll;
1163
+ $[10] = t2;
1164
+ $[11] = t3;
1165
+ } else {
1166
+ t3 = $[11];
1167
+ }
1168
+ return t3;
1169
+ }
1170
+ function useSyncActivity() {
1171
+ const $ = _c(19);
1172
+ const {
1173
+ pendingMutations,
1174
+ clearFailure,
1175
+ failedTransactions,
1176
+ completedTransactions,
1177
+ clearCompletedHistory,
1178
+ isUploading,
1179
+ isDownloading
1180
+ } = useSyncStatus();
1181
+ const {
1182
+ triggerSync
1183
+ } = useSyncControl();
1184
+ let t0;
1185
+ if ($[0] !== triggerSync) {
1186
+ t0 = async () => {
1187
+ await triggerSync();
1188
+ };
1189
+ $[0] = triggerSync;
1190
+ $[1] = t0;
1191
+ } else {
1192
+ t0 = $[1];
1193
+ }
1194
+ const retryAll = t0;
1195
+ let t1;
1196
+ if ($[2] !== clearFailure) {
1197
+ t1 = (failureId) => {
1198
+ clearFailure(failureId);
1199
+ };
1200
+ $[2] = clearFailure;
1201
+ $[3] = t1;
1202
+ } else {
1203
+ t1 = $[3];
1204
+ }
1205
+ const dismissFailure = t1;
1206
+ let t2;
1207
+ if ($[4] !== clearCompletedHistory) {
1208
+ t2 = () => {
1209
+ clearCompletedHistory();
1210
+ };
1211
+ $[4] = clearCompletedHistory;
1212
+ $[5] = t2;
1213
+ } else {
1214
+ t2 = $[5];
1215
+ }
1216
+ const clearCompleted = t2;
1217
+ let t3;
1218
+ if ($[6] !== completedTransactions.length || $[7] !== failedTransactions.length || $[8] !== pendingMutations.length) {
1219
+ t3 = {
1220
+ pending: pendingMutations.length,
1221
+ failed: failedTransactions.length,
1222
+ completed: completedTransactions.length
1223
+ };
1224
+ $[6] = completedTransactions.length;
1225
+ $[7] = failedTransactions.length;
1226
+ $[8] = pendingMutations.length;
1227
+ $[9] = t3;
1228
+ } else {
1229
+ t3 = $[9];
1230
+ }
1231
+ const counts = t3;
1232
+ const hasActivity = isUploading || isDownloading || failedTransactions.length > 0;
1233
+ let t4;
1234
+ if ($[10] !== clearCompleted || $[11] !== completedTransactions || $[12] !== counts || $[13] !== dismissFailure || $[14] !== failedTransactions || $[15] !== hasActivity || $[16] !== pendingMutations || $[17] !== retryAll) {
1235
+ t4 = {
1236
+ pending: pendingMutations,
1237
+ failed: failedTransactions,
1238
+ completed: completedTransactions,
1239
+ counts,
1240
+ hasActivity,
1241
+ retryAll,
1242
+ dismissFailure,
1243
+ clearCompleted
1244
+ };
1245
+ $[10] = clearCompleted;
1246
+ $[11] = completedTransactions;
1247
+ $[12] = counts;
1248
+ $[13] = dismissFailure;
1249
+ $[14] = failedTransactions;
1250
+ $[15] = hasActivity;
1251
+ $[16] = pendingMutations;
1252
+ $[17] = retryAll;
1253
+ $[18] = t4;
1254
+ } else {
1255
+ t4 = $[18];
1256
+ }
1257
+ return t4;
1258
+ }
1259
+
1260
+ export {
1261
+ ConflictBus,
1262
+ PowerSyncContext,
1263
+ SyncStatusContext,
1264
+ ConnectionHealthContext,
1265
+ SyncMetricsContext,
1266
+ AttachmentQueueContext,
1267
+ PowerSyncProvider,
1268
+ usePowerSync,
1269
+ useSyncStatus,
1270
+ useSyncControl,
1271
+ useSyncMode,
1272
+ useConnectionHealth,
1273
+ useSyncMetrics,
1274
+ useAttachmentQueue,
1275
+ useDatabase,
1276
+ usePlatform,
1277
+ useOnlineStatus,
1278
+ usePendingMutations,
1279
+ useIsSyncing,
1280
+ useDownloadProgress,
1281
+ useEntitySyncStatus,
1282
+ useUploadStatus,
1283
+ useSyncActivity
1284
+ };
1285
+ //# sourceMappingURL=chunk-GMFDCVMZ.js.map