@pol-studios/powersync 1.0.6 → 1.0.7

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