@pol-studios/powersync 1.0.4 → 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.
- package/dist/CacheSettingsManager-1exbOC6S.d.ts +261 -0
- package/dist/attachments/index.d.ts +65 -355
- package/dist/attachments/index.js +24 -6
- package/dist/{types-Cd7RhNqf.d.ts → background-sync-ChCXW-EV.d.ts} +53 -2
- package/dist/chunk-4C3RY5SU.js +204 -0
- package/dist/chunk-4C3RY5SU.js.map +1 -0
- package/dist/{chunk-3AYXHQ4W.js → chunk-53WH2JJV.js} +111 -47
- package/dist/chunk-53WH2JJV.js.map +1 -0
- package/dist/chunk-A4IBBWGO.js +377 -0
- package/dist/chunk-A4IBBWGO.js.map +1 -0
- package/dist/chunk-BREGB4WL.js +1768 -0
- package/dist/chunk-BREGB4WL.js.map +1 -0
- package/dist/{chunk-EJ23MXPQ.js → chunk-CGL33PL4.js} +3 -1
- package/dist/chunk-CGL33PL4.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/chunk-DHYUBVP7.js +131 -0
- package/dist/chunk-DHYUBVP7.js.map +1 -0
- package/dist/chunk-FV2HXEIY.js +124 -0
- package/dist/chunk-FV2HXEIY.js.map +1 -0
- package/dist/chunk-GKF7TOMT.js +1 -0
- package/dist/{chunk-OTJXIRWX.js → chunk-H772V6XQ.js} +304 -51
- package/dist/chunk-H772V6XQ.js.map +1 -0
- package/dist/{chunk-C2RSTGDC.js → chunk-HFOFLW5F.js} +525 -87
- package/dist/chunk-HFOFLW5F.js.map +1 -0
- package/dist/chunk-KGSFAE5B.js +1 -0
- package/dist/chunk-LNL64IJZ.js +1 -0
- package/dist/chunk-MKD2VCX3.js +32 -0
- package/dist/chunk-MKD2VCX3.js.map +1 -0
- package/dist/{chunk-7EMDVIZX.js → chunk-N75DEF5J.js} +19 -1
- package/dist/chunk-N75DEF5J.js.map +1 -0
- package/dist/chunk-P6WOZO7H.js +49 -0
- package/dist/chunk-P6WOZO7H.js.map +1 -0
- package/dist/chunk-TGBT5XBE.js +1 -0
- package/dist/chunk-TGBT5XBE.js.map +1 -0
- package/dist/chunk-UEYRTLKE.js +72 -0
- package/dist/chunk-UEYRTLKE.js.map +1 -0
- package/dist/chunk-WGHNIAF7.js +329 -0
- package/dist/chunk-WGHNIAF7.js.map +1 -0
- package/dist/chunk-WQ5MPAVC.js +449 -0
- package/dist/chunk-WQ5MPAVC.js.map +1 -0
- package/dist/{chunk-FPTDATY5.js → chunk-XQAJM2MW.js} +22 -11
- package/dist/chunk-XQAJM2MW.js.map +1 -0
- package/dist/chunk-YSTEESEG.js +676 -0
- package/dist/chunk-YSTEESEG.js.map +1 -0
- package/dist/chunk-ZEOKPWUC.js +1165 -0
- package/dist/chunk-ZEOKPWUC.js.map +1 -0
- package/dist/connector/index.d.ts +182 -2
- package/dist/connector/index.js +14 -3
- package/dist/core/index.d.ts +5 -3
- package/dist/core/index.js +5 -2
- package/dist/error/index.d.ts +54 -0
- package/dist/error/index.js +8 -0
- package/dist/error/index.js.map +1 -0
- package/dist/index.d.ts +237 -11
- package/dist/index.js +183 -27
- package/dist/index.native.d.ts +20 -9
- package/dist/index.native.js +183 -28
- package/dist/index.web.d.ts +20 -9
- package/dist/index.web.js +184 -28
- package/dist/maintenance/index.d.ts +118 -0
- package/dist/maintenance/index.js +17 -0
- package/dist/maintenance/index.js.map +1 -0
- package/dist/platform/index.d.ts +16 -1
- package/dist/platform/index.js +2 -0
- package/dist/platform/index.js.map +1 -1
- package/dist/platform/index.native.d.ts +2 -2
- package/dist/platform/index.native.js +2 -1
- package/dist/platform/index.web.d.ts +1 -1
- package/dist/platform/index.web.js +2 -1
- package/dist/pol-attachment-queue-C7YNXXhK.d.ts +676 -0
- package/dist/provider/index.d.ts +693 -12
- package/dist/provider/index.js +57 -12
- package/dist/storage/index.d.ts +6 -0
- package/dist/storage/index.js +28 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/index.native.d.ts +6 -0
- package/dist/storage/index.native.js +26 -0
- package/dist/storage/index.native.js.map +1 -0
- package/dist/storage/index.web.d.ts +6 -0
- package/dist/storage/index.web.js +26 -0
- package/dist/storage/index.web.js.map +1 -0
- package/dist/storage/upload/index.d.ts +55 -0
- package/dist/storage/upload/index.js +15 -0
- package/dist/storage/upload/index.js.map +1 -0
- package/dist/storage/upload/index.native.d.ts +57 -0
- package/dist/storage/upload/index.native.js +14 -0
- package/dist/storage/upload/index.native.js.map +1 -0
- package/dist/storage/upload/index.web.d.ts +5 -0
- package/dist/storage/upload/index.web.js +14 -0
- package/dist/storage/upload/index.web.js.map +1 -0
- package/dist/{index-Cb-NI0Ct.d.ts → supabase-connector-qLm-WHkM.d.ts} +146 -10
- package/dist/sync/index.d.ts +288 -22
- package/dist/sync/index.js +23 -5
- package/dist/types-BVacP54t.d.ts +52 -0
- package/dist/types-Bgvx7-E8.d.ts +187 -0
- package/dist/{types-afHtE1U_.d.ts → types-CDqWh56B.d.ts} +2 -0
- package/package.json +72 -2
- package/dist/chunk-32OLICZO.js +0 -1
- package/dist/chunk-3AYXHQ4W.js.map +0 -1
- package/dist/chunk-7EMDVIZX.js.map +0 -1
- package/dist/chunk-7JQZBZ5N.js +0 -1
- package/dist/chunk-C2RSTGDC.js.map +0 -1
- package/dist/chunk-EJ23MXPQ.js.map +0 -1
- package/dist/chunk-FPTDATY5.js.map +0 -1
- package/dist/chunk-GMFDCVMZ.js +0 -1285
- package/dist/chunk-GMFDCVMZ.js.map +0 -1
- package/dist/chunk-OLHGI472.js +0 -1
- package/dist/chunk-OTJXIRWX.js.map +0 -1
- package/dist/chunk-V6LJ6MR2.js +0 -740
- package/dist/chunk-V6LJ6MR2.js.map +0 -1
- package/dist/chunk-VJCL2SWD.js +0 -1
- /package/dist/{chunk-32OLICZO.js.map → chunk-DGUM43GV.js.map} +0 -0
- /package/dist/{chunk-7JQZBZ5N.js.map → chunk-GKF7TOMT.js.map} +0 -0
- /package/dist/{chunk-OLHGI472.js.map → chunk-KGSFAE5B.js.map} +0 -0
- /package/dist/{chunk-VJCL2SWD.js.map → chunk-LNL64IJZ.js.map} +0 -0
package/dist/sync/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { b as SyncStatusTrackerOptions, P as PowerSyncRawStatus, U as Unsubscribe, M as MetricsCollectorOptions, d as SyncOperationData, H as HealthMonitorOptions, e as HealthCheckResult } from '../
|
|
2
|
-
export { c as SyncControlActions, f as SyncEvent, g as SyncEventListener, S as SyncScope, a as SyncStatusState } from '../
|
|
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-
|
|
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
5
|
|
|
6
6
|
/**
|
|
@@ -48,14 +48,19 @@ declare class SyncStatusTracker {
|
|
|
48
48
|
private _listeners;
|
|
49
49
|
private _syncModeListeners;
|
|
50
50
|
private _forceNextUpload;
|
|
51
|
+
private _networkReachable;
|
|
52
|
+
private _networkRestoreTimer;
|
|
53
|
+
private readonly _networkRestoreDelayMs;
|
|
54
|
+
private _persistDebounceTimer;
|
|
51
55
|
private _lastProgress;
|
|
52
56
|
private _failedTransactions;
|
|
53
57
|
private readonly _maxStoredFailures;
|
|
54
58
|
private readonly _failureTTLMs;
|
|
55
59
|
private _failureListeners;
|
|
56
60
|
private _completedTransactions;
|
|
57
|
-
private readonly _maxCompletedHistory;
|
|
58
61
|
private _completedListeners;
|
|
62
|
+
private _lastNotificationTime;
|
|
63
|
+
private _isAutoOffline;
|
|
59
64
|
constructor(storage: AsyncStorageAdapter, logger: LoggerAdapter, options?: SyncStatusTrackerOptions);
|
|
60
65
|
/**
|
|
61
66
|
* Initialize the tracker by loading persisted state.
|
|
@@ -75,12 +80,7 @@ declare class SyncStatusTracker {
|
|
|
75
80
|
*/
|
|
76
81
|
getSyncMode(): SyncMode;
|
|
77
82
|
/**
|
|
78
|
-
*
|
|
79
|
-
* @deprecated Use getSyncMode() instead
|
|
80
|
-
*/
|
|
81
|
-
isPaused(): boolean;
|
|
82
|
-
/**
|
|
83
|
-
* Check if uploads are allowed based on current sync mode.
|
|
83
|
+
* Check if uploads are allowed based on current sync mode and network reachability.
|
|
84
84
|
*/
|
|
85
85
|
canUpload(): boolean;
|
|
86
86
|
/**
|
|
@@ -97,12 +97,22 @@ declare class SyncStatusTracker {
|
|
|
97
97
|
*/
|
|
98
98
|
clearForceNextUpload(): void;
|
|
99
99
|
/**
|
|
100
|
-
* Check if upload should proceed, considering force flag.
|
|
100
|
+
* Check if upload should proceed, considering force flag and network reachability.
|
|
101
101
|
* NOTE: Does NOT auto-reset the flag - caller must use clearForceNextUpload()
|
|
102
102
|
* after all uploads are complete. This prevents race conditions when
|
|
103
103
|
* PowerSync calls uploadData() multiple times for multiple transactions.
|
|
104
104
|
*/
|
|
105
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;
|
|
106
116
|
/**
|
|
107
117
|
* Get pending mutations.
|
|
108
118
|
*/
|
|
@@ -128,10 +138,15 @@ declare class SyncStatusTracker {
|
|
|
128
138
|
*/
|
|
129
139
|
setSyncMode(mode: SyncMode): Promise<void>;
|
|
130
140
|
/**
|
|
131
|
-
*
|
|
132
|
-
*
|
|
141
|
+
* Get whether offline mode was set automatically (network loss) vs manually.
|
|
142
|
+
* Used to determine if sync should auto-resume when network returns.
|
|
133
143
|
*/
|
|
134
|
-
|
|
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>;
|
|
135
150
|
/**
|
|
136
151
|
* Subscribe to status changes.
|
|
137
152
|
* @returns Unsubscribe function
|
|
@@ -142,18 +157,17 @@ declare class SyncStatusTracker {
|
|
|
142
157
|
* @returns Unsubscribe function
|
|
143
158
|
*/
|
|
144
159
|
onSyncModeChange(listener: (mode: SyncMode) => void): Unsubscribe;
|
|
145
|
-
/**
|
|
146
|
-
* Subscribe to paused state changes.
|
|
147
|
-
* @deprecated Use onSyncModeChange() instead
|
|
148
|
-
* @returns Unsubscribe function
|
|
149
|
-
*/
|
|
150
|
-
onPausedChange(listener: (isPaused: boolean) => void): Unsubscribe;
|
|
151
160
|
/**
|
|
152
161
|
* Record a transaction failure.
|
|
153
162
|
* If a failure for the same entries already exists, updates the retry count.
|
|
154
163
|
* Otherwise, creates a new failure record.
|
|
164
|
+
*
|
|
165
|
+
* @param preserveMetadata - Optional. If provided, preserves retryCount and firstFailedAt from a previous failure.
|
|
155
166
|
*/
|
|
156
|
-
recordTransactionFailure(entries: CrudEntry[], error: SyncError, isPermanent: boolean, affectedEntityIds: string[], affectedTables: string[]
|
|
167
|
+
recordTransactionFailure(entries: CrudEntry[], error: SyncError, isPermanent: boolean, affectedEntityIds: string[], affectedTables: string[], preserveMetadata?: {
|
|
168
|
+
retryCount: number;
|
|
169
|
+
firstFailedAt: Date;
|
|
170
|
+
}): void;
|
|
157
171
|
/**
|
|
158
172
|
* Clear a specific failure by ID.
|
|
159
173
|
*/
|
|
@@ -162,6 +176,17 @@ declare class SyncStatusTracker {
|
|
|
162
176
|
* Clear all failures.
|
|
163
177
|
*/
|
|
164
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;
|
|
165
190
|
/**
|
|
166
191
|
* Get failures affecting a specific entity.
|
|
167
192
|
*/
|
|
@@ -200,15 +225,63 @@ declare class SyncStatusTracker {
|
|
|
200
225
|
* Clear completed transaction history.
|
|
201
226
|
*/
|
|
202
227
|
clearCompletedHistory(): void;
|
|
228
|
+
/**
|
|
229
|
+
* Clear a specific completed transaction by ID.
|
|
230
|
+
*/
|
|
231
|
+
clearCompletedItem(completedId: string): void;
|
|
203
232
|
/**
|
|
204
233
|
* Subscribe to completed transaction changes.
|
|
205
234
|
* @returns Unsubscribe function
|
|
206
235
|
*/
|
|
207
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;
|
|
208
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
|
+
*/
|
|
209
270
|
private _notifyListeners;
|
|
210
271
|
private _notifyFailureListeners;
|
|
211
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;
|
|
212
285
|
}
|
|
213
286
|
|
|
214
287
|
/**
|
|
@@ -360,6 +433,7 @@ declare class HealthMonitor {
|
|
|
360
433
|
private _listeners;
|
|
361
434
|
private _running;
|
|
362
435
|
private _paused;
|
|
436
|
+
private _pendingTimers;
|
|
363
437
|
constructor(logger: LoggerAdapter, options?: HealthMonitorOptions);
|
|
364
438
|
/**
|
|
365
439
|
* Set the database instance to monitor.
|
|
@@ -418,4 +492,196 @@ declare class HealthMonitor {
|
|
|
418
492
|
private _withTimeout;
|
|
419
493
|
}
|
|
420
494
|
|
|
421
|
-
|
|
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 };
|
package/dist/sync/index.js
CHANGED
|
@@ -1,14 +1,32 @@
|
|
|
1
|
-
import
|
|
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-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
15
|
+
} from "../chunk-H772V6XQ.js";
|
|
16
|
+
import "../chunk-CGL33PL4.js";
|
|
17
|
+
import "../chunk-XQAJM2MW.js";
|
|
18
|
+
import "../chunk-DGUM43GV.js";
|
|
9
19
|
export {
|
|
20
|
+
DeadLetterQueue,
|
|
10
21
|
HealthMonitor,
|
|
11
22
|
MetricsCollector,
|
|
12
|
-
SyncStatusTracker
|
|
23
|
+
SyncStatusTracker,
|
|
24
|
+
createDeadLetterEntry,
|
|
25
|
+
defineBackgroundSyncTask,
|
|
26
|
+
generateDLQEntryId,
|
|
27
|
+
initializeBackgroundSync,
|
|
28
|
+
isBackgroundSyncRegistered,
|
|
29
|
+
registerBackgroundSync,
|
|
30
|
+
unregisterBackgroundSync
|
|
13
31
|
};
|
|
14
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
|