@pol-studios/powersync 1.0.25 → 1.0.32

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/README.md +0 -1
  2. package/dist/{CacheSettingsManager-uz-kbnRH.d.ts → CacheSettingsManager-0H_7thHW.d.ts} +21 -3
  3. package/dist/attachments/index.d.ts +30 -30
  4. package/dist/attachments/index.js +13 -4
  5. package/dist/{background-sync-ChCXW-EV.d.ts → background-sync-BujnI3IR.d.ts} +1 -1
  6. package/dist/{chunk-55DKCJV4.js → chunk-2RDWLXJW.js} +408 -78
  7. package/dist/chunk-2RDWLXJW.js.map +1 -0
  8. package/dist/{chunk-P4HZA6ZT.js → chunk-4665ZSE5.js} +2 -2
  9. package/dist/chunk-4665ZSE5.js.map +1 -0
  10. package/dist/{chunk-XOY2CJ67.js → chunk-4F5B5CZ7.js} +3 -3
  11. package/dist/chunk-5WRI5ZAA.js +31 -0
  12. package/dist/{chunk-BGBQYQV3.js → chunk-65A3SYJZ.js} +193 -299
  13. package/dist/chunk-65A3SYJZ.js.map +1 -0
  14. package/dist/chunk-6SZ64KCZ.js +755 -0
  15. package/dist/chunk-6SZ64KCZ.js.map +1 -0
  16. package/dist/{chunk-YSTEESEG.js → chunk-74TBHWJ4.js} +122 -11
  17. package/dist/chunk-74TBHWJ4.js.map +1 -0
  18. package/dist/chunk-ANXWYQEJ.js +1 -0
  19. package/dist/chunk-ANXWYQEJ.js.map +1 -0
  20. package/dist/{chunk-CAB26E6F.js → chunk-C4J4MLER.js} +29 -24
  21. package/dist/chunk-C4J4MLER.js.map +1 -0
  22. package/dist/{chunk-C5ODS3XH.js → chunk-EOW7JK7Q.js} +9 -16
  23. package/dist/chunk-EOW7JK7Q.js.map +1 -0
  24. package/dist/chunk-HRAVPIAZ.js +220 -0
  25. package/dist/chunk-HRAVPIAZ.js.map +1 -0
  26. package/dist/{chunk-XAEII4ZX.js → chunk-NUGQOTEM.js} +32 -4
  27. package/dist/chunk-NUGQOTEM.js.map +1 -0
  28. package/dist/chunk-OGUFUZSY.js +5415 -0
  29. package/dist/chunk-OGUFUZSY.js.map +1 -0
  30. package/dist/{chunk-VB737IVN.js → chunk-P4D6BQ4X.js} +328 -706
  31. package/dist/chunk-P4D6BQ4X.js.map +1 -0
  32. package/dist/{chunk-CACKC6XG.js → chunk-PGEDE6IM.js} +136 -89
  33. package/dist/chunk-PGEDE6IM.js.map +1 -0
  34. package/dist/{chunk-A4IBBWGO.js → chunk-RALHHPTU.js} +1 -1
  35. package/dist/chunk-RIDSPLE5.js +42 -0
  36. package/dist/chunk-RIDSPLE5.js.map +1 -0
  37. package/dist/{chunk-Z6VOBGTU.js → chunk-UOMHWUHV.js} +2 -12
  38. package/dist/chunk-UOMHWUHV.js.map +1 -0
  39. package/dist/{chunk-WGHNIAF7.js → chunk-YONQYTVH.js} +2 -2
  40. package/dist/chunk-ZAN22NGL.js +13 -0
  41. package/dist/chunk-ZAN22NGL.js.map +1 -0
  42. package/dist/config/index.d.ts +200 -0
  43. package/dist/config/index.js +23 -0
  44. package/dist/config/index.js.map +1 -0
  45. package/dist/connector/index.d.ts +23 -5
  46. package/dist/connector/index.js +4 -2
  47. package/dist/core/index.d.ts +2 -2
  48. package/dist/core/index.js +1 -0
  49. package/dist/error/index.js +1 -0
  50. package/dist/generator/index.js +2 -0
  51. package/dist/generator/index.js.map +1 -1
  52. package/dist/index.d.ts +19 -16
  53. package/dist/index.js +88 -46
  54. package/dist/index.native.d.ts +18 -14
  55. package/dist/index.native.js +93 -44
  56. package/dist/index.web.d.ts +17 -14
  57. package/dist/index.web.js +88 -46
  58. package/dist/maintenance/index.d.ts +2 -2
  59. package/dist/maintenance/index.js +3 -2
  60. package/dist/platform/index.d.ts +1 -1
  61. package/dist/platform/index.js +2 -0
  62. package/dist/platform/index.js.map +1 -1
  63. package/dist/platform/index.native.d.ts +1 -1
  64. package/dist/platform/index.native.js +1 -0
  65. package/dist/platform/index.web.d.ts +1 -1
  66. package/dist/platform/index.web.js +1 -0
  67. package/dist/pol-attachment-queue-DqBvLAEY.d.ts +255 -0
  68. package/dist/provider/index.d.ts +319 -124
  69. package/dist/provider/index.js +21 -16
  70. package/dist/provider/index.native.d.ts +108 -0
  71. package/dist/provider/index.native.js +121 -0
  72. package/dist/provider/index.native.js.map +1 -0
  73. package/dist/provider/index.web.d.ts +16 -0
  74. package/dist/provider/index.web.js +112 -0
  75. package/dist/provider/index.web.js.map +1 -0
  76. package/dist/react/index.d.ts +16 -65
  77. package/dist/react/index.js +2 -9
  78. package/dist/storage/index.d.ts +5 -4
  79. package/dist/storage/index.js +12 -9
  80. package/dist/storage/index.native.d.ts +5 -4
  81. package/dist/storage/index.native.js +8 -5
  82. package/dist/storage/index.web.d.ts +5 -4
  83. package/dist/storage/index.web.js +11 -8
  84. package/dist/storage/upload/index.d.ts +4 -3
  85. package/dist/storage/upload/index.js +4 -2
  86. package/dist/storage/upload/index.native.d.ts +4 -3
  87. package/dist/storage/upload/index.native.js +4 -2
  88. package/dist/storage/upload/index.web.d.ts +2 -1
  89. package/dist/storage/upload/index.web.js +4 -2
  90. package/dist/{supabase-connector-D2oIl2t8.d.ts → supabase-connector-HMxBA9Kg.d.ts} +23 -25
  91. package/dist/sync/index.d.ts +183 -11
  92. package/dist/sync/index.js +13 -3
  93. package/dist/{types-CyvBaAl8.d.ts → types-6QHGELuY.d.ts} +4 -1
  94. package/dist/{types-CDqWh56B.d.ts → types-B9MptP7E.d.ts} +13 -1
  95. package/dist/types-BhAEsJj-.d.ts +330 -0
  96. package/dist/{types-D0WcHrq6.d.ts → types-CGMibJKD.d.ts} +8 -0
  97. package/dist/{types-DiBvmGEi.d.ts → types-DqJnP50o.d.ts} +22 -24
  98. package/dist/{pol-attachment-queue-BE2HU3Us.d.ts → types-JCEhw2Lf.d.ts} +139 -346
  99. package/package.json +18 -4
  100. package/dist/chunk-24RDMMCL.js +0 -44
  101. package/dist/chunk-24RDMMCL.js.map +0 -1
  102. package/dist/chunk-55DKCJV4.js.map +0 -1
  103. package/dist/chunk-654ERHA7.js +0 -1
  104. package/dist/chunk-BGBQYQV3.js.map +0 -1
  105. package/dist/chunk-C5ODS3XH.js.map +0 -1
  106. package/dist/chunk-CAB26E6F.js.map +0 -1
  107. package/dist/chunk-CACKC6XG.js.map +0 -1
  108. package/dist/chunk-P4HZA6ZT.js.map +0 -1
  109. package/dist/chunk-TIFL2KWE.js +0 -358
  110. package/dist/chunk-TIFL2KWE.js.map +0 -1
  111. package/dist/chunk-VB737IVN.js.map +0 -1
  112. package/dist/chunk-XAEII4ZX.js.map +0 -1
  113. package/dist/chunk-YSTEESEG.js.map +0 -1
  114. package/dist/chunk-Z6VOBGTU.js.map +0 -1
  115. /package/dist/{chunk-XOY2CJ67.js.map → chunk-4F5B5CZ7.js.map} +0 -0
  116. /package/dist/{chunk-654ERHA7.js.map → chunk-5WRI5ZAA.js.map} +0 -0
  117. /package/dist/{chunk-A4IBBWGO.js.map → chunk-RALHHPTU.js.map} +0 -0
  118. /package/dist/{chunk-WGHNIAF7.js.map → chunk-YONQYTVH.js.map} +0 -0
@@ -1,19 +1,18 @@
1
1
  import {
2
- PowerSyncErrorBoundary
3
- } from "./chunk-P6WOZO7H.js";
4
- import {
5
- createPolAttachmentQueue
6
- } from "./chunk-CACKC6XG.js";
2
+ createPolAttachmentQueue,
3
+ getCustomUrlResolver,
4
+ isCustomSource,
5
+ isSignedUrlSource,
6
+ resolveBucketFromConfig
7
+ } from "./chunk-PGEDE6IM.js";
7
8
  import {
9
+ DEFAULT_CONNECTION_HEALTH,
10
+ DEFAULT_SYNC_METRICS,
11
+ DEFAULT_SYNC_STATUS,
8
12
  HealthMonitor,
9
13
  MetricsCollector,
10
14
  SyncStatusTracker
11
- } from "./chunk-55DKCJV4.js";
12
- import {
13
- DEFAULT_CONNECTION_HEALTH,
14
- DEFAULT_SYNC_METRICS,
15
- DEFAULT_SYNC_STATUS
16
- } from "./chunk-24RDMMCL.js";
15
+ } from "./chunk-2RDWLXJW.js";
17
16
  import {
18
17
  AttachmentQueueContext,
19
18
  CompletedTransactionsContext,
@@ -30,19 +29,13 @@ import {
30
29
  usePendingMutationsContext,
31
30
  usePowerSync,
32
31
  useSyncStatus
33
- } from "./chunk-YSTEESEG.js";
34
- import {
35
- createSupabaseUploadHandler
36
- } from "./chunk-CAB26E6F.js";
32
+ } from "./chunk-74TBHWJ4.js";
37
33
  import {
38
34
  SupabaseStorageAdapter
39
- } from "./chunk-XAEII4ZX.js";
40
- import {
41
- createNativePlatformAdapter
42
- } from "./chunk-WN5ZJ3E2.js";
35
+ } from "./chunk-NUGQOTEM.js";
43
36
  import {
44
37
  SupabaseConnector
45
- } from "./chunk-BGBQYQV3.js";
38
+ } from "./chunk-65A3SYJZ.js";
46
39
  import {
47
40
  createSyncError,
48
41
  extractEntityIds,
@@ -120,6 +113,10 @@ var ConflictBus = class _ConflictBus {
120
113
  }
121
114
  };
122
115
 
116
+ // src/provider/constants.ts
117
+ var UPLOAD_MAX_RETRIES = 7;
118
+ var UPLOAD_BACKOFF_DELAYS = [4, 8, 16, 32, 64, 128, 256];
119
+
123
120
  // src/provider/PowerSyncProvider.tsx
124
121
  import { jsx } from "react/jsx-runtime";
125
122
  function PowerSyncProvider({
@@ -134,6 +131,7 @@ function PowerSyncProvider({
134
131
  schema,
135
132
  powerSyncUrl,
136
133
  supabaseClient,
134
+ queryClient,
137
135
  dbFilename = "powersync.db",
138
136
  connector: connectorConfig,
139
137
  attachments: attachmentConfig,
@@ -170,6 +168,13 @@ function PowerSyncProvider({
170
168
  const [failedTransactions, setFailedTransactions] = useState([]);
171
169
  const [completedTransactions, setCompletedTransactions] = useState([]);
172
170
  const [newCompletedTransactions, setNewCompletedTransactions] = useState([]);
171
+ const [uploadRetryState, setUploadRetryState] = useState({
172
+ retryCount: 0,
173
+ nextRetryAt: null,
174
+ isWaitingForRetry: false,
175
+ maxRetriesReached: false
176
+ });
177
+ const failureHandledThisCycleRef = useRef(false);
173
178
  const [connectionHealth, setConnectionHealth] = useState(DEFAULT_CONNECTION_HEALTH);
174
179
  const [syncMetrics, setSyncMetrics] = useState(DEFAULT_SYNC_METRICS);
175
180
  const [isAutoOffline, setIsAutoOffline] = useState(false);
@@ -192,6 +197,9 @@ function PowerSyncProvider({
192
197
  const syncModeRef = useRef("push-pull");
193
198
  const removePendingMutationRef = useRef(() => {
194
199
  });
200
+ const removePendingMutationsRef = useRef(() => {
201
+ });
202
+ const uploadRetryTimeoutRef = useRef(null);
195
203
  const onSyncStatusChangeRef = useRef(onSyncStatusChange);
196
204
  const onReadyRef = useRef(onReady);
197
205
  const onErrorRef = useRef(onError);
@@ -313,6 +321,13 @@ function PowerSyncProvider({
313
321
  setIsReady(true);
314
322
  setIsInitializing(false);
315
323
  healthMonitorRef.current?.setDatabase(database);
324
+ if (statusTrackerRef.current) {
325
+ statusTrackerRef.current.setDatabaseAndInit(database).then(() => {
326
+ setCompletedTransactions(statusTrackerRef.current?.getCompletedTransactions() ?? []);
327
+ setNewCompletedTransactions(statusTrackerRef.current?.getNewCompletedTransactions() ?? []);
328
+ setFailedTransactions(statusTrackerRef.current?.getFailedTransactions() ?? []);
329
+ });
330
+ }
316
331
  if (mergedSyncConfig.enableHealthMonitoring) {
317
332
  healthMonitorRef.current?.start();
318
333
  }
@@ -387,6 +402,7 @@ function PowerSyncProvider({
387
402
  schemaRouter: connectorConfig?.schemaRouter,
388
403
  crudHandler: connectorConfig?.crudHandler,
389
404
  retryConfig: connectorConfig?.retryConfig,
405
+ uploadErrorMiddleware: connectorConfig?.uploadErrorMiddleware,
390
406
  logger,
391
407
  // Conflict detection - enabled by default
392
408
  conflictDetection: {
@@ -395,21 +411,84 @@ function PowerSyncProvider({
395
411
  conflictBus,
396
412
  // Check if uploads should be performed based on sync mode
397
413
  shouldUpload: () => statusTrackerRef.current?.shouldUpload() ?? true,
398
- // Clear failures when transaction succeeds
414
+ // Clear failures when transaction succeeds (auto-clear on success)
399
415
  onTransactionSuccess: (entries) => {
400
416
  if (!statusTracker_0) return;
401
- const entityIds = extractEntityIds(entries);
402
- entityIds.forEach((id) => {
403
- const failures = statusTracker_0.getFailuresForEntity(id);
404
- failures.forEach((f) => statusTracker_0.clearFailure(f.id));
405
- });
417
+ const entryIds = entries.map((e) => e.id);
418
+ statusTracker_0.clearSuccessfulEntries(entryIds);
406
419
  setFailedTransactions(statusTracker_0.getFailedTransactions());
420
+ failureHandledThisCycleRef.current = false;
421
+ if (uploadRetryTimeoutRef.current) {
422
+ clearTimeout(uploadRetryTimeoutRef.current);
423
+ uploadRetryTimeoutRef.current = null;
424
+ }
425
+ setUploadRetryState({
426
+ retryCount: 0,
427
+ nextRetryAt: null,
428
+ isWaitingForRetry: false,
429
+ maxRetriesReached: false
430
+ });
407
431
  },
408
- // Record failures when transaction fails
432
+ // Record failures when transaction fails with disconnect-based exponential backoff
409
433
  onTransactionFailure: (entries_0, error_0, classified) => {
410
434
  if (!statusTracker_0) return;
411
435
  statusTracker_0.recordTransactionFailure(entries_0, createSyncError(classified, error_0.message), classified.isPermanent, extractEntityIds(entries_0), extractTableNames(entries_0));
412
436
  setFailedTransactions(statusTracker_0.getFailedTransactions());
437
+ if (failureHandledThisCycleRef.current) {
438
+ logger.debug("[PowerSyncProvider] Failure already handled this cycle, skipping backoff");
439
+ return;
440
+ }
441
+ failureHandledThisCycleRef.current = true;
442
+ const BACKOFF_DELAYS = UPLOAD_BACKOFF_DELAYS;
443
+ const MAX_RETRIES = UPLOAD_MAX_RETRIES;
444
+ if (uploadRetryTimeoutRef.current) {
445
+ clearTimeout(uploadRetryTimeoutRef.current);
446
+ uploadRetryTimeoutRef.current = null;
447
+ }
448
+ setUploadRetryState((prev) => {
449
+ const newRetryCount = prev.retryCount + 1;
450
+ if (newRetryCount > MAX_RETRIES) {
451
+ logger.warn(`[PowerSyncProvider] Max upload retries (${MAX_RETRIES}) reached, staying disconnected`);
452
+ return {
453
+ retryCount: newRetryCount,
454
+ nextRetryAt: null,
455
+ isWaitingForRetry: false,
456
+ maxRetriesReached: true
457
+ };
458
+ }
459
+ const delaySeconds = BACKOFF_DELAYS[Math.min(newRetryCount - 1, BACKOFF_DELAYS.length - 1)];
460
+ const delayMs = delaySeconds * 1e3;
461
+ const nextRetryAt = new Date(Date.now() + delayMs);
462
+ logger.info(`[PowerSyncProvider] Upload failed (attempt ${newRetryCount}/${MAX_RETRIES}), disconnecting and retrying in ${delaySeconds}s`);
463
+ db.disconnect().catch((err_1) => {
464
+ logger.warn("[PowerSyncProvider] Error during backoff disconnect:", err_1);
465
+ });
466
+ uploadRetryTimeoutRef.current = setTimeout(async () => {
467
+ uploadRetryTimeoutRef.current = null;
468
+ failureHandledThisCycleRef.current = false;
469
+ logger.info(`[PowerSyncProvider] Backoff complete, reconnecting for retry attempt ${newRetryCount}`);
470
+ setUploadRetryState((curr) => ({
471
+ ...curr,
472
+ isWaitingForRetry: false,
473
+ nextRetryAt: null
474
+ }));
475
+ const currentConnector = connectorRef.current;
476
+ if (currentConnector && db && !dbClosedRef.current) {
477
+ try {
478
+ await db.connect(currentConnector);
479
+ logger.info("[PowerSyncProvider] Reconnected after backoff");
480
+ } catch (reconnectErr) {
481
+ logger.error("[PowerSyncProvider] Failed to reconnect after backoff:", reconnectErr);
482
+ }
483
+ }
484
+ }, delayMs);
485
+ return {
486
+ retryCount: newRetryCount,
487
+ nextRetryAt,
488
+ isWaitingForRetry: true,
489
+ maxRetriesReached: false
490
+ };
491
+ });
413
492
  },
414
493
  // Record completed transactions
415
494
  onTransactionComplete: (entries_1) => {
@@ -417,6 +496,7 @@ function PowerSyncProvider({
417
496
  statusTracker_0.recordTransactionComplete(entries_1);
418
497
  setCompletedTransactions(statusTracker_0.getCompletedTransactions());
419
498
  setNewCompletedTransactions(statusTracker_0.getNewCompletedTransactions());
499
+ removePendingMutationsRef.current(entries_1.map((e_0) => e_0.id));
420
500
  }
421
501
  });
422
502
  if (abortController.signal.aborted) {
@@ -537,7 +617,7 @@ function PowerSyncProvider({
537
617
  } catch {
538
618
  return null;
539
619
  }
540
- }).filter((e) => e !== null);
620
+ }).filter((e_1) => e_1 !== null);
541
621
  if (!dbClosedRef.current) {
542
622
  statusTrackerRef.current?.updatePendingMutations(mutations);
543
623
  setPendingMutations(mutations);
@@ -550,22 +630,32 @@ function PowerSyncProvider({
550
630
  ...entry,
551
631
  createdAt: entry.createdAt ?? /* @__PURE__ */ new Date()
552
632
  };
553
- setPendingMutations((prev) => {
554
- const newMutations = [...prev, entryWithTimestamp];
633
+ setPendingMutations((prev_0) => {
634
+ const newMutations = [...prev_0, entryWithTimestamp];
555
635
  statusTrackerRef.current?.updatePendingMutations(newMutations);
556
636
  return newMutations;
557
637
  });
558
638
  }, []);
559
- const removePendingMutation = useCallback((id_0) => {
560
- setPendingMutations((prev_0) => {
561
- const newMutations_0 = prev_0.filter((m) => m.id !== id_0);
639
+ const removePendingMutation = useCallback((id) => {
640
+ setPendingMutations((prev_1) => {
641
+ const newMutations_0 = prev_1.filter((m) => m.id !== id);
562
642
  statusTrackerRef.current?.updatePendingMutations(newMutations_0);
563
643
  return newMutations_0;
564
644
  });
565
645
  }, []);
646
+ const removePendingMutations = useCallback((ids) => {
647
+ if (ids.length === 0) return;
648
+ const idSet = new Set(ids);
649
+ setPendingMutations((prev_2) => {
650
+ const newMutations_1 = prev_2.filter((m_0) => !idSet.has(m_0.id));
651
+ statusTrackerRef.current?.updatePendingMutations(newMutations_1);
652
+ return newMutations_1;
653
+ });
654
+ }, []);
566
655
  useEffect(() => {
567
656
  removePendingMutationRef.current = removePendingMutation;
568
- }, [removePendingMutation]);
657
+ removePendingMutationsRef.current = removePendingMutations;
658
+ }, [removePendingMutation, removePendingMutations]);
569
659
  useEffect(() => {
570
660
  if (!db) return;
571
661
  dbClosedRef.current = false;
@@ -581,19 +671,36 @@ function PowerSyncProvider({
581
671
  const initAttachmentQueue = async () => {
582
672
  try {
583
673
  logger.info("[PowerSyncProvider] Initializing attachment queue...");
674
+ const bucket = resolveBucketFromConfig(attachmentConfig);
675
+ if (!bucket && !isCustomSource(attachmentConfig)) {
676
+ throw new Error("[PowerSyncProvider] Attachment config requires source.bucket or a custom source");
677
+ }
678
+ if (isCustomSource(attachmentConfig)) {
679
+ const resolver = getCustomUrlResolver(attachmentConfig);
680
+ if (!resolver) {
681
+ throw new Error('[PowerSyncProvider] Custom attachment source requires a getUrl function. Provide: source: { type: "custom", getUrl: (path) => "https://..." }');
682
+ }
683
+ }
684
+ const useSignedUrls = isSignedUrlSource(attachmentConfig);
685
+ const customUrlResolver = getCustomUrlResolver(attachmentConfig);
686
+ const sourceCompression = attachmentConfig.source?.type === "supabase-bucket" ? attachmentConfig.source.compression : void 0;
584
687
  const remoteStorage = new SupabaseStorageAdapter({
585
688
  client: supabaseClient,
586
- defaultBucket: attachmentConfig.bucket,
689
+ defaultBucket: bucket ?? "",
587
690
  logger,
588
- imageTransform: attachmentConfig.compression ? {
589
- enabled: attachmentConfig.compression.enabled ?? true,
590
- width: attachmentConfig.compression.maxWidth,
591
- quality: attachmentConfig.compression.quality ? Math.round(attachmentConfig.compression.quality * 100) : void 0
691
+ useSignedUrls,
692
+ customUrlResolver,
693
+ imageTransform: sourceCompression ? {
694
+ enabled: sourceCompression.enabled ?? true,
695
+ width: sourceCompression.maxWidth,
696
+ quality: sourceCompression.quality ? Math.round(sourceCompression.quality * 100) : void 0
592
697
  } : void 0
593
698
  }, platform.fileSystem);
594
699
  const queueOptions = {
595
700
  ...attachmentConfig,
596
- remoteStorage
701
+ remoteStorage,
702
+ supabaseClient
703
+ // Pass supabase client for watchPaths callback
597
704
  };
598
705
  const queue = createPolAttachmentQueue(db, platform, queueOptions);
599
706
  await queue.init();
@@ -605,9 +712,9 @@ function PowerSyncProvider({
605
712
  setAttachmentQueue(queue);
606
713
  setAttachmentQueueReady(true);
607
714
  logger.info("[PowerSyncProvider] Attachment queue initialized successfully");
608
- } catch (err_1) {
715
+ } catch (err_2) {
609
716
  if (!controller_0.cancelled) {
610
- logger.error("[PowerSyncProvider] Attachment queue initialization failed:", err_1);
717
+ logger.error("[PowerSyncProvider] Attachment queue initialization failed:", err_2);
611
718
  setAttachmentQueueReady(true);
612
719
  }
613
720
  }
@@ -635,16 +742,20 @@ function PowerSyncProvider({
635
742
  attachmentQueueRef.current?.dispose();
636
743
  healthMonitorRef.current?.stop();
637
744
  conflictBusRef.current?.destroy();
745
+ if (uploadRetryTimeoutRef.current) {
746
+ clearTimeout(uploadRetryTimeoutRef.current);
747
+ uploadRetryTimeoutRef.current = null;
748
+ }
638
749
  if (db) {
639
750
  cleanupPromiseRef.current = (async () => {
640
751
  try {
641
752
  await db.disconnect();
642
753
  await db.close();
643
754
  logger.debug("[PowerSyncProvider] Database cleanup completed");
644
- } catch (err_2) {
645
- const errorMessage = err_2 instanceof Error ? err_2.message : String(err_2);
755
+ } catch (err_3) {
756
+ const errorMessage = err_3 instanceof Error ? err_3.message : String(err_3);
646
757
  if (!errorMessage.includes("not open") && !errorMessage.includes("closed")) {
647
- logger.warn("[PowerSyncProvider] Error during cleanup:", err_2);
758
+ logger.warn("[PowerSyncProvider] Error during cleanup:", err_3);
648
759
  }
649
760
  } finally {
650
761
  isCleaningUpRef.current = false;
@@ -701,8 +812,8 @@ function PowerSyncProvider({
701
812
  try {
702
813
  await db.connect(connector);
703
814
  logger.info("[PowerSyncProvider] Reconnected after network restore");
704
- } catch (err_3) {
705
- logger.warn("[PowerSyncProvider] Failed to reconnect after network restore:", err_3);
815
+ } catch (err_4) {
816
+ logger.warn("[PowerSyncProvider] Failed to reconnect after network restore:", err_4);
706
817
  }
707
818
  }
708
819
  }
@@ -733,8 +844,8 @@ function PowerSyncProvider({
733
844
  if (db && connector && !db.connected) {
734
845
  db.connect(connector).then(() => {
735
846
  logger.info("[PowerSyncProvider] Reconnected after auto-resume on startup");
736
- }).catch((err_4) => {
737
- logger.warn("[PowerSyncProvider] Failed to reconnect after auto-resume on startup:", err_4);
847
+ }).catch((err_5) => {
848
+ logger.warn("[PowerSyncProvider] Failed to reconnect after auto-resume on startup:", err_5);
738
849
  });
739
850
  }
740
851
  }
@@ -754,75 +865,66 @@ function PowerSyncProvider({
754
865
  tracker_3.clearFailure(failureId);
755
866
  setFailedTransactions(tracker_3.getFailedTransactions());
756
867
  }, [logger]);
757
- const clearAllFailures = useCallback(() => {
868
+ const clearCompletedHistory = useCallback(() => {
758
869
  const tracker_4 = statusTrackerRef.current;
759
870
  if (!tracker_4) {
760
- logger.warn("[PowerSyncProvider] Cannot clear failures - tracker not initialized");
871
+ logger.warn("[PowerSyncProvider] Cannot clear completed history - tracker not initialized");
761
872
  return;
762
873
  }
763
- tracker_4.clearAllFailures();
764
- setFailedTransactions(tracker_4.getFailedTransactions());
874
+ tracker_4.clearCompletedHistory();
875
+ setCompletedTransactions(tracker_4.getCompletedTransactions());
876
+ setNewCompletedTransactions(tracker_4.getNewCompletedTransactions());
765
877
  }, [logger]);
766
- const clearCompletedHistory = useCallback(() => {
878
+ const clearCompletedItem = useCallback((completedId) => {
767
879
  const tracker_5 = statusTrackerRef.current;
768
880
  if (!tracker_5) {
769
- logger.warn("[PowerSyncProvider] Cannot clear completed history - tracker not initialized");
881
+ logger.warn("[PowerSyncProvider] Cannot clear completed item - tracker not initialized");
770
882
  return;
771
883
  }
772
- tracker_5.clearCompletedHistory();
884
+ tracker_5.clearCompletedItem(completedId);
773
885
  setCompletedTransactions(tracker_5.getCompletedTransactions());
774
886
  setNewCompletedTransactions(tracker_5.getNewCompletedTransactions());
775
887
  }, [logger]);
776
- const clearCompletedItem = useCallback((completedId) => {
888
+ const markNotificationsAsSeen = useCallback(() => {
777
889
  const tracker_6 = statusTrackerRef.current;
778
890
  if (!tracker_6) {
779
- logger.warn("[PowerSyncProvider] Cannot clear completed item - tracker not initialized");
891
+ logger.warn("[PowerSyncProvider] Cannot mark notifications as seen - tracker not initialized");
780
892
  return;
781
893
  }
782
- tracker_6.clearCompletedItem(completedId);
783
- setCompletedTransactions(tracker_6.getCompletedTransactions());
894
+ tracker_6.markNotificationsAsSeen();
784
895
  setNewCompletedTransactions(tracker_6.getNewCompletedTransactions());
785
896
  }, [logger]);
786
- const markNotificationsAsSeen = useCallback(() => {
897
+ const setSyncMode = useCallback(async (mode) => {
787
898
  const tracker_7 = statusTrackerRef.current;
788
899
  if (!tracker_7) {
789
- logger.warn("[PowerSyncProvider] Cannot mark notifications as seen - tracker not initialized");
790
- return;
791
- }
792
- tracker_7.markNotificationsAsSeen();
793
- setNewCompletedTransactions(tracker_7.getNewCompletedTransactions());
794
- }, [logger]);
795
- const setSyncMode = useCallback(async (mode) => {
796
- const tracker_8 = statusTrackerRef.current;
797
- if (!tracker_8) {
798
900
  logger.warn("[PowerSyncProvider] Cannot set sync mode - tracker not initialized");
799
901
  return;
800
902
  }
801
- await tracker_8.setIsAutoOffline(false);
903
+ await tracker_7.setIsAutoOffline(false);
802
904
  setIsAutoOffline(false);
803
- await tracker_8.setSyncMode(mode);
905
+ await tracker_7.setSyncMode(mode);
804
906
  setSyncModeState({
805
907
  loaded: true,
806
908
  mode
807
909
  });
808
910
  }, [logger]);
809
911
  const setForceNextUpload = useCallback((force) => {
810
- const tracker_9 = statusTrackerRef.current;
811
- if (!tracker_9) {
912
+ const tracker_8 = statusTrackerRef.current;
913
+ if (!tracker_8) {
812
914
  logger.warn("[PowerSyncProvider] Cannot set force upload - tracker not initialized");
813
915
  return;
814
916
  }
815
- tracker_9.setForceNextUpload(force);
917
+ tracker_8.setForceNextUpload(force);
816
918
  }, [logger]);
817
919
  const setAutoOfflineMode = useCallback(async (mode_0, isAuto) => {
818
- const tracker_10 = statusTrackerRef.current;
819
- if (!tracker_10) {
920
+ const tracker_9 = statusTrackerRef.current;
921
+ if (!tracker_9) {
820
922
  logger.warn("[PowerSyncProvider] Cannot set sync mode - tracker not initialized");
821
923
  return;
822
924
  }
823
- await tracker_10.setIsAutoOffline(isAuto);
925
+ await tracker_9.setIsAutoOffline(isAuto);
824
926
  setIsAutoOffline(isAuto);
825
- await tracker_10.setSyncMode(mode_0);
927
+ await tracker_9.setSyncMode(mode_0);
826
928
  setSyncModeState({
827
929
  loaded: true,
828
930
  mode: mode_0
@@ -853,51 +955,81 @@ function PowerSyncProvider({
853
955
  }
854
956
  }
855
957
  }, [db, connector, syncStatus.uploading, logger]);
856
- const discardAllPendingMutations = useCallback(async () => {
857
- if (!db || !connector) {
858
- logger.warn("[PowerSync] Cannot discard all - not initialized");
958
+ const manualUploadRetry = useCallback(async () => {
959
+ const currentConnector_0 = connectorRef.current;
960
+ if (!db || !currentConnector_0) {
961
+ logger.warn("[PowerSyncProvider] Cannot manual retry - not initialized");
859
962
  return;
860
963
  }
861
- if (syncStatus.uploading) {
862
- throw new Error("Cannot discard while upload is in progress");
964
+ if (uploadRetryTimeoutRef.current) {
965
+ clearTimeout(uploadRetryTimeoutRef.current);
966
+ uploadRetryTimeoutRef.current = null;
863
967
  }
864
- logger.info("[PowerSync] Discarding all pending mutations");
865
- await db.disconnect();
968
+ failureHandledThisCycleRef.current = false;
969
+ setUploadRetryState({
970
+ retryCount: 0,
971
+ nextRetryAt: null,
972
+ isWaitingForRetry: false,
973
+ maxRetriesReached: false
974
+ });
975
+ logger.info("[PowerSyncProvider] Manual upload retry triggered");
866
976
  try {
867
- await db.execute("DELETE FROM ps_crud");
868
- logger.info("[PowerSync] All mutations discarded successfully");
869
- } finally {
870
- const currentConnector = connectorRef.current;
871
- if (currentConnector && db) {
872
- try {
873
- await db.connect(currentConnector);
874
- } catch (reconnectError) {
875
- logger.error("[PowerSync] Failed to reconnect after discard:", reconnectError);
876
- throw reconnectError;
877
- }
977
+ if (db.connected) {
978
+ await db.disconnect();
878
979
  }
980
+ await db.connect(currentConnector_0);
981
+ logger.info("[PowerSyncProvider] Reconnected after manual retry");
982
+ } catch (err_6) {
983
+ logger.error("[PowerSyncProvider] Manual retry failed:", err_6);
879
984
  }
880
- }, [db, connector, syncStatus.uploading, logger]);
881
- const pauseAutoRetry = useCallback(() => {
882
- if (!connector) {
883
- logger.warn("[PowerSyncProvider] Cannot pause auto-retry - connector not initialized");
985
+ }, [db, logger]);
986
+ const discardFailedEntryAndReconnect = useCallback(async (entryId) => {
987
+ const currentConnector_1 = connectorRef.current;
988
+ const tracker_10 = statusTrackerRef.current;
989
+ if (!db || !currentConnector_1) {
990
+ logger.warn("[PowerSyncProvider] Cannot discard failed entry - not initialized");
884
991
  return;
885
992
  }
886
- connector.pauseAutoRetry();
887
- }, [connector, logger]);
888
- const resumeAutoRetry = useCallback(() => {
889
- if (!connector) {
890
- logger.warn("[PowerSyncProvider] Cannot resume auto-retry - connector not initialized");
891
- return;
993
+ if (uploadRetryTimeoutRef.current) {
994
+ clearTimeout(uploadRetryTimeoutRef.current);
995
+ uploadRetryTimeoutRef.current = null;
996
+ }
997
+ logger.info("[PowerSyncProvider] Discarding entry", entryId, "and reconnecting");
998
+ await db.disconnect();
999
+ try {
1000
+ await db.execute("DELETE FROM ps_crud WHERE id = ?", [entryId]);
1001
+ logger.info("[PowerSyncProvider] Entry", entryId, "discarded");
1002
+ if (tracker_10) {
1003
+ const failures = tracker_10.getFailedTransactions();
1004
+ for (const failure of failures) {
1005
+ const hasEntry = failure.entries.some((e_2) => e_2.clientId === entryId);
1006
+ if (hasEntry) {
1007
+ tracker_10.clearFailure(failure.id);
1008
+ break;
1009
+ }
1010
+ }
1011
+ setFailedTransactions(tracker_10.getFailedTransactions());
1012
+ }
1013
+ failureHandledThisCycleRef.current = false;
1014
+ setUploadRetryState({
1015
+ retryCount: 0,
1016
+ nextRetryAt: null,
1017
+ isWaitingForRetry: false,
1018
+ maxRetriesReached: false
1019
+ });
1020
+ await db.connect(currentConnector_1);
1021
+ logger.info("[PowerSyncProvider] Reconnected after discarding entry", entryId);
1022
+ } catch (err_7) {
1023
+ logger.error("[PowerSyncProvider] Failed to discard entry and reconnect:", err_7);
1024
+ throw err_7;
892
1025
  }
893
- connector.resumeAutoRetry();
894
- }, [connector, logger]);
1026
+ }, [db, logger]);
895
1027
  const retryFailure = useCallback(async (failureId_0) => {
896
1028
  const tracker_11 = statusTrackerRef.current;
897
1029
  if (!tracker_11) return;
898
1030
  const failures_0 = tracker_11.getFailedTransactions();
899
- const failure = failures_0.find((f_0) => f_0.id === failureId_0);
900
- if (!failure) {
1031
+ const failure_0 = failures_0.find((f) => f.id === failureId_0);
1032
+ if (!failure_0) {
901
1033
  logger.warn("[PowerSyncProvider] Failure not found:", failureId_0);
902
1034
  return;
903
1035
  }
@@ -906,9 +1038,9 @@ function PowerSyncProvider({
906
1038
  setFailedTransactions(tracker_11.getFailedTransactions());
907
1039
  if (!db || !connector) {
908
1040
  logger.warn("[PowerSyncProvider] Cannot retry - not initialized");
909
- tracker_11.recordTransactionFailure(failure.entries, failure.error, failure.isPermanent, failure.affectedEntityIds, failure.affectedTables, {
910
- retryCount: failure.retryCount,
911
- firstFailedAt: failure.firstFailedAt
1041
+ tracker_11.recordTransactionFailure(failure_0.entries, failure_0.error, failure_0.isPermanent, failure_0.affectedEntityIds, failure_0.affectedTables, {
1042
+ retryCount: failure_0.retryCount,
1043
+ firstFailedAt: failure_0.firstFailedAt
912
1044
  });
913
1045
  setFailedTransactions(tracker_11.getFailedTransactions());
914
1046
  return;
@@ -919,15 +1051,64 @@ function PowerSyncProvider({
919
1051
  }
920
1052
  await db.connect(connector);
921
1053
  logger.info("[PowerSyncProvider] Retry triggered for failure:", failureId_0);
922
- } catch (err_5) {
923
- logger.error("[PowerSyncProvider] Retry failed, re-recording failure:", err_5);
924
- tracker_11.recordTransactionFailure(failure.entries, failure.error, failure.isPermanent, failure.affectedEntityIds, failure.affectedTables, {
925
- retryCount: failure.retryCount,
926
- firstFailedAt: failure.firstFailedAt
1054
+ } catch (err_8) {
1055
+ logger.error("[PowerSyncProvider] Retry failed, re-recording failure:", err_8);
1056
+ tracker_11.recordTransactionFailure(failure_0.entries, failure_0.error, failure_0.isPermanent, failure_0.affectedEntityIds, failure_0.affectedTables, {
1057
+ retryCount: failure_0.retryCount,
1058
+ firstFailedAt: failure_0.firstFailedAt
927
1059
  });
928
1060
  setFailedTransactions(tracker_11.getFailedTransactions());
929
1061
  }
930
1062
  }, [db, connector, logger]);
1063
+ const resetSync = useCallback(async (options) => {
1064
+ const {
1065
+ clearAttachments = true,
1066
+ clearQueryCache = true,
1067
+ timeout = 3e4
1068
+ } = options ?? {};
1069
+ logger.info("[PowerSyncProvider] Starting sync reset...", {
1070
+ clearAttachments,
1071
+ clearQueryCache,
1072
+ timeout
1073
+ });
1074
+ if (!db) {
1075
+ logger.warn("[PowerSyncProvider] Cannot reset sync: database not initialized");
1076
+ return;
1077
+ }
1078
+ try {
1079
+ logger.info("[PowerSyncProvider] Disconnecting and clearing sync data...");
1080
+ await db.disconnectAndClear({
1081
+ clearLocal: false
1082
+ });
1083
+ logger.info("[PowerSyncProvider] Sync data cleared");
1084
+ if (clearQueryCache && queryClient) {
1085
+ try {
1086
+ logger.info("[PowerSyncProvider] Clearing React Query cache...");
1087
+ queryClient.clear();
1088
+ logger.info("[PowerSyncProvider] React Query cache cleared");
1089
+ } catch (cacheError) {
1090
+ logger.error("[PowerSyncProvider] Failed to clear React Query cache:", cacheError);
1091
+ }
1092
+ }
1093
+ if (clearAttachments && attachmentQueue) {
1094
+ try {
1095
+ logger.info("[PowerSyncProvider] Clearing attachment cache...");
1096
+ const clearPromise = attachmentQueue.clearCache();
1097
+ const timeoutPromise_0 = new Promise((_, reject) => {
1098
+ setTimeout(() => reject(new Error("Attachment cache clear timed out")), timeout);
1099
+ });
1100
+ await Promise.race([clearPromise, timeoutPromise_0]);
1101
+ logger.info("[PowerSyncProvider] Attachment cache cleared");
1102
+ } catch (attachmentError) {
1103
+ logger.error("[PowerSyncProvider] Failed to clear attachment cache:", attachmentError);
1104
+ }
1105
+ }
1106
+ logger.info("[PowerSyncProvider] Sync reset completed successfully");
1107
+ } catch (err_9) {
1108
+ logger.error("[PowerSyncProvider] Sync reset failed:", err_9);
1109
+ throw err_9;
1110
+ }
1111
+ }, [db, queryClient, attachmentQueue, logger]);
931
1112
  const powerSyncContextValue = useMemo(() => ({
932
1113
  db,
933
1114
  connector,
@@ -938,8 +1119,9 @@ function PowerSyncProvider({
938
1119
  error,
939
1120
  schema,
940
1121
  platform,
941
- conflictBus
942
- }), [db, connector, attachmentQueue, isReady, isInitializing, attachmentQueueReady, error, schema, platform, conflictBus]);
1122
+ conflictBus,
1123
+ resetSync
1124
+ }), [db, connector, attachmentQueue, isReady, isInitializing, attachmentQueueReady, error, schema, platform, conflictBus, resetSync]);
943
1125
  const syncStatusContextValue = useMemo(() => ({
944
1126
  status: syncStatus,
945
1127
  pendingMutations,
@@ -955,10 +1137,9 @@ function PowerSyncProvider({
955
1137
  // Failed transaction fields
956
1138
  failedTransactions,
957
1139
  hasUploadErrors: failedTransactions.length > 0,
958
- permanentErrorCount: failedTransactions.filter((f_1) => f_1.isPermanent).length,
1140
+ permanentErrorCount: failedTransactions.filter((f_0) => f_0.isPermanent).length,
959
1141
  // Clear failure functions
960
1142
  clearFailure,
961
- clearAllFailures,
962
1143
  // Completed transaction fields
963
1144
  completedTransactions,
964
1145
  clearCompletedHistory,
@@ -967,11 +1148,14 @@ function PowerSyncProvider({
967
1148
  setForceNextUpload,
968
1149
  // Discard mutation functions
969
1150
  discardPendingMutation,
970
- discardAllPendingMutations,
971
- // Retry control functions
972
- pauseAutoRetry,
973
- resumeAutoRetry
974
- }), [syncStatus, pendingMutations, syncModeState.mode, lastSyncedAt, connectionError, failedTransactions, clearFailure, clearAllFailures, completedTransactions, clearCompletedHistory, setSyncMode, setForceNextUpload, discardPendingMutation, discardAllPendingMutations, pauseAutoRetry, resumeAutoRetry]);
1151
+ // Upload retry state
1152
+ isWaitingForUploadRetry: uploadRetryState.isWaitingForRetry,
1153
+ nextUploadRetryAt: uploadRetryState.nextRetryAt,
1154
+ maxUploadRetriesReached: uploadRetryState.maxRetriesReached,
1155
+ uploadRetryCount: uploadRetryState.retryCount,
1156
+ manualUploadRetry,
1157
+ discardFailedEntryAndReconnect
1158
+ }), [syncStatus, pendingMutations, syncModeState.mode, lastSyncedAt, connectionError, failedTransactions, clearFailure, completedTransactions, clearCompletedHistory, setSyncMode, setForceNextUpload, discardPendingMutation, uploadRetryState, manualUploadRetry, discardFailedEntryAndReconnect]);
975
1159
  const connectionHealthContextValue = useMemo(() => ({
976
1160
  health: connectionHealth
977
1161
  }), [connectionHealth]);
@@ -994,20 +1178,16 @@ function PowerSyncProvider({
994
1178
  pendingMutations,
995
1179
  pendingCount: pendingMutations.length,
996
1180
  discardPendingMutation,
997
- discardAllPendingMutations,
998
1181
  addPendingMutation,
999
1182
  removePendingMutation
1000
- }), [pendingMutations, discardPendingMutation, discardAllPendingMutations, addPendingMutation, removePendingMutation]);
1183
+ }), [pendingMutations, discardPendingMutation, addPendingMutation, removePendingMutation]);
1001
1184
  const failedTransactionsValue = useMemo(() => ({
1002
1185
  failedTransactions,
1003
1186
  hasUploadErrors: failedTransactions.length > 0,
1004
- permanentErrorCount: failedTransactions.filter((f_2) => f_2.isPermanent).length,
1187
+ permanentErrorCount: failedTransactions.filter((f_1) => f_1.isPermanent).length,
1005
1188
  clearFailure,
1006
- clearAllFailures,
1007
- pauseAutoRetry,
1008
- resumeAutoRetry,
1009
1189
  retryFailure
1010
- }), [failedTransactions, clearFailure, clearAllFailures, pauseAutoRetry, resumeAutoRetry, retryFailure]);
1190
+ }), [failedTransactions, clearFailure, retryFailure]);
1011
1191
  const completedTransactionsValue = useMemo(() => ({
1012
1192
  completedTransactions,
1013
1193
  clearCompletedHistory,
@@ -1021,17 +1201,18 @@ function PowerSyncProvider({
1021
1201
  isAutoOffline,
1022
1202
  networkReachable,
1023
1203
  setSyncMode,
1024
- setForceNextUpload
1025
- }), [syncModeState.mode, isAutoOffline, networkReachable, setSyncMode, setForceNextUpload]);
1204
+ setForceNextUpload,
1205
+ // Upload retry state
1206
+ isWaitingForUploadRetry: uploadRetryState.isWaitingForRetry,
1207
+ nextUploadRetryAt: uploadRetryState.nextRetryAt,
1208
+ maxUploadRetriesReached: uploadRetryState.maxRetriesReached,
1209
+ uploadRetryCount: uploadRetryState.retryCount,
1210
+ manualUploadRetry,
1211
+ discardFailedEntryAndReconnect
1212
+ }), [syncModeState.mode, isAutoOffline, networkReachable, setSyncMode, setForceNextUpload, uploadRetryState, manualUploadRetry, discardFailedEntryAndReconnect]);
1026
1213
  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 }) }) }) }) }) }) }) }) }) }) });
1027
1214
  }
1028
1215
 
1029
- // src/provider/OfflineDataProvider.tsx
1030
- import { c as _c } from "react/compiler-runtime";
1031
- import { useEffect as useEffect3, useRef as useRef3, useState as useState2 } from "react";
1032
- import { View, Text, StyleSheet, Pressable } from "react-native";
1033
- import { DataLayerProvider } from "@pol-studios/db";
1034
-
1035
1216
  // src/provider/ProviderBridge.tsx
1036
1217
  import { useEffect as useEffect2, useRef as useRef2 } from "react";
1037
1218
  import { PowerSyncContext as PowerSyncContext2 } from "@powersync/react-native";
@@ -1143,570 +1324,11 @@ function ProviderBridge({
1143
1324
  return /* @__PURE__ */ jsx2(Fragment, { children: content });
1144
1325
  }
1145
1326
 
1146
- // src/provider/OfflineDataProvider.tsx
1147
- import { Fragment as Fragment2, jsx as jsx3, jsxs } from "react/jsx-runtime";
1148
- var defaultLogger = {
1149
- debug: (...args) => console.debug("[OfflineData]", ...args),
1150
- info: (...args) => console.info("[OfflineData]", ...args),
1151
- warn: (...args) => console.warn("[OfflineData]", ...args),
1152
- error: (...args) => console.error("[OfflineData]", ...args)
1153
- };
1154
- var errorStyles = StyleSheet.create({
1155
- container: {
1156
- flex: 1,
1157
- justifyContent: "center",
1158
- alignItems: "center",
1159
- backgroundColor: "#f5f5f5",
1160
- padding: 20
1161
- },
1162
- content: {
1163
- backgroundColor: "white",
1164
- borderRadius: 12,
1165
- padding: 24,
1166
- maxWidth: 400,
1167
- width: "100%",
1168
- shadowColor: "#000",
1169
- shadowOffset: {
1170
- width: 0,
1171
- height: 2
1172
- },
1173
- shadowOpacity: 0.1,
1174
- shadowRadius: 8,
1175
- elevation: 4
1176
- },
1177
- title: {
1178
- fontSize: 20,
1179
- fontWeight: "600",
1180
- color: "#1a1a1a",
1181
- marginBottom: 12,
1182
- textAlign: "center"
1183
- },
1184
- message: {
1185
- fontSize: 14,
1186
- color: "#666",
1187
- marginBottom: 16,
1188
- textAlign: "center",
1189
- lineHeight: 20
1190
- },
1191
- errorDetail: {
1192
- fontSize: 12,
1193
- color: "#999",
1194
- marginBottom: 20,
1195
- textAlign: "center",
1196
- fontFamily: "monospace"
1197
- },
1198
- retryButton: {
1199
- backgroundColor: "#007AFF",
1200
- borderRadius: 8,
1201
- paddingVertical: 12,
1202
- paddingHorizontal: 24,
1203
- alignItems: "center"
1204
- },
1205
- retryButtonText: {
1206
- color: "white",
1207
- fontSize: 16,
1208
- fontWeight: "600"
1209
- }
1210
- });
1211
- function DefaultErrorRecoveryUI(t0) {
1212
- const $ = _c(10);
1213
- const {
1214
- error,
1215
- onRetry
1216
- } = t0;
1217
- let t1;
1218
- let t2;
1219
- if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1220
- t1 = /* @__PURE__ */ jsx3(Text, { style: errorStyles.title, children: "Database Error" });
1221
- t2 = /* @__PURE__ */ jsx3(Text, { style: errorStyles.message, children: "The local database encountered an error. This can happen if the app was interrupted during startup." });
1222
- $[0] = t1;
1223
- $[1] = t2;
1224
- } else {
1225
- t1 = $[0];
1226
- t2 = $[1];
1227
- }
1228
- let t3;
1229
- if ($[2] !== error.message) {
1230
- t3 = /* @__PURE__ */ jsx3(Text, { style: errorStyles.errorDetail, children: error.message });
1231
- $[2] = error.message;
1232
- $[3] = t3;
1233
- } else {
1234
- t3 = $[3];
1235
- }
1236
- let t4;
1237
- if ($[4] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1238
- t4 = /* @__PURE__ */ jsx3(Text, { style: errorStyles.retryButtonText, children: "Retry" });
1239
- $[4] = t4;
1240
- } else {
1241
- t4 = $[4];
1242
- }
1243
- let t5;
1244
- if ($[5] !== onRetry) {
1245
- t5 = /* @__PURE__ */ jsx3(Pressable, { style: errorStyles.retryButton, onPress: onRetry, children: t4 });
1246
- $[5] = onRetry;
1247
- $[6] = t5;
1248
- } else {
1249
- t5 = $[6];
1250
- }
1251
- let t6;
1252
- if ($[7] !== t3 || $[8] !== t5) {
1253
- t6 = /* @__PURE__ */ jsx3(View, { style: errorStyles.container, children: /* @__PURE__ */ jsxs(View, { style: errorStyles.content, children: [
1254
- t1,
1255
- t2,
1256
- t3,
1257
- t5
1258
- ] }) });
1259
- $[7] = t3;
1260
- $[8] = t5;
1261
- $[9] = t6;
1262
- } else {
1263
- t6 = $[9];
1264
- }
1265
- return t6;
1266
- }
1267
- function OfflineDataProvider(t0) {
1268
- const $ = _c(103);
1269
- const {
1270
- config,
1271
- children,
1272
- dataLayer,
1273
- backgroundSync,
1274
- skipConflictProvider: t1,
1275
- skipStorageQueueProvider: t2,
1276
- storageBackend,
1277
- renderInitError,
1278
- renderError,
1279
- onReady,
1280
- onError,
1281
- onSyncStatusChange,
1282
- onBackgroundSyncSystemReady: onBackgroundSyncSystemReadyProp
1283
- } = t0;
1284
- const skipConflictProvider = t1 === void 0 ? false : t1;
1285
- const skipStorageQueueProvider = t2 === void 0 ? false : t2;
1286
- const {
1287
- schema,
1288
- supabaseClient,
1289
- queryClient,
1290
- powerSyncUrl,
1291
- dbFilename: t3,
1292
- attachments,
1293
- platform: customPlatform,
1294
- connector: connectorConfig,
1295
- sync: syncConfig
1296
- } = config;
1297
- const dbFilename = t3 === void 0 ? "powersync.db" : t3;
1298
- const [initError, setInitError] = useState2(null);
1299
- const [retryKey, setRetryKey] = useState2(0);
1300
- const [powerSyncInstance, setPowerSyncInstance] = useState2(null);
1301
- const [powerSyncSyncStatus, setPowerSyncSyncStatus] = useState2(void 0);
1302
- const addPendingMutationRef = useRef3(null);
1303
- const removePendingMutationRef = useRef3(null);
1304
- const backgroundSyncSystemRef = useRef3(null);
1305
- let t4;
1306
- if ($[0] !== customPlatform) {
1307
- t4 = customPlatform ?? createNativePlatformAdapter(defaultLogger);
1308
- $[0] = customPlatform;
1309
- $[1] = t4;
1310
- } else {
1311
- t4 = $[1];
1312
- }
1313
- const platform = t4;
1314
- let t10;
1315
- let t5;
1316
- let t6;
1317
- let t7;
1318
- let t8;
1319
- let t9;
1320
- if ($[2] !== platform.logger) {
1321
- t5 = async () => {
1322
- platform.logger.warn("Sync not available: Use useSyncControl from PowerSync context");
1323
- };
1324
- t6 = async () => {
1325
- platform.logger.warn("Live sync not available: Use useSyncControl from PowerSync context");
1326
- };
1327
- t7 = () => {
1328
- platform.logger.warn("Live sync not available: Use useSyncControl from PowerSync context");
1329
- };
1330
- t8 = async () => {
1331
- platform.logger.warn("Scope control not available: Use useSyncControl from PowerSync context");
1332
- };
1333
- t9 = async () => {
1334
- platform.logger.warn("Retry not available: Use useSyncControl from PowerSync context");
1335
- };
1336
- t10 = () => {
1337
- platform.logger.warn("Clear failed uploads not available: Use useSyncControl from PowerSync context");
1338
- };
1339
- $[2] = platform.logger;
1340
- $[3] = t10;
1341
- $[4] = t5;
1342
- $[5] = t6;
1343
- $[6] = t7;
1344
- $[7] = t8;
1345
- $[8] = t9;
1346
- } else {
1347
- t10 = $[3];
1348
- t5 = $[4];
1349
- t6 = $[5];
1350
- t7 = $[6];
1351
- t8 = $[7];
1352
- t9 = $[8];
1353
- }
1354
- let t11;
1355
- if ($[9] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1356
- t11 = [];
1357
- $[9] = t11;
1358
- } else {
1359
- t11 = $[9];
1360
- }
1361
- let t12;
1362
- let t13;
1363
- if ($[10] !== platform.logger) {
1364
- t12 = () => {
1365
- platform.logger.warn("Pause auto-retry not available: Use useSyncControl from PowerSync context");
1366
- };
1367
- t13 = () => {
1368
- platform.logger.warn("Resume auto-retry not available: Use useSyncControl from PowerSync context");
1369
- };
1370
- $[10] = platform.logger;
1371
- $[11] = t12;
1372
- $[12] = t13;
1373
- } else {
1374
- t12 = $[11];
1375
- t13 = $[12];
1376
- }
1377
- let t14;
1378
- let t15;
1379
- if ($[13] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
1380
- t14 = (entry) => {
1381
- if (addPendingMutationRef.current) {
1382
- addPendingMutationRef.current(entry);
1383
- }
1384
- };
1385
- t15 = (id) => {
1386
- if (removePendingMutationRef.current) {
1387
- removePendingMutationRef.current(id);
1388
- }
1389
- };
1390
- $[13] = t14;
1391
- $[14] = t15;
1392
- } else {
1393
- t14 = $[13];
1394
- t15 = $[14];
1395
- }
1396
- let t16;
1397
- if ($[15] !== t10 || $[16] !== t12 || $[17] !== t13 || $[18] !== t5 || $[19] !== t6 || $[20] !== t7 || $[21] !== t8 || $[22] !== t9) {
1398
- t16 = {
1399
- triggerSync: t5,
1400
- startLiveSync: t6,
1401
- stopLiveSync: t7,
1402
- setScope: t8,
1403
- retryFailedUploads: t9,
1404
- clearFailedUploads: t10,
1405
- failedUploads: t11,
1406
- pauseAutoRetry: t12,
1407
- resumeAutoRetry: t13,
1408
- isAutoRetryPaused: false,
1409
- addPendingMutation: t14,
1410
- removePendingMutation: t15
1411
- };
1412
- $[15] = t10;
1413
- $[16] = t12;
1414
- $[17] = t13;
1415
- $[18] = t5;
1416
- $[19] = t6;
1417
- $[20] = t7;
1418
- $[21] = t8;
1419
- $[22] = t9;
1420
- $[23] = t16;
1421
- } else {
1422
- t16 = $[23];
1423
- }
1424
- const syncControl = t16;
1425
- let t17;
1426
- bb0: {
1427
- if (!attachments) {
1428
- t17 = void 0;
1429
- break bb0;
1430
- }
1431
- let t182;
1432
- if ($[24] !== attachments.bucket || $[25] !== storageBackend || $[26] !== supabaseClient) {
1433
- t182 = supabaseClient ? createSupabaseUploadHandler(supabaseClient, {
1434
- defaultBucket: attachments.bucket,
1435
- resolver: storageBackend?.resolveBucket?.bind(storageBackend)
1436
- }) : void 0;
1437
- $[24] = attachments.bucket;
1438
- $[25] = storageBackend;
1439
- $[26] = supabaseClient;
1440
- $[27] = t182;
1441
- } else {
1442
- t182 = $[27];
1443
- }
1444
- const nativeUploadHandler = t182;
1445
- const t192 = storageBackend;
1446
- let t202;
1447
- if ($[28] !== attachments.bucket || $[29] !== attachments.compression || $[30] !== attachments.download || $[31] !== attachments.maxCacheBytes || $[32] !== attachments.onUploadComplete || $[33] !== attachments.onUploadFailed || $[34] !== attachments.skipDownload || $[35] !== attachments.watchIds || $[36] !== nativeUploadHandler || $[37] !== t192) {
1448
- t202 = {
1449
- bucket: attachments.bucket,
1450
- watchIds: attachments.watchIds,
1451
- skipDownload: attachments.skipDownload,
1452
- onUploadComplete: attachments.onUploadComplete,
1453
- onUploadFailed: attachments.onUploadFailed,
1454
- maxCacheBytes: attachments.maxCacheBytes,
1455
- compression: attachments.compression,
1456
- download: attachments.download,
1457
- remoteStorage: t192,
1458
- uploadHandler: nativeUploadHandler
1459
- };
1460
- $[28] = attachments.bucket;
1461
- $[29] = attachments.compression;
1462
- $[30] = attachments.download;
1463
- $[31] = attachments.maxCacheBytes;
1464
- $[32] = attachments.onUploadComplete;
1465
- $[33] = attachments.onUploadFailed;
1466
- $[34] = attachments.skipDownload;
1467
- $[35] = attachments.watchIds;
1468
- $[36] = nativeUploadHandler;
1469
- $[37] = t192;
1470
- $[38] = t202;
1471
- } else {
1472
- t202 = $[38];
1473
- }
1474
- t17 = t202;
1475
- }
1476
- const attachmentConfig = t17;
1477
- const t18 = powerSyncUrl ?? "";
1478
- const t19 = syncConfig?.autoConnect ?? true;
1479
- const t20 = syncConfig?.enableHealthMonitoring ?? true;
1480
- const t21 = syncConfig?.enableMetrics ?? true;
1481
- let t22;
1482
- if ($[39] !== t19 || $[40] !== t20 || $[41] !== t21) {
1483
- t22 = {
1484
- autoConnect: t19,
1485
- enableHealthMonitoring: t20,
1486
- enableMetrics: t21
1487
- };
1488
- $[39] = t19;
1489
- $[40] = t20;
1490
- $[41] = t21;
1491
- $[42] = t22;
1492
- } else {
1493
- t22 = $[42];
1494
- }
1495
- let t23;
1496
- if ($[43] !== attachmentConfig || $[44] !== connectorConfig || $[45] !== dbFilename || $[46] !== platform || $[47] !== queryClient || $[48] !== schema || $[49] !== supabaseClient || $[50] !== t18 || $[51] !== t22) {
1497
- t23 = {
1498
- platform,
1499
- schema,
1500
- powerSyncUrl: t18,
1501
- supabaseClient,
1502
- queryClient,
1503
- dbFilename,
1504
- connector: connectorConfig,
1505
- attachments: attachmentConfig,
1506
- sync: t22
1507
- };
1508
- $[43] = attachmentConfig;
1509
- $[44] = connectorConfig;
1510
- $[45] = dbFilename;
1511
- $[46] = platform;
1512
- $[47] = queryClient;
1513
- $[48] = schema;
1514
- $[49] = supabaseClient;
1515
- $[50] = t18;
1516
- $[51] = t22;
1517
- $[52] = t23;
1518
- } else {
1519
- t23 = $[52];
1520
- }
1521
- const powerSyncConfig = t23;
1522
- let t24;
1523
- if ($[53] !== onError || $[54] !== platform.logger) {
1524
- t24 = (err) => {
1525
- platform.logger.error("PowerSync error:", err);
1526
- const errorMessage = err.message ?? "";
1527
- if (errorMessage.includes("not open") || errorMessage.includes("closed") || errorMessage.includes("failed to open") || errorMessage.includes("initialization failed")) {
1528
- setInitError(err);
1529
- }
1530
- onError?.(err);
1531
- };
1532
- $[53] = onError;
1533
- $[54] = platform.logger;
1534
- $[55] = t24;
1535
- } else {
1536
- t24 = $[55];
1537
- }
1538
- const handlePowerSyncError = t24;
1539
- let t25;
1540
- if ($[56] !== platform.logger) {
1541
- t25 = () => {
1542
- platform.logger.info("Retrying PowerSync initialization...");
1543
- setInitError(null);
1544
- setRetryKey(_temp);
1545
- };
1546
- $[56] = platform.logger;
1547
- $[57] = t25;
1548
- } else {
1549
- t25 = $[57];
1550
- }
1551
- const handleRetry = t25;
1552
- let t26;
1553
- if ($[58] !== backgroundSync?.callbacks || $[59] !== onBackgroundSyncSystemReadyProp || $[60] !== platform.logger) {
1554
- t26 = (system) => {
1555
- backgroundSyncSystemRef.current = system;
1556
- backgroundSync?.callbacks?.onSyncStart?.();
1557
- onBackgroundSyncSystemReadyProp?.(system);
1558
- platform.logger.info("[Background Sync] System ready");
1559
- };
1560
- $[58] = backgroundSync?.callbacks;
1561
- $[59] = onBackgroundSyncSystemReadyProp;
1562
- $[60] = platform.logger;
1563
- $[61] = t26;
1564
- } else {
1565
- t26 = $[61];
1566
- }
1567
- backgroundSync?.callbacks;
1568
- const handleBackgroundSyncSystemReady = t26;
1569
- let t27;
1570
- if ($[62] !== renderError || $[63] !== renderInitError) {
1571
- t27 = (error, retry) => {
1572
- const customRenderer = renderInitError ?? renderError;
1573
- if (customRenderer) {
1574
- return customRenderer(error, retry);
1575
- }
1576
- return /* @__PURE__ */ jsx3(DefaultErrorRecoveryUI, { error, onRetry: retry });
1577
- };
1578
- $[62] = renderError;
1579
- $[63] = renderInitError;
1580
- $[64] = t27;
1581
- } else {
1582
- t27 = $[64];
1583
- }
1584
- const errorFallback = t27;
1585
- let t28;
1586
- if ($[65] !== powerSyncSyncStatus || $[66] !== powerSyncUrl) {
1587
- t28 = !powerSyncUrl ? {
1588
- hasSynced: true,
1589
- connected: true,
1590
- connecting: false,
1591
- isOnline: true
1592
- } : powerSyncSyncStatus;
1593
- $[65] = powerSyncSyncStatus;
1594
- $[66] = powerSyncUrl;
1595
- $[67] = t28;
1596
- } else {
1597
- t28 = $[67];
1598
- }
1599
- const effectiveSyncStatus = t28;
1600
- let t29;
1601
- let t30;
1602
- if ($[68] !== effectiveSyncStatus || $[69] !== onSyncStatusChange) {
1603
- t29 = () => {
1604
- if (effectiveSyncStatus) {
1605
- onSyncStatusChange?.(effectiveSyncStatus);
1606
- }
1607
- };
1608
- t30 = [effectiveSyncStatus, onSyncStatusChange];
1609
- $[68] = effectiveSyncStatus;
1610
- $[69] = onSyncStatusChange;
1611
- $[70] = t29;
1612
- $[71] = t30;
1613
- } else {
1614
- t29 = $[70];
1615
- t30 = $[71];
1616
- }
1617
- useEffect3(t29, t30);
1618
- let t31;
1619
- let t32;
1620
- if ($[72] !== backgroundSync || $[73] !== children || $[74] !== dataLayer || $[75] !== effectiveSyncStatus || $[76] !== errorFallback || $[77] !== handleBackgroundSyncSystemReady || $[78] !== handlePowerSyncError || $[79] !== handleRetry || $[80] !== initError || $[81] !== onReady || $[82] !== platform.logger || $[83] !== powerSyncConfig || $[84] !== powerSyncInstance || $[85] !== powerSyncUrl || $[86] !== queryClient || $[87] !== renderError || $[88] !== renderInitError || $[89] !== retryKey || $[90] !== skipConflictProvider || $[91] !== skipStorageQueueProvider || $[92] !== supabaseClient || $[93] !== syncControl) {
1621
- t32 = /* @__PURE__ */ Symbol.for("react.early_return_sentinel");
1622
- bb1: {
1623
- const renderContent = () => {
1624
- if (!powerSyncUrl) {
1625
- return /* @__PURE__ */ jsx3(Fragment2, { children });
1626
- }
1627
- if (initError) {
1628
- const customRenderer_0 = renderInitError ?? renderError;
1629
- if (customRenderer_0) {
1630
- return /* @__PURE__ */ jsx3(Fragment2, { children: customRenderer_0(initError, handleRetry) });
1631
- }
1632
- return /* @__PURE__ */ jsx3(DefaultErrorRecoveryUI, { error: initError, onRetry: handleRetry });
1633
- }
1634
- return /* @__PURE__ */ jsx3(PowerSyncErrorBoundary, { fallback: errorFallback, onError: handlePowerSyncError, children: /* @__PURE__ */ jsx3(PowerSyncProvider, { config: powerSyncConfig, onReady: () => {
1635
- platform.logger.info("PowerSync initialized and ready");
1636
- setInitError(null);
1637
- onReady?.();
1638
- }, onError: handlePowerSyncError, children: /* @__PURE__ */ jsx3(ProviderBridge, { skipConflictProvider, skipStorageQueueProvider, backgroundSync, onBackgroundSyncSystemReady: handleBackgroundSyncSystemReady, onDbReady: (db, syncStatus) => {
1639
- setPowerSyncInstance(db);
1640
- setPowerSyncSyncStatus(syncStatus);
1641
- }, onSyncStatusChange: (syncStatus_0) => {
1642
- setPowerSyncSyncStatus(syncStatus_0);
1643
- }, onAddPendingMutationReady: (add) => {
1644
- addPendingMutationRef.current = add;
1645
- }, onRemovePendingMutationReady: (remove) => {
1646
- removePendingMutationRef.current = remove;
1647
- }, children }) }, retryKey) });
1648
- };
1649
- let t33;
1650
- if ($[96] !== dataLayer.config || $[97] !== effectiveSyncStatus || $[98] !== powerSyncInstance || $[99] !== queryClient || $[100] !== supabaseClient || $[101] !== syncControl) {
1651
- t33 = (content) => /* @__PURE__ */ jsx3(DataLayerProvider, { config: dataLayer.config, powerSyncInstance, supabaseClient, queryClient, powerSyncSyncStatus: effectiveSyncStatus, syncControl, children: content });
1652
- $[96] = dataLayer.config;
1653
- $[97] = effectiveSyncStatus;
1654
- $[98] = powerSyncInstance;
1655
- $[99] = queryClient;
1656
- $[100] = supabaseClient;
1657
- $[101] = syncControl;
1658
- $[102] = t33;
1659
- } else {
1660
- t33 = $[102];
1661
- }
1662
- const renderWithDataLayer = t33;
1663
- if (dataLayer && !dataLayer.skip) {
1664
- t32 = renderWithDataLayer(renderContent());
1665
- break bb1;
1666
- }
1667
- t31 = renderContent();
1668
- }
1669
- $[72] = backgroundSync;
1670
- $[73] = children;
1671
- $[74] = dataLayer;
1672
- $[75] = effectiveSyncStatus;
1673
- $[76] = errorFallback;
1674
- $[77] = handleBackgroundSyncSystemReady;
1675
- $[78] = handlePowerSyncError;
1676
- $[79] = handleRetry;
1677
- $[80] = initError;
1678
- $[81] = onReady;
1679
- $[82] = platform.logger;
1680
- $[83] = powerSyncConfig;
1681
- $[84] = powerSyncInstance;
1682
- $[85] = powerSyncUrl;
1683
- $[86] = queryClient;
1684
- $[87] = renderError;
1685
- $[88] = renderInitError;
1686
- $[89] = retryKey;
1687
- $[90] = skipConflictProvider;
1688
- $[91] = skipStorageQueueProvider;
1689
- $[92] = supabaseClient;
1690
- $[93] = syncControl;
1691
- $[94] = t31;
1692
- $[95] = t32;
1693
- } else {
1694
- t31 = $[94];
1695
- t32 = $[95];
1696
- }
1697
- if (t32 !== /* @__PURE__ */ Symbol.for("react.early_return_sentinel")) {
1698
- return t32;
1699
- }
1700
- return t31;
1701
- }
1702
- function _temp(prev) {
1703
- return prev + 1;
1704
- }
1705
-
1706
1327
  export {
1707
1328
  ConflictBus,
1329
+ UPLOAD_MAX_RETRIES,
1330
+ UPLOAD_BACKOFF_DELAYS,
1708
1331
  PowerSyncProvider,
1709
- ProviderBridge,
1710
- OfflineDataProvider
1332
+ ProviderBridge
1711
1333
  };
1712
- //# sourceMappingURL=chunk-VB737IVN.js.map
1334
+ //# sourceMappingURL=chunk-P4D6BQ4X.js.map