@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,8 +1,7 @@
1
- import { b as SyncStatusTrackerOptions, P as PowerSyncRawStatus, U as Unsubscribe, M as MetricsCollectorOptions, d as SyncOperationData, H as HealthMonitorOptions, e as HealthCheckResult } from '../types-Cd7RhNqf.js';
2
- export { c as SyncControlActions, f as SyncEvent, g as SyncEventListener, S as SyncScope, a as SyncStatusState } from '../types-Cd7RhNqf.js';
3
- import { a as SyncStatus, S as SyncMode, C as CrudEntry, f as SyncError, F as FailedTransaction, h as CompletedTransaction, e as SyncMetrics, A as AbstractPowerSyncDatabase, b as ConnectionHealth } from '../types-afHtE1U_.js';
1
+ import { b as SyncStatusTrackerOptions, P as PowerSyncRawStatus, U as Unsubscribe, M as MetricsCollectorOptions, d as SyncOperationData, H as HealthMonitorOptions, e as HealthCheckResult } from '../background-sync-ChCXW-EV.js';
2
+ export { B as BackgroundSyncOptions, h as BackgroundSyncSystem, c as SyncControlActions, f as SyncEvent, g as SyncEventListener, S as SyncScope, a as SyncStatusState, i as defineBackgroundSyncTask, j as initializeBackgroundSync, k as isBackgroundSyncRegistered, r as registerBackgroundSync, u as unregisterBackgroundSync } from '../background-sync-ChCXW-EV.js';
3
+ import { a as SyncStatus, S as SyncMode, C as CrudEntry, f as SyncError, F as FailedTransaction, h as CompletedTransaction, e as SyncMetrics, A as AbstractPowerSyncDatabase, b as ConnectionHealth } from '../types-CDqWh56B.js';
4
4
  import { AsyncStorageAdapter, LoggerAdapter } from '../platform/index.js';
5
- export { F as FailedUpload, a as FailedUploadStore, f as failedUploadStore } from '../failed-upload-store-C0cLxxPz.js';
6
5
 
7
6
  /**
8
7
  * Sync Status Tracker for @pol-studios/powersync
@@ -49,14 +48,19 @@ declare class SyncStatusTracker {
49
48
  private _listeners;
50
49
  private _syncModeListeners;
51
50
  private _forceNextUpload;
51
+ private _networkReachable;
52
+ private _networkRestoreTimer;
53
+ private readonly _networkRestoreDelayMs;
54
+ private _persistDebounceTimer;
52
55
  private _lastProgress;
53
56
  private _failedTransactions;
54
57
  private readonly _maxStoredFailures;
55
58
  private readonly _failureTTLMs;
56
59
  private _failureListeners;
57
60
  private _completedTransactions;
58
- private readonly _maxCompletedHistory;
59
61
  private _completedListeners;
62
+ private _lastNotificationTime;
63
+ private _isAutoOffline;
60
64
  constructor(storage: AsyncStorageAdapter, logger: LoggerAdapter, options?: SyncStatusTrackerOptions);
61
65
  /**
62
66
  * Initialize the tracker by loading persisted state.
@@ -76,12 +80,7 @@ declare class SyncStatusTracker {
76
80
  */
77
81
  getSyncMode(): SyncMode;
78
82
  /**
79
- * Get whether sync is paused (offline mode).
80
- * @deprecated Use getSyncMode() instead
81
- */
82
- isPaused(): boolean;
83
- /**
84
- * Check if uploads are allowed based on current sync mode.
83
+ * Check if uploads are allowed based on current sync mode and network reachability.
85
84
  */
86
85
  canUpload(): boolean;
87
86
  /**
@@ -98,12 +97,22 @@ declare class SyncStatusTracker {
98
97
  */
99
98
  clearForceNextUpload(): void;
100
99
  /**
101
- * Check if upload should proceed, considering force flag.
100
+ * Check if upload should proceed, considering force flag and network reachability.
102
101
  * NOTE: Does NOT auto-reset the flag - caller must use clearForceNextUpload()
103
102
  * after all uploads are complete. This prevents race conditions when
104
103
  * PowerSync calls uploadData() multiple times for multiple transactions.
105
104
  */
106
105
  shouldUpload(): boolean;
106
+ /**
107
+ * Set network reachability state.
108
+ * - When unreachable: Instantly blocks uploads (0ms)
109
+ * - When reachable: Delayed restore (1-2 seconds) to avoid flickering on brief disconnects
110
+ */
111
+ setNetworkReachable(reachable: boolean): void;
112
+ /**
113
+ * Get current network reachability state.
114
+ */
115
+ isNetworkReachable(): boolean;
107
116
  /**
108
117
  * Get pending mutations.
109
118
  */
@@ -129,10 +138,15 @@ declare class SyncStatusTracker {
129
138
  */
130
139
  setSyncMode(mode: SyncMode): Promise<void>;
131
140
  /**
132
- * Set paused state.
133
- * @deprecated Use setSyncMode() instead
141
+ * Get whether offline mode was set automatically (network loss) vs manually.
142
+ * Used to determine if sync should auto-resume when network returns.
134
143
  */
135
- setPaused(paused: boolean): Promise<void>;
144
+ getIsAutoOffline(): boolean;
145
+ /**
146
+ * Set the auto-offline flag and persist it.
147
+ * @param isAuto - true if offline was set automatically, false if user chose offline
148
+ */
149
+ setIsAutoOffline(isAuto: boolean): Promise<void>;
136
150
  /**
137
151
  * Subscribe to status changes.
138
152
  * @returns Unsubscribe function
@@ -143,18 +157,17 @@ declare class SyncStatusTracker {
143
157
  * @returns Unsubscribe function
144
158
  */
145
159
  onSyncModeChange(listener: (mode: SyncMode) => void): Unsubscribe;
146
- /**
147
- * Subscribe to paused state changes.
148
- * @deprecated Use onSyncModeChange() instead
149
- * @returns Unsubscribe function
150
- */
151
- onPausedChange(listener: (isPaused: boolean) => void): Unsubscribe;
152
160
  /**
153
161
  * Record a transaction failure.
154
162
  * If a failure for the same entries already exists, updates the retry count.
155
163
  * Otherwise, creates a new failure record.
164
+ *
165
+ * @param preserveMetadata - Optional. If provided, preserves retryCount and firstFailedAt from a previous failure.
156
166
  */
157
- recordTransactionFailure(entries: CrudEntry[], error: SyncError, isPermanent: boolean, affectedEntityIds: string[], affectedTables: string[]): void;
167
+ recordTransactionFailure(entries: CrudEntry[], error: SyncError, isPermanent: boolean, affectedEntityIds: string[], affectedTables: string[], preserveMetadata?: {
168
+ retryCount: number;
169
+ firstFailedAt: Date;
170
+ }): void;
158
171
  /**
159
172
  * Clear a specific failure by ID.
160
173
  */
@@ -163,6 +176,17 @@ declare class SyncStatusTracker {
163
176
  * Clear all failures.
164
177
  */
165
178
  clearAllFailures(): void;
179
+ /**
180
+ * Remove a failed transaction from tracking and return its entries.
181
+ * This is a "pop" operation - the failure is removed from the list.
182
+ *
183
+ * Note: The actual CRUD entries remain in PowerSync's ps_crud table
184
+ * until successfully uploaded. This just removes from our tracking.
185
+ *
186
+ * @param failureId - The failure ID to remove
187
+ * @returns The CrudEntry[] that were in the failure, or null if not found
188
+ */
189
+ takeFailureForRetry(failureId: string): CrudEntry[] | null;
166
190
  /**
167
191
  * Get failures affecting a specific entity.
168
192
  */
@@ -201,15 +225,63 @@ declare class SyncStatusTracker {
201
225
  * Clear completed transaction history.
202
226
  */
203
227
  clearCompletedHistory(): void;
228
+ /**
229
+ * Clear a specific completed transaction by ID.
230
+ */
231
+ clearCompletedItem(completedId: string): void;
204
232
  /**
205
233
  * Subscribe to completed transaction changes.
206
234
  * @returns Unsubscribe function
207
235
  */
208
236
  onCompletedChange(listener: (completed: CompletedTransaction[]) => void): Unsubscribe;
237
+ /**
238
+ * Get completed transactions that occurred AFTER the last notification time.
239
+ * This is used for displaying "X changes synced" notifications to avoid
240
+ * showing stale counts from historical completed transactions.
241
+ */
242
+ getNewCompletedTransactions(): CompletedTransaction[];
243
+ /**
244
+ * Mark notifications as seen by updating the last notification time.
245
+ * Call this when the notification is displayed or dismissed.
246
+ */
247
+ markNotificationsAsSeen(): void;
248
+ /**
249
+ * Get the timestamp of when notifications were last displayed/dismissed.
250
+ */
251
+ getLastNotificationTime(): number;
252
+ /**
253
+ * Schedule a debounced persist operation.
254
+ * This prevents race conditions from multiple rapid persist calls.
255
+ */
256
+ private _schedulePersist;
257
+ /**
258
+ * Persist completed and failed transactions to storage.
259
+ */
260
+ private _persistTransactions;
209
261
  private _hasStatusChanged;
262
+ /**
263
+ * Notify all listeners of status changes with throttling.
264
+ *
265
+ * Uses a "dirty" flag pattern: when throttled, we schedule a timer
266
+ * but get the CURRENT state when the timer fires, not the stale state
267
+ * from when the timer was scheduled. This ensures rapid state changes
268
+ * during the throttle window aren't lost.
269
+ */
210
270
  private _notifyListeners;
211
271
  private _notifyFailureListeners;
212
272
  private _notifyCompletedListeners;
273
+ /**
274
+ * Remap a CrudEntry from persisted JSON (handles toJSON() property remapping).
275
+ * PowerSync's CrudEntry.toJSON() remaps: opData→data, table→type, clientId→op_id, transactionId→tx_id
276
+ *
277
+ * @returns The remapped CrudEntry, or null if critical fields (table, id) are missing
278
+ */
279
+ private remapEntry;
280
+ /**
281
+ * Normalize CrudEntry array to plain objects to avoid CrudEntry.toJSON() remapping issues.
282
+ * PowerSync's CrudEntry.toJSON() remaps property names which breaks deserialization.
283
+ */
284
+ private normalizeEntries;
213
285
  }
214
286
 
215
287
  /**
@@ -361,6 +433,7 @@ declare class HealthMonitor {
361
433
  private _listeners;
362
434
  private _running;
363
435
  private _paused;
436
+ private _pendingTimers;
364
437
  constructor(logger: LoggerAdapter, options?: HealthMonitorOptions);
365
438
  /**
366
439
  * Set the database instance to monitor.
@@ -419,4 +492,196 @@ declare class HealthMonitor {
419
492
  private _withTimeout;
420
493
  }
421
494
 
422
- export { HealthCheckResult, HealthMonitor, HealthMonitorOptions, MetricsCollector, MetricsCollectorOptions, PowerSyncRawStatus, SyncOperationData, SyncStatusTracker, SyncStatusTrackerOptions, Unsubscribe };
495
+ /**
496
+ * Dead Letter Queue (DLQ) for PowerSync
497
+ *
498
+ * Handles mutations that have permanently failed and cannot be automatically retried.
499
+ * These are operations that need manual intervention (data fix, user action, etc.).
500
+ *
501
+ * Use cases:
502
+ * - RLS policy violations (user doesn't have permission)
503
+ * - Foreign key constraint violations (referenced record doesn't exist)
504
+ * - Validation errors (data doesn't match schema)
505
+ * - Max retry exceeded for transient errors
506
+ *
507
+ * The DLQ gives users a way to:
508
+ * 1. See mutations that will never succeed automatically
509
+ * 2. Understand why they failed
510
+ * 3. Manually fix the underlying data issue
511
+ * 4. Retry after fixing
512
+ * 5. Permanently discard if no longer needed
513
+ */
514
+
515
+ /**
516
+ * Reason why a mutation was moved to the dead letter queue
517
+ */
518
+ type DeadLetterReason = 'permanent_error' | 'max_retries_exceeded' | 'manual_move' | 'conflict_unresolved' | 'data_corruption';
519
+ /**
520
+ * A single entry in the dead letter queue
521
+ */
522
+ interface DeadLetterEntry {
523
+ /** Unique identifier for this DLQ entry */
524
+ id: string;
525
+ /** The CRUD entries that failed */
526
+ entries: CrudEntry[];
527
+ /** The error that caused the failure */
528
+ error: SyncError;
529
+ /** Why this was moved to the DLQ */
530
+ reason: DeadLetterReason;
531
+ /** When this was moved to the DLQ */
532
+ movedAt: Date;
533
+ /** Table names affected */
534
+ affectedTables: string[];
535
+ /** Entity IDs affected */
536
+ affectedEntityIds: string[];
537
+ /** Number of retry attempts before being moved to DLQ */
538
+ retryAttempts: number;
539
+ /** Optional user note (e.g., why they're keeping it) */
540
+ userNote?: string;
541
+ }
542
+ /**
543
+ * Options for creating a DeadLetterQueue
544
+ */
545
+ interface DeadLetterQueueOptions {
546
+ /** Async storage adapter for persistence */
547
+ storage: AsyncStorageAdapter;
548
+ /** Logger for debugging */
549
+ logger: LoggerAdapter;
550
+ /** Maximum entries to keep in DLQ */
551
+ maxEntries?: number;
552
+ /** Time-to-live for entries in ms (0 = never expire) */
553
+ entryTTLMs?: number;
554
+ /** Storage key for persistence */
555
+ storageKey?: string;
556
+ }
557
+ /**
558
+ * Listener for DLQ changes
559
+ */
560
+ type DeadLetterQueueListener = (entries: DeadLetterEntry[]) => void;
561
+ /**
562
+ * Dead Letter Queue for permanently failed mutations
563
+ *
564
+ * @example
565
+ * ```typescript
566
+ * const dlq = new DeadLetterQueue({
567
+ * storage: asyncStorage,
568
+ * logger: console,
569
+ * });
570
+ *
571
+ * await dlq.init();
572
+ *
573
+ * // Add a failed mutation
574
+ * await dlq.add({
575
+ * id: 'dlq_123',
576
+ * entries: failedCrudEntries,
577
+ * error: { type: 'validation', message: 'RLS policy violation', ... },
578
+ * reason: 'permanent_error',
579
+ * movedAt: new Date(),
580
+ * affectedTables: ['projects'],
581
+ * affectedEntityIds: ['project-456'],
582
+ * retryAttempts: 3,
583
+ * });
584
+ *
585
+ * // Subscribe to changes
586
+ * const unsubscribe = dlq.onQueueChange((entries) => {
587
+ * console.log('DLQ has', entries.length, 'entries');
588
+ * });
589
+ *
590
+ * // Retry an entry (removes from DLQ)
591
+ * const entry = await dlq.retry('dlq_123');
592
+ * // Now re-submit entry.entries to PowerSync
593
+ * ```
594
+ */
595
+ declare class DeadLetterQueue {
596
+ private readonly storage;
597
+ private readonly logger;
598
+ private readonly maxEntries;
599
+ private readonly entryTTLMs;
600
+ private readonly storageKey;
601
+ private entries;
602
+ private listeners;
603
+ private initialized;
604
+ constructor(options: DeadLetterQueueOptions);
605
+ /**
606
+ * Initialize the DLQ by loading persisted entries
607
+ */
608
+ init(): Promise<void>;
609
+ /**
610
+ * Dispose the DLQ (cleanup)
611
+ */
612
+ dispose(): void;
613
+ /**
614
+ * Add an entry to the dead letter queue
615
+ */
616
+ add(entry: DeadLetterEntry): Promise<void>;
617
+ /**
618
+ * Get all entries in the DLQ
619
+ */
620
+ getAll(): DeadLetterEntry[];
621
+ /**
622
+ * Get an entry by ID
623
+ */
624
+ get(id: string): DeadLetterEntry | null;
625
+ /**
626
+ * Get entries affecting a specific entity
627
+ */
628
+ getByEntityId(entityId: string): DeadLetterEntry[];
629
+ /**
630
+ * Get entries for a specific table
631
+ */
632
+ getByTable(tableName: string): DeadLetterEntry[];
633
+ /**
634
+ * Get entry count
635
+ */
636
+ get count(): number;
637
+ /**
638
+ * Check if DLQ has any entries
639
+ */
640
+ get hasEntries(): boolean;
641
+ /**
642
+ * Remove an entry from the DLQ (e.g., user discards it)
643
+ */
644
+ remove(id: string): Promise<DeadLetterEntry | null>;
645
+ /**
646
+ * Retry an entry - removes it from DLQ and returns it for resubmission
647
+ *
648
+ * @returns The entry that was removed (caller should resubmit to PowerSync)
649
+ */
650
+ retry(id: string): Promise<DeadLetterEntry | null>;
651
+ /**
652
+ * Clear all entries from the DLQ
653
+ */
654
+ clear(): Promise<void>;
655
+ /**
656
+ * Update user note on an entry
657
+ */
658
+ updateNote(id: string, note: string | undefined): Promise<void>;
659
+ /**
660
+ * Subscribe to DLQ changes
661
+ * @returns Unsubscribe function
662
+ */
663
+ onQueueChange(listener: DeadLetterQueueListener): () => void;
664
+ /**
665
+ * Get statistics about the DLQ
666
+ */
667
+ getStats(): {
668
+ totalEntries: number;
669
+ byReason: Record<DeadLetterReason, number>;
670
+ byTable: Record<string, number>;
671
+ oldestEntry: Date | null;
672
+ newestEntry: Date | null;
673
+ };
674
+ private persist;
675
+ private notifyListeners;
676
+ private cleanupExpired;
677
+ }
678
+ /**
679
+ * Generate a unique ID for a DLQ entry based on CRUD entries
680
+ */
681
+ declare function generateDLQEntryId(entries: CrudEntry[]): string;
682
+ /**
683
+ * Create a DeadLetterEntry from a failed transaction
684
+ */
685
+ declare function createDeadLetterEntry(entries: CrudEntry[], error: SyncError, reason: DeadLetterReason, retryAttempts?: number): DeadLetterEntry;
686
+
687
+ export { type DeadLetterEntry, DeadLetterQueue, type DeadLetterQueueListener, type DeadLetterQueueOptions, type DeadLetterReason, HealthCheckResult, HealthMonitor, HealthMonitorOptions, MetricsCollector, MetricsCollectorOptions, PowerSyncRawStatus, SyncOperationData, SyncStatusTracker, SyncStatusTrackerOptions, Unsubscribe, createDeadLetterEntry, generateDLQEntryId };
@@ -1,20 +1,32 @@
1
- import "../chunk-5FIMA26D.js";
1
+ import {
2
+ DeadLetterQueue,
3
+ createDeadLetterEntry,
4
+ defineBackgroundSyncTask,
5
+ generateDLQEntryId,
6
+ initializeBackgroundSync,
7
+ isBackgroundSyncRegistered,
8
+ registerBackgroundSync,
9
+ unregisterBackgroundSync
10
+ } from "../chunk-A4IBBWGO.js";
2
11
  import {
3
12
  HealthMonitor,
4
13
  MetricsCollector,
5
14
  SyncStatusTracker
6
- } from "../chunk-R4YFWQ3Q.js";
7
- import "../chunk-EJ23MXPQ.js";
8
- import {
9
- FailedUploadStore,
10
- failedUploadStore
11
- } from "../chunk-PAFBKNL3.js";
12
- import "../chunk-FPTDATY5.js";
15
+ } from "../chunk-H772V6XQ.js";
16
+ import "../chunk-CGL33PL4.js";
17
+ import "../chunk-XQAJM2MW.js";
18
+ import "../chunk-DGUM43GV.js";
13
19
  export {
14
- FailedUploadStore,
20
+ DeadLetterQueue,
15
21
  HealthMonitor,
16
22
  MetricsCollector,
17
23
  SyncStatusTracker,
18
- failedUploadStore
24
+ createDeadLetterEntry,
25
+ defineBackgroundSyncTask,
26
+ generateDLQEntryId,
27
+ initializeBackgroundSync,
28
+ isBackgroundSyncRegistered,
29
+ registerBackgroundSync,
30
+ unregisterBackgroundSync
19
31
  };
20
32
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,52 @@
1
+ import { a as BucketConfig } from './types-Bgvx7-E8.js';
2
+
3
+ /**
4
+ * Upload Handler Types for @pol-studios/powersync
5
+ *
6
+ * Defines types for platform-specific upload handlers.
7
+ */
8
+
9
+ /**
10
+ * Options for creating a SupabaseUploadHandler.
11
+ */
12
+ interface SupabaseUploadHandlerOptions {
13
+ /** Supabase client instance */
14
+ supabaseClient: any;
15
+ /** Bucket configuration for multi-bucket routing */
16
+ bucketConfig: BucketConfig;
17
+ }
18
+ /**
19
+ * Event handlers for upload progress tracking.
20
+ */
21
+ interface UploadEventHandlers {
22
+ /** Called with progress updates during upload */
23
+ onProgress?: (progress: {
24
+ loaded: number;
25
+ total: number;
26
+ }) => void;
27
+ /** Called when upload completes successfully */
28
+ onComplete?: () => void;
29
+ /** Called when upload fails */
30
+ onError?: (error: Error) => void;
31
+ }
32
+ /**
33
+ * Configuration for native upload notifications (Android).
34
+ */
35
+ interface UploadNotificationConfig {
36
+ /** Whether to show upload notifications */
37
+ enabled: boolean;
38
+ /** Whether to auto-clear notification on completion */
39
+ autoClear: boolean;
40
+ /** Title shown during upload progress */
41
+ onProgressTitle: string;
42
+ /** Title shown when upload completes */
43
+ onCompleteTitle: string;
44
+ /** Title shown when upload fails */
45
+ onErrorTitle: string;
46
+ }
47
+ /**
48
+ * Default notification configuration for Android uploads.
49
+ */
50
+ declare const DEFAULT_UPLOAD_NOTIFICATION: UploadNotificationConfig;
51
+
52
+ export { DEFAULT_UPLOAD_NOTIFICATION as D, type SupabaseUploadHandlerOptions as S, type UploadEventHandlers as U, type UploadNotificationConfig as a };
@@ -0,0 +1,187 @@
1
+ import { LoggerAdapter } from './platform/index.js';
2
+
3
+ /**
4
+ * Storage Types for @pol-studios/powersync
5
+ *
6
+ * Defines interfaces for pluggable storage adapters supporting
7
+ * different backend storage providers (Supabase, S3, etc.).
8
+ */
9
+ /**
10
+ * Function type for resolving storage bucket from a file path.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const resolver: BucketResolver = (path) => {
15
+ * if (path.startsWith('avatars/')) return 'user-avatars';
16
+ * if (path.startsWith('docs/')) return 'documents';
17
+ * return 'default-bucket';
18
+ * };
19
+ * ```
20
+ */
21
+ type BucketResolver = (storagePath: string) => string;
22
+ /**
23
+ * Configuration for bucket resolution.
24
+ * Supports multiple strategies: default bucket, prefix mapping, or custom resolver.
25
+ */
26
+ interface BucketConfig {
27
+ /** Default bucket when no other rule matches */
28
+ defaultBucket: string;
29
+ /**
30
+ * Map of path prefixes to bucket names.
31
+ * Checked in iteration order (use Map to preserve order).
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * const bucketMap = new Map([
36
+ * ['avatars/', 'user-avatars'],
37
+ * ['docs/', 'documents'],
38
+ * ]);
39
+ * ```
40
+ */
41
+ bucketMap?: Map<string, string>;
42
+ /**
43
+ * Custom resolver function (takes precedence over bucketMap).
44
+ * Return undefined to fall through to bucketMap/defaultBucket.
45
+ */
46
+ resolver?: (storagePath: string) => string | undefined;
47
+ }
48
+ /**
49
+ * Resolve bucket from a storage path using BucketConfig.
50
+ *
51
+ * Resolution order:
52
+ * 1. Custom resolver (if provided and returns a value)
53
+ * 2. bucketMap prefix matching (if provided)
54
+ * 3. defaultBucket
55
+ */
56
+ declare function resolveBucketFromConfig(config: BucketConfig, storagePath: string): string;
57
+ /**
58
+ * Interface for remote storage download adapters.
59
+ * Implement this to support non-Supabase storage backends.
60
+ */
61
+ interface RemoteStorageAdapter {
62
+ /**
63
+ * Download a file from remote storage to local path.
64
+ */
65
+ download(remotePath: string, localPath: string): Promise<void>;
66
+ /**
67
+ * Get a signed download URL for a remote file.
68
+ */
69
+ getDownloadUrl(remotePath: string): Promise<string>;
70
+ /**
71
+ * Check if a file exists in remote storage.
72
+ */
73
+ exists(remotePath: string): Promise<boolean>;
74
+ }
75
+ /**
76
+ * Options for upload operations.
77
+ */
78
+ interface UploadOptions {
79
+ contentType?: string;
80
+ onProgress?: (progress: {
81
+ loaded: number;
82
+ total: number;
83
+ }) => void;
84
+ }
85
+ /**
86
+ * Interface for attachment upload handlers.
87
+ * Implement this to support non-Supabase upload backends.
88
+ */
89
+ interface AttachmentUploadHandler {
90
+ /**
91
+ * Upload a file from local path to remote storage.
92
+ */
93
+ upload(localPath: string, remotePath: string, options?: UploadOptions): Promise<void>;
94
+ /**
95
+ * Get a signed upload URL (optional, for direct uploads).
96
+ */
97
+ getUploadUrl?(remotePath: string): Promise<string>;
98
+ }
99
+ /**
100
+ * Interface for platform-specific upload handlers.
101
+ * Used by SupabaseUploadHandler implementations.
102
+ *
103
+ * Note: This is named StorageUploadHandler to avoid conflicts with
104
+ * the UploadHandler interface in attachments/types.ts which has
105
+ * slightly different semantics.
106
+ */
107
+ interface StorageUploadHandler {
108
+ /**
109
+ * Upload a file to remote storage.
110
+ *
111
+ * @param storagePath - Remote path in storage bucket
112
+ * @param localFileUri - Local file URI (file:// on native, blob URL on web)
113
+ * @param mediaType - MIME type of the file
114
+ * @param signal - Optional AbortSignal for cancellation
115
+ */
116
+ uploadFile(storagePath: string, localFileUri: string, mediaType: string, signal?: AbortSignal): Promise<void>;
117
+ /**
118
+ * Resolve the storage bucket for a given path.
119
+ */
120
+ resolveBucket(storagePath: string): string;
121
+ }
122
+
123
+ /**
124
+ * Options for creating a SupabaseStorageAdapter.
125
+ */
126
+ interface SupabaseStorageAdapterOptions {
127
+ /** Supabase client instance */
128
+ client: any;
129
+ /** Bucket configuration for multi-bucket routing */
130
+ bucketConfig: BucketConfig;
131
+ /**
132
+ * Custom signed URL expiry in seconds.
133
+ * @default 60 (short-lived for security)
134
+ */
135
+ signedUrlExpiry?: number;
136
+ /**
137
+ * Optional logger for diagnostic messages.
138
+ * If not provided, falls back to console.warn for warnings.
139
+ */
140
+ logger?: LoggerAdapter;
141
+ }
142
+ /**
143
+ * Result of a download operation.
144
+ */
145
+ interface DownloadResult {
146
+ /** Local file path where the file was saved */
147
+ localPath: string;
148
+ /** MIME type of the downloaded file */
149
+ mimeType: string;
150
+ /** Size of the downloaded file in bytes */
151
+ size: number;
152
+ }
153
+ /**
154
+ * PowerSync StorageAdapter interface from @powersync/attachments.
155
+ * Re-declared here to avoid import dependency.
156
+ */
157
+ interface PowerSyncStorageAdapter {
158
+ /** Upload a file to remote storage */
159
+ uploadFile(filename: string, data: ArrayBuffer, options?: {
160
+ mediaType?: string;
161
+ }): Promise<void>;
162
+ /** Download a file from remote storage */
163
+ downloadFile(filePath: string): Promise<Blob>;
164
+ /** Write a file to local storage */
165
+ writeFile(fileURI: string, base64Data: string, options?: {
166
+ encoding?: 'utf8' | 'base64';
167
+ }): Promise<void>;
168
+ /** Read a file from local storage */
169
+ readFile(fileURI: string, options?: {
170
+ encoding?: 'utf8' | 'base64';
171
+ mediaType?: string;
172
+ }): Promise<ArrayBuffer>;
173
+ /** Delete a local file */
174
+ deleteFile(uri: string, options?: {
175
+ filename?: string;
176
+ }): Promise<void>;
177
+ /** Check if a local file exists */
178
+ fileExists(fileURI: string): Promise<boolean>;
179
+ /** Create a directory */
180
+ makeDir(uri: string): Promise<void>;
181
+ /** Copy a file */
182
+ copyFile(sourceUri: string, targetUri: string): Promise<void>;
183
+ /** Get the user storage directory */
184
+ getUserStorageDirectory(): string;
185
+ }
186
+
187
+ export { type AttachmentUploadHandler as A, type BucketResolver as B, type DownloadResult as D, type PowerSyncStorageAdapter as P, type RemoteStorageAdapter as R, type StorageUploadHandler as S, type UploadOptions as U, type BucketConfig as a, type SupabaseStorageAdapterOptions as b, resolveBucketFromConfig as r };
@@ -39,6 +39,8 @@ interface CrudEntry {
39
39
  opData?: Record<string, unknown>;
40
40
  /** Transaction ID for grouping operations */
41
41
  transactionId?: number;
42
+ /** When this mutation was created (for display purposes) */
43
+ createdAt?: Date;
42
44
  }
43
45
  /**
44
46
  * Download progress information during sync