@pol-studios/powersync 1.0.30 → 1.0.33

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 (116) hide show
  1. package/dist/{CacheSettingsManager-uz-kbnRH.d.ts → CacheSettingsManager-0H_7thHW.d.ts} +21 -3
  2. package/dist/attachments/index.d.ts +30 -30
  3. package/dist/attachments/index.js +13 -4
  4. package/dist/{background-sync-CVR3PkFi.d.ts → background-sync-BujnI3IR.d.ts} +1 -1
  5. package/dist/{chunk-RE5HWLCB.js → chunk-2RDWLXJW.js} +322 -103
  6. package/dist/chunk-2RDWLXJW.js.map +1 -0
  7. package/dist/{chunk-P4HZA6ZT.js → chunk-4665ZSE5.js} +2 -2
  8. package/dist/chunk-4665ZSE5.js.map +1 -0
  9. package/dist/{chunk-XOY2CJ67.js → chunk-4F5B5CZ7.js} +3 -3
  10. package/dist/chunk-5WRI5ZAA.js +31 -0
  11. package/dist/{chunk-BC2SRII2.js → chunk-65A3SYJZ.js} +14 -1
  12. package/dist/chunk-65A3SYJZ.js.map +1 -0
  13. package/dist/chunk-6SZ64KCZ.js +755 -0
  14. package/dist/chunk-6SZ64KCZ.js.map +1 -0
  15. package/dist/{chunk-C2ACBYBZ.js → chunk-74TBHWJ4.js} +10 -96
  16. package/dist/{chunk-C2ACBYBZ.js.map → chunk-74TBHWJ4.js.map} +1 -1
  17. package/dist/chunk-ANXWYQEJ.js +1 -0
  18. package/dist/chunk-ANXWYQEJ.js.map +1 -0
  19. package/dist/{chunk-CAB26E6F.js → chunk-C4J4MLER.js} +29 -24
  20. package/dist/chunk-C4J4MLER.js.map +1 -0
  21. package/dist/{chunk-C5ODS3XH.js → chunk-EOW7JK7Q.js} +9 -16
  22. package/dist/chunk-EOW7JK7Q.js.map +1 -0
  23. package/dist/chunk-HRAVPIAZ.js +220 -0
  24. package/dist/chunk-HRAVPIAZ.js.map +1 -0
  25. package/dist/{chunk-XAEII4ZX.js → chunk-NUGQOTEM.js} +32 -4
  26. package/dist/chunk-NUGQOTEM.js.map +1 -0
  27. package/dist/chunk-OGUFUZSY.js +5415 -0
  28. package/dist/chunk-OGUFUZSY.js.map +1 -0
  29. package/dist/{chunk-JCGOZVWL.js → chunk-P4D6BQ4X.js} +115 -576
  30. package/dist/chunk-P4D6BQ4X.js.map +1 -0
  31. package/dist/{chunk-CACKC6XG.js → chunk-PGEDE6IM.js} +136 -89
  32. package/dist/chunk-PGEDE6IM.js.map +1 -0
  33. package/dist/{chunk-A4IBBWGO.js → chunk-RALHHPTU.js} +1 -1
  34. package/dist/chunk-RIDSPLE5.js +42 -0
  35. package/dist/chunk-RIDSPLE5.js.map +1 -0
  36. package/dist/{chunk-Z6VOBGTU.js → chunk-UOMHWUHV.js} +2 -12
  37. package/dist/chunk-UOMHWUHV.js.map +1 -0
  38. package/dist/{chunk-QREWE3NR.js → chunk-YONQYTVH.js} +2 -2
  39. package/dist/chunk-ZAN22NGL.js +13 -0
  40. package/dist/chunk-ZAN22NGL.js.map +1 -0
  41. package/dist/config/index.d.ts +200 -0
  42. package/dist/config/index.js +23 -0
  43. package/dist/config/index.js.map +1 -0
  44. package/dist/connector/index.d.ts +23 -5
  45. package/dist/connector/index.js +4 -1
  46. package/dist/core/index.d.ts +2 -2
  47. package/dist/core/index.js +1 -0
  48. package/dist/error/index.js +1 -0
  49. package/dist/generator/index.js +2 -0
  50. package/dist/generator/index.js.map +1 -1
  51. package/dist/index.d.ts +19 -16
  52. package/dist/index.js +68 -36
  53. package/dist/index.native.d.ts +18 -14
  54. package/dist/index.native.js +73 -34
  55. package/dist/index.web.d.ts +17 -14
  56. package/dist/index.web.js +68 -36
  57. package/dist/maintenance/index.d.ts +2 -2
  58. package/dist/maintenance/index.js +3 -2
  59. package/dist/platform/index.d.ts +1 -1
  60. package/dist/platform/index.js +2 -0
  61. package/dist/platform/index.js.map +1 -1
  62. package/dist/platform/index.native.d.ts +1 -1
  63. package/dist/platform/index.native.js +1 -0
  64. package/dist/platform/index.web.d.ts +1 -1
  65. package/dist/platform/index.web.js +1 -0
  66. package/dist/pol-attachment-queue-DqBvLAEY.d.ts +255 -0
  67. package/dist/provider/index.d.ts +149 -114
  68. package/dist/provider/index.js +9 -14
  69. package/dist/provider/index.native.d.ts +108 -0
  70. package/dist/provider/index.native.js +121 -0
  71. package/dist/provider/index.native.js.map +1 -0
  72. package/dist/provider/index.web.d.ts +16 -0
  73. package/dist/provider/index.web.js +112 -0
  74. package/dist/provider/index.web.js.map +1 -0
  75. package/dist/react/index.d.ts +16 -65
  76. package/dist/react/index.js +2 -9
  77. package/dist/storage/index.d.ts +5 -4
  78. package/dist/storage/index.js +12 -9
  79. package/dist/storage/index.native.d.ts +5 -4
  80. package/dist/storage/index.native.js +8 -5
  81. package/dist/storage/index.web.d.ts +5 -4
  82. package/dist/storage/index.web.js +11 -8
  83. package/dist/storage/upload/index.d.ts +4 -3
  84. package/dist/storage/upload/index.js +4 -2
  85. package/dist/storage/upload/index.native.d.ts +4 -3
  86. package/dist/storage/upload/index.native.js +4 -2
  87. package/dist/storage/upload/index.web.d.ts +2 -1
  88. package/dist/storage/upload/index.web.js +4 -2
  89. package/dist/{supabase-connector-C4YpH_l3.d.ts → supabase-connector-HMxBA9Kg.d.ts} +2 -2
  90. package/dist/sync/index.d.ts +155 -20
  91. package/dist/sync/index.js +13 -3
  92. package/dist/{types-CyvBaAl8.d.ts → types-6QHGELuY.d.ts} +4 -1
  93. package/dist/{types-Dv1uf0LZ.d.ts → types-B9MptP7E.d.ts} +7 -10
  94. package/dist/types-BhAEsJj-.d.ts +330 -0
  95. package/dist/{types-D0WcHrq6.d.ts → types-CGMibJKD.d.ts} +8 -0
  96. package/dist/{types-CpM2_LhU.d.ts → types-DqJnP50o.d.ts} +6 -1
  97. package/dist/{pol-attachment-queue-BE2HU3Us.d.ts → types-JCEhw2Lf.d.ts} +139 -346
  98. package/package.json +18 -4
  99. package/dist/chunk-654ERHA7.js +0 -1
  100. package/dist/chunk-BC2SRII2.js.map +0 -1
  101. package/dist/chunk-C5ODS3XH.js.map +0 -1
  102. package/dist/chunk-CAB26E6F.js.map +0 -1
  103. package/dist/chunk-CACKC6XG.js.map +0 -1
  104. package/dist/chunk-FNYQFILT.js +0 -44
  105. package/dist/chunk-FNYQFILT.js.map +0 -1
  106. package/dist/chunk-JCGOZVWL.js.map +0 -1
  107. package/dist/chunk-P4HZA6ZT.js.map +0 -1
  108. package/dist/chunk-RBPWEOIV.js +0 -358
  109. package/dist/chunk-RBPWEOIV.js.map +0 -1
  110. package/dist/chunk-RE5HWLCB.js.map +0 -1
  111. package/dist/chunk-XAEII4ZX.js.map +0 -1
  112. package/dist/chunk-Z6VOBGTU.js.map +0 -1
  113. /package/dist/{chunk-XOY2CJ67.js.map → chunk-4F5B5CZ7.js.map} +0 -0
  114. /package/dist/{chunk-654ERHA7.js.map → chunk-5WRI5ZAA.js.map} +0 -0
  115. /package/dist/{chunk-A4IBBWGO.js.map → chunk-RALHHPTU.js.map} +0 -0
  116. /package/dist/{chunk-QREWE3NR.js.map → chunk-YONQYTVH.js.map} +0 -0
@@ -0,0 +1,255 @@
1
+ import { AbstractAttachmentQueue, AttachmentQueueOptions, AttachmentRecord } from '@powersync/attachments';
2
+ import { AbstractPowerSyncDatabase } from '@powersync/common';
3
+ import { PlatformAdapter } from './platform/index.js';
4
+ import { e as AttachmentStorageAdapter, c as AttachmentSourceConfig, h as UploadHandler, U as UploadConfig, i as DownloadConfig, a as PolAttachmentRecord, f as CompressionConfig, k as CacheConfig, t as UploadStatus, v as AttachmentSyncStats, d as AttachmentConfig } from './types-JCEhw2Lf.js';
5
+
6
+ /**
7
+ * POL Attachment Queue
8
+ *
9
+ * Extends the official @powersync/attachments AbstractAttachmentQueue with
10
+ * POL-specific features:
11
+ * - Reactive watchPaths callback for attachment path sources
12
+ * - Durable upload queue with exponential backoff retry
13
+ * - FAILED_PERMANENT state for unrecoverable upload errors
14
+ * - Image compression integration
15
+ * - Upload callbacks (onUploadComplete, onUploadFailed)
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const queue = new PolAttachmentQueue({
20
+ * powersync: db,
21
+ * storage: storageAdapter,
22
+ * source: {
23
+ * source: { type: 'supabase-bucket', bucket: 'project-assets' },
24
+ * watchPaths: (db, supabase, onUpdate) => {
25
+ * db.watch(
26
+ * // Filter in the query - only emit paths you want to download
27
+ * `SELECT storagePath FROM photos
28
+ * WHERE storagePath IS NOT NULL
29
+ * AND mediaType NOT LIKE 'video/%'`,
30
+ * [],
31
+ * { onResult: (r) => onUpdate(r.rows._array.map(row => row.storagePath)) }
32
+ * );
33
+ * },
34
+ * },
35
+ * });
36
+ *
37
+ * await queue.init();
38
+ * ```
39
+ */
40
+
41
+ /**
42
+ * Options for PolAttachmentQueue that extend the official AttachmentQueueOptions.
43
+ */
44
+ interface PolAttachmentQueueOptions extends AttachmentQueueOptions {
45
+ platform: PlatformAdapter;
46
+ remoteStorage: AttachmentStorageAdapter;
47
+ /** Attachment source configuration with reactive watchPaths callback */
48
+ source: AttachmentSourceConfig;
49
+ /**
50
+ * Supabase client for passing to watchPaths callback.
51
+ * Required when using watchPaths (new API).
52
+ */
53
+ supabaseClient?: unknown;
54
+ uploadHandler?: UploadHandler;
55
+ uploadConfig?: Partial<UploadConfig>;
56
+ /** Download configuration for concurrency tuning */
57
+ downloadConfig?: Partial<DownloadConfig>;
58
+ onUploadComplete?: (record: PolAttachmentRecord) => Promise<void>;
59
+ onUploadFailed?: (record: PolAttachmentRecord, error: Error) => void;
60
+ compression?: Partial<CompressionConfig>;
61
+ cache?: Partial<CacheConfig>;
62
+ }
63
+ /**
64
+ * POL Attachment Queue that extends the official AbstractAttachmentQueue.
65
+ */
66
+ declare class PolAttachmentQueue extends AbstractAttachmentQueue<PolAttachmentQueueOptions> {
67
+ private readonly platform;
68
+ private readonly polLogger;
69
+ private readonly source;
70
+ private readonly remoteStorage;
71
+ private readonly supabaseClient?;
72
+ private readonly uploadHandler?;
73
+ private readonly uploadConfig;
74
+ private readonly downloadConfig;
75
+ private readonly compressionConfig;
76
+ private readonly cacheConfig;
77
+ private _uploadState;
78
+ private _disposed;
79
+ private _initialized;
80
+ private _watchGeneration;
81
+ private _watchCleanup;
82
+ private _watchMutex;
83
+ private _networkListenerCleanup;
84
+ private _wasConnected;
85
+ private _cacheCapacityRetries;
86
+ private _progressCallbacks;
87
+ private _lastNotifyTime;
88
+ private _notifyTimer;
89
+ private _cachedStats;
90
+ private _cachedStatsTimestamp;
91
+ constructor(options: PolAttachmentQueueOptions);
92
+ watchUploads(): void;
93
+ /**
94
+ * Override parent's expireCache to disable count-based cache eviction.
95
+ *
96
+ * The parent implementation deletes SYNCED/ARCHIVED records beyond cacheLimit,
97
+ * which caused a bug where downloads would reset because:
98
+ * 1. expireCache deleted records beyond cacheLimit (default 100)
99
+ * 2. watchPaths still emitted those IDs
100
+ * 3. They got re-created as QUEUED_DOWNLOAD
101
+ * 4. Downloads restarted in an infinite loop
102
+ *
103
+ * Our implementation uses size-based cache limits only (via clearCache/cacheConfig.maxSize).
104
+ */
105
+ expireCache(): Promise<void>;
106
+ /**
107
+ * Override parent's watchDownloads to use concurrent downloads.
108
+ *
109
+ * The parent implementation downloads one file at a time.
110
+ * This override processes downloads in parallel batches for faster sync.
111
+ */
112
+ watchDownloads(): void;
113
+ /**
114
+ * Process pending downloads with concurrency control.
115
+ * Downloads multiple files in parallel based on downloadConfig.concurrency.
116
+ * Enforces cache size limits after each batch completes.
117
+ */
118
+ private _downloadRecordsConcurrent;
119
+ uploadAttachment(record: {
120
+ id: string;
121
+ }): Promise<boolean>;
122
+ watchAttachmentIds(): Promise<void>;
123
+ saveToQueue(record: Omit<AttachmentRecord, 'timestamp'>): Promise<AttachmentRecord>;
124
+ onAttachmentIdsChange(onUpdate: (ids: string[]) => void): void;
125
+ downloadRecord(record: AttachmentRecord): Promise<boolean>;
126
+ newAttachmentRecord(record?: Partial<AttachmentRecord>): Promise<AttachmentRecord>;
127
+ init(): Promise<void>;
128
+ /**
129
+ * Dispose the attachment queue and clean up resources.
130
+ * This method is synchronous to ensure callers don't need to await it,
131
+ * but it fires off async cleanup in the background for graceful shutdown.
132
+ */
133
+ dispose(): void;
134
+ /**
135
+ * Async cleanup that runs in the background after dispose().
136
+ * Waits for active upload promises to settle gracefully.
137
+ */
138
+ private _asyncCleanup;
139
+ queueUpload(options: {
140
+ storagePath: string;
141
+ sourceUri: string;
142
+ filename: string;
143
+ mediaType: string;
144
+ bucketId?: string;
145
+ metadata?: Record<string, unknown>;
146
+ }): Promise<void>;
147
+ getPendingUploads(): Promise<PolAttachmentRecord[]>;
148
+ getSoonestRetryTime(): Promise<number | null>;
149
+ getFailedPermanentUploads(): Promise<PolAttachmentRecord[]>;
150
+ getStaleUploads(): Promise<PolAttachmentRecord[]>;
151
+ getSyncedUploadsWithPendingCallback(): Promise<PolAttachmentRecord[]>;
152
+ clearUploadCallback(id: string): Promise<void>;
153
+ retryUpload(id: string): Promise<void>;
154
+ /**
155
+ * Reset all uploads in QUEUED_UPLOAD state so they retry immediately.
156
+ * This clears retry counts and errors, allowing uploads to be retried fresh.
157
+ *
158
+ * @returns The number of uploads that were reset
159
+ */
160
+ resetUploadRetries(): Promise<number>;
161
+ /**
162
+ * Trigger immediate retry of uploads WITHOUT resetting their retry count.
163
+ * This preserves backoff state for truly failing uploads while allowing
164
+ * uploads that were waiting for network to retry immediately.
165
+ *
166
+ * Only affects uploads that:
167
+ * - Are past their retry time (upload_next_retry_at <= now), OR
168
+ * - Have no retry time set (upload_next_retry_at IS NULL)
169
+ *
170
+ * @returns The number of uploads that will be retried
171
+ */
172
+ retryUploads(): Promise<number>;
173
+ deleteUpload(id: string): Promise<void>;
174
+ /**
175
+ * Re-queue an upload for an orphaned attachment.
176
+ * Use this when a database record exists with a storagePath but the file was never uploaded.
177
+ *
178
+ * This handles the case where:
179
+ * - User took a photo and the database record was created with a storagePath
180
+ * - The attachment queue record was created but disappeared before upload completed
181
+ * - The photo shows locally but was never uploaded to storage
182
+ *
183
+ * @param options.storagePath - The storage path (e.g., "projectId/fileId.jpg")
184
+ * @param options.localFileUri - URI to the local file to upload
185
+ * @param options.mediaType - MIME type of the file
186
+ * @param options.bucketId - Optional bucket ID for multi-bucket setups
187
+ * @returns true if upload was queued, false if already exists in valid state
188
+ */
189
+ requeueOrphanedUpload(options: {
190
+ storagePath: string;
191
+ localFileUri: string;
192
+ mediaType: string;
193
+ bucketId?: string;
194
+ }): Promise<boolean>;
195
+ getRecord(id: string): Promise<PolAttachmentRecord | null>;
196
+ getFailedUploads(): Promise<PolAttachmentRecord[]>;
197
+ retryFailedUpload(id: string): Promise<void>;
198
+ deleteFailedUpload(id: string): Promise<void>;
199
+ get activeUploads(): UploadStatus[];
200
+ pauseUploads(): void;
201
+ resumeUploads(): void;
202
+ clearCache(): Promise<void>;
203
+ cacheLocalFile(storagePath: string, sourceUri: string): Promise<void>;
204
+ getLocalUriForStoragePath(storagePath: string): Promise<string | null>;
205
+ /**
206
+ * Purge attachments by their IDs.
207
+ * Archives and deletes local files for the specified attachment IDs.
208
+ * Useful for edge cases where external code needs to force-remove attachments.
209
+ *
210
+ * @param ids - Array of attachment IDs to purge
211
+ */
212
+ purgeAttachments(ids: string[]): Promise<void>;
213
+ onProgress(callback: (stats: AttachmentSyncStats) => void): () => void;
214
+ getStats(): Promise<AttachmentSyncStats>;
215
+ /**
216
+ * Repair attachment sizes for synced records that have size=0.
217
+ * This backfills sizes from the actual file system for existing downloads.
218
+ * @returns Number of records repaired
219
+ */
220
+ repairAttachmentSizes(): Promise<number>;
221
+ private _getDownloadManagerDeps;
222
+ private _getUploadManagerDeps;
223
+ private _getCacheManagerDeps;
224
+ private _startUploadProcessing;
225
+ private _createTableIfNotExists;
226
+ private _migrateUploadColumns;
227
+ private _invalidateStatsCache;
228
+ private _getStatus;
229
+ private _notify;
230
+ }
231
+ /**
232
+ * Factory function options that combine AttachmentConfig with required runtime dependencies.
233
+ */
234
+ interface CreateAttachmentQueueOptions extends AttachmentConfig {
235
+ /** Remote storage adapter for downloading/uploading files */
236
+ remoteStorage: AttachmentStorageAdapter;
237
+ /**
238
+ * Supabase client for passing to watchPaths callback.
239
+ * Required when using watchPaths (new API).
240
+ */
241
+ supabaseClient?: unknown;
242
+ /** Upload handler for processing uploads */
243
+ uploadHandler?: UploadHandler;
244
+ /** Upload configuration */
245
+ uploadConfig?: Partial<UploadConfig>;
246
+ /** Download configuration (concurrency, timeout) */
247
+ downloadConfig?: Partial<DownloadConfig>;
248
+ /** Compression configuration */
249
+ compression?: Partial<CompressionConfig>;
250
+ /** Cache configuration */
251
+ cache?: Partial<CacheConfig>;
252
+ }
253
+ declare function createPolAttachmentQueue(powersync: AbstractPowerSyncDatabase, platform: PlatformAdapter, config: CreateAttachmentQueueOptions): PolAttachmentQueue;
254
+
255
+ export { PolAttachmentQueue as P, type PolAttachmentQueueOptions as a, createPolAttachmentQueue as c };
@@ -1,17 +1,19 @@
1
1
  import { SupabaseClient } from '@supabase/supabase-js';
2
2
  import { QueryClient } from '@tanstack/react-query';
3
- import { A as AbstractPowerSyncDatabase, a as SyncStatus, C as CrudEntry, S as SyncMode, F as FailedTransaction, h as CompletedTransaction, b as ConnectionHealth, e as SyncMetrics, D as DownloadProgress, E as EntitySyncState, f as SyncError, U as UploadBlockReason } from '../types-Dv1uf0LZ.js';
3
+ import { A as AbstractPowerSyncDatabase, a as SyncStatus, C as CrudEntry, S as SyncMode, F as FailedTransaction, h as CompletedTransaction, b as ConnectionHealth, e as SyncMetrics, D as DownloadProgress, E as EntitySyncState, f as SyncError, U as UploadBlockReason } from '../types-B9MptP7E.js';
4
4
  import { PlatformAdapter } from '../platform/index.js';
5
- import { a as ConnectorConfig, i as ConflictBus } from '../types-CpM2_LhU.js';
6
- import { f as AttachmentConfig, P as PolAttachmentQueue, A as AttachmentSourceConfig, F as AttachmentRecord, C as CompressionConfig, j as DownloadConfig } from '../pol-attachment-queue-BE2HU3Us.js';
7
- import { S as SupabaseConnector } from '../supabase-connector-C4YpH_l3.js';
5
+ import { a as ConnectorConfig, i as ConflictBus, h as UploadErrorMiddleware } from '../types-DqJnP50o.js';
6
+ import { d as AttachmentConfig, c as AttachmentSourceConfig, z as AttachmentRecord, f as CompressionConfig, i as DownloadConfig } from '../types-JCEhw2Lf.js';
7
+ import { P as PolAttachmentQueue } from '../pol-attachment-queue-DqBvLAEY.js';
8
+ import { S as SupabaseConnector } from '../supabase-connector-HMxBA9Kg.js';
8
9
  import * as react from 'react';
9
10
  import react__default, { ReactNode } from 'react';
10
11
  import { Schema } from '@powersync/react-native';
11
- import { a as StorageBackend } from '../types-D0WcHrq6.js';
12
- import { h as BackgroundSyncSystem, c as SyncControlActions } from '../background-sync-CVR3PkFi.js';
13
- import '@powersync/attachments';
12
+ import { a as StorageBackend } from '../types-CGMibJKD.js';
13
+ import { h as BackgroundSyncSystem, c as SyncControlActions } from '../background-sync-BujnI3IR.js';
14
+ import { a as ProcessedPolConfig } from '../types-BhAEsJj-.js';
14
15
  import '@powersync/common';
16
+ import '@powersync/attachments';
15
17
 
16
18
  /**
17
19
  * Provider Types for @pol-studios/powersync
@@ -79,8 +81,12 @@ interface PowerSyncConfig<TSchema = unknown> {
79
81
  * @example
80
82
  * ```typescript
81
83
  * attachments: {
82
- * source: { table: 'photos', idColumn: 'storage_path' },
83
- * remoteStorage: supabaseStorageAdapter,
84
+ * source: { type: 'supabase-bucket', bucket: 'photos' },
85
+ * watchPaths: (db, supabase, onUpdate) => {
86
+ * db.watch('SELECT storage_path FROM photos', [], {
87
+ * onResult: (r) => onUpdate(r.rows._array.map(x => x.storage_path)),
88
+ * });
89
+ * },
84
90
  * }
85
91
  * ```
86
92
  */
@@ -116,6 +122,26 @@ interface SyncConfig {
116
122
  */
117
123
  enableMetrics?: boolean;
118
124
  }
125
+ /**
126
+ * Options for resetSync operation.
127
+ */
128
+ interface ResetSyncOptions {
129
+ /**
130
+ * Clear downloaded attachments (photos, documents).
131
+ * @default true
132
+ */
133
+ clearAttachments?: boolean;
134
+ /**
135
+ * Clear React Query cache.
136
+ * @default true
137
+ */
138
+ clearQueryCache?: boolean;
139
+ /**
140
+ * Timeout for cache operations in milliseconds.
141
+ * @default 30000
142
+ */
143
+ timeout?: number;
144
+ }
119
145
  /**
120
146
  * Value provided by the main PowerSyncContext.
121
147
  *
@@ -173,6 +199,23 @@ interface PowerSyncContextValue<TSchema = unknown> {
173
199
  * Use this to wire up conflict UI components.
174
200
  */
175
201
  conflictBus: ConflictBus;
202
+ /**
203
+ * Reset sync data by disconnecting and clearing synced data.
204
+ * Optionally clears React Query cache and attachment cache.
205
+ *
206
+ * @param options - Reset options
207
+ * @example
208
+ * ```typescript
209
+ * const { resetSync } = usePowerSync();
210
+ *
211
+ * await resetSync({
212
+ * clearAttachments: true, // Clear downloaded photos/documents
213
+ * clearQueryCache: true, // Clear React Query cache
214
+ * timeout: 30000, // Timeout for cache operations
215
+ * });
216
+ * ```
217
+ */
218
+ resetSync: (options?: ResetSyncOptions) => Promise<void>;
176
219
  }
177
220
  /**
178
221
  * Value provided by SyncStatusContext.
@@ -722,7 +765,26 @@ interface PowerSyncSyncStatusSnapshot {
722
765
  }
723
766
  /**
724
767
  * Attachment configuration for OfflineDataProvider.
725
- * Uses the new 2-callback API (watchIds, skipDownload).
768
+ *
769
+ * @example
770
+ * ```typescript
771
+ * attachments: {
772
+ * source: { type: 'supabase-bucket', bucket: 'photos', signed: true },
773
+ * watchPaths: (db, supabase, onUpdate) => {
774
+ * const abort = new AbortController();
775
+ * db.watch(
776
+ * // Filter directly in the query - only emit paths you want to download
777
+ * `SELECT storagePath FROM photos
778
+ * WHERE storagePath IS NOT NULL
779
+ * AND storagePath NOT LIKE '%.mp4'`,
780
+ * [],
781
+ * { onResult: (r) => onUpdate(r.rows._array.map(x => x.storagePath)) },
782
+ * { signal: abort.signal }
783
+ * );
784
+ * return () => abort.abort();
785
+ * },
786
+ * }
787
+ * ```
726
788
  */
727
789
  interface OfflineDataAttachmentConfig extends AttachmentSourceConfig {
728
790
  /** Optional: callback when upload completes */
@@ -768,6 +830,8 @@ interface OfflineDataProviderConfig {
768
830
  conflictDetection?: {
769
831
  enabled: boolean;
770
832
  };
833
+ /** Upload error middleware chain for classifying and handling upload errors */
834
+ uploadErrorMiddleware?: UploadErrorMiddleware[];
771
835
  };
772
836
  /** Sync behavior configuration */
773
837
  sync?: {
@@ -783,8 +847,45 @@ interface OfflineDataProviderConfig {
783
847
  * Props for OfflineDataProvider
784
848
  */
785
849
  interface OfflineDataProviderProps {
786
- /** Provider configuration */
787
- config: OfflineDataProviderConfig;
850
+ /**
851
+ * Provider configuration (legacy).
852
+ * Use either `config` OR `polConfig`, not both.
853
+ */
854
+ config?: OfflineDataProviderConfig;
855
+ /**
856
+ * Unified configuration from `definePolConfig`.
857
+ * This is the recommended way to configure OfflineDataProvider.
858
+ *
859
+ * When using polConfig, you must also provide:
860
+ * - `supabaseClient`
861
+ * - `queryClient`
862
+ *
863
+ * @example
864
+ * ```tsx
865
+ * import { definePolConfig } from '@pol-studios/powersync/config';
866
+ *
867
+ * const polConfig = definePolConfig({ ... });
868
+ *
869
+ * <OfflineDataProvider
870
+ * polConfig={polConfig}
871
+ * supabaseClient={supabase}
872
+ * queryClient={queryClient}
873
+ * >
874
+ * <App />
875
+ * </OfflineDataProvider>
876
+ * ```
877
+ */
878
+ polConfig?: ProcessedPolConfig;
879
+ /**
880
+ * Supabase client instance.
881
+ * Required when using `polConfig`.
882
+ */
883
+ supabaseClient?: SupabaseClient;
884
+ /**
885
+ * React Query client.
886
+ * Required when using `polConfig`.
887
+ */
888
+ queryClient?: QueryClient;
788
889
  children: ReactNode;
789
890
  /**
790
891
  * DataLayer configuration for @pol-studios/db integration.
@@ -803,6 +904,37 @@ interface OfflineDataProviderProps {
803
904
  skipStorageQueueProvider?: boolean;
804
905
  /** Custom storage backend (overrides built-in Supabase adapter) */
805
906
  storageBackend?: StorageBackend;
907
+ /**
908
+ * Custom platform adapter (optional).
909
+ * Use this to provide custom logging or filesystem implementations.
910
+ * If not provided, a default native platform adapter is created.
911
+ */
912
+ platform?: PlatformAdapter;
913
+ /**
914
+ * Attachment callback overrides at React level.
915
+ * These override the callbacks defined in polConfig.attachments,
916
+ * allowing you to use React hooks or access component context.
917
+ *
918
+ * @example
919
+ * ```tsx
920
+ * const watchPaths = useCallback((db, supabase, onUpdate) => {
921
+ * db.watch(
922
+ * `SELECT storagePath FROM photos
923
+ * WHERE storagePath IS NOT NULL
924
+ * AND mediaType NOT LIKE 'video/%'`,
925
+ * [],
926
+ * { onResult: (r) => onUpdate(r.rows._array.map(x => x.storagePath)) }
927
+ * );
928
+ * return () => {};
929
+ * }, []);
930
+ *
931
+ * <OfflineDataProvider
932
+ * polConfig={polConfig}
933
+ * attachments={{ watchPaths }}
934
+ * >
935
+ * ```
936
+ */
937
+ attachments?: Partial<Pick<OfflineDataAttachmentConfig, 'watchPaths'>>;
806
938
  /** Custom error UI for initialization errors */
807
939
  renderInitError?: (error: Error, retry: () => void) => ReactNode;
808
940
  /** Custom error UI (alias for renderInitError) */
@@ -839,94 +971,6 @@ interface ProviderBridgeProps {
839
971
  onRemovePendingMutationReady: (remove: (id: string) => void) => void;
840
972
  }
841
973
 
842
- /**
843
- * OfflineDataProvider Component for @pol-studios/powersync
844
- *
845
- * Batteries-included offline data provider that combines:
846
- * - PowerSyncProvider for offline-first data sync
847
- * - DataLayerProvider integration from @pol-studios/db
848
- * - ConflictProvider for conflict resolution UI
849
- * - StorageQueueProvider for attachment queue access
850
- * - Background sync system setup
851
- * - Error recovery UI with retry capability
852
- * - Online-only mode fallback (no PowerSync URL)
853
- *
854
- * @example
855
- * ```tsx
856
- * <OfflineDataProvider
857
- * config={{
858
- * schema: AppSchema,
859
- * supabaseClient: supabase,
860
- * queryClient: queryClient,
861
- * powerSyncUrl: env.powerSyncUrl,
862
- * attachments: {
863
- * bucket: 'my-bucket',
864
- * watchIds: (db, onUpdate) => {
865
- * db.watch('SELECT storagePath as id FROM photos', [], {
866
- * onResult: (r) => onUpdate(r.rows._array.map(x => x.id)),
867
- * });
868
- * },
869
- * skipDownload: async ({ ids }) => {
870
- * // Return IDs to skip downloading (e.g., videos)
871
- * return ids.filter(id => id.endsWith('.mp4'));
872
- * },
873
- * },
874
- * }}
875
- * dataLayer={{ config: dataLayerConfig }}
876
- * renderInitError={(error, retry) => <MyErrorUI error={error} onRetry={retry} />}
877
- * >
878
- * <App />
879
- * </OfflineDataProvider>
880
- * ```
881
- */
882
-
883
- /**
884
- * Batteries-included offline data provider.
885
- *
886
- * Combines PowerSyncProvider with error boundary, DataLayerProvider integration,
887
- * and sensible defaults for a complete offline-first data solution.
888
- *
889
- * Key features:
890
- * - Automatic PowerSync setup and initialization
891
- * - Integration with @pol-studios/db DataLayerProvider
892
- * - ConflictProvider and StorageQueueProvider wiring
893
- * - Background sync system support
894
- * - Error recovery UI with retry capability
895
- * - Online-only mode fallback when no PowerSync URL is provided
896
- *
897
- * @example
898
- * ```tsx
899
- * // Basic usage
900
- * <OfflineDataProvider
901
- * config={{
902
- * schema: AppSchema,
903
- * supabaseClient: supabase,
904
- * queryClient: queryClient,
905
- * powerSyncUrl: process.env.EXPO_PUBLIC_POWERSYNC_URL,
906
- * }}
907
- * >
908
- * <App />
909
- * </OfflineDataProvider>
910
- *
911
- * // With DataLayer integration
912
- * <OfflineDataProvider
913
- * config={{ ... }}
914
- * dataLayer={{ config: dataLayerConfig }}
915
- * >
916
- * <App />
917
- * </OfflineDataProvider>
918
- *
919
- * // With custom error UI
920
- * <OfflineDataProvider
921
- * config={{ ... }}
922
- * renderInitError={(error, retry) => <MyErrorUI error={error} onRetry={retry} />}
923
- * >
924
- * <App />
925
- * </OfflineDataProvider>
926
- * ```
927
- */
928
- declare function OfflineDataProvider({ config, children, dataLayer, backgroundSync, skipConflictProvider, skipStorageQueueProvider, storageBackend, renderInitError, renderError, onReady, onError, onSyncStatusChange, onBackgroundSyncSystemReady: onBackgroundSyncSystemReadyProp, }: OfflineDataProviderProps): react__default.ReactElement;
929
-
930
974
  /**
931
975
  * ProviderBridge Component for @pol-studios/powersync
932
976
  *
@@ -1684,21 +1728,12 @@ interface RetryCountdownResult {
1684
1728
  }
1685
1729
  /**
1686
1730
  * Hook for retry countdown display.
1687
- * Returns the soonest nextRetryAt from all failed transactions.
1688
- * Re-renders every second when countdown is active.
1689
1731
  *
1690
- * @returns Retry countdown information
1732
+ * @deprecated The nextRetryAt and backoffMs fields have been removed from FailedTransaction.
1733
+ * PowerSync SDK now controls retry timing internally. This hook is retained for backward
1734
+ * compatibility but will always return null values.
1691
1735
  *
1692
- * @example
1693
- * ```typescript
1694
- * function RetryTimer() {
1695
- * const { nextRetryAt, formattedCountdown } = useRetryCountdown();
1696
- *
1697
- * if (!nextRetryAt) return null;
1698
- *
1699
- * return <Text>Retrying in {formattedCountdown}</Text>;
1700
- * }
1701
- * ```
1736
+ * @returns Retry countdown information (always returns null values)
1702
1737
  */
1703
1738
  declare function useRetryCountdown(): RetryCountdownResult;
1704
1739
 
@@ -1720,4 +1755,4 @@ declare const UPLOAD_MAX_RETRIES = 7;
1720
1755
  */
1721
1756
  declare const UPLOAD_BACKOFF_DELAYS: readonly [4, 8, 16, 32, 64, 128, 256];
1722
1757
 
1723
- export { AttachmentQueueContext, type BackgroundSyncCallbacks, type BackgroundSyncConfig, type BackgroundSyncStatus, CompletedTransactionsContext, type CompletedTransactionsContextValue, ConnectionHealthContext, type ConnectionHealthContextValue, ConnectionStatusContext, type ConnectionStatusContextValue, DEFAULT_CONNECTION_HEALTH, DEFAULT_SYNC_CONFIG, DEFAULT_SYNC_METRICS, DEFAULT_SYNC_STATUS, type DataLayerConfig, type DataLayerIntegration, type EntitySyncStatusResult, FailedTransactionsContext, type FailedTransactionsContextValue, type OfflineDataAttachmentConfig, OfflineDataProvider, type OfflineDataProviderConfig, type OfflineDataProviderProps, PendingMutationsContext, type PendingMutationsContextValue, type PowerSyncConfig, PowerSyncContext, type PowerSyncContextValue, PowerSyncProvider, type PowerSyncProviderProps, type PowerSyncSyncStatusSnapshot, ProviderBridge, type ProviderBridgeProps, type RetryCountdownResult, SyncActivityContext, type SyncActivityContextValue, type SyncActivityResult, type SyncConfig, SyncMetricsContext, type SyncMetricsContextValue, SyncModeContext, type SyncModeContextValue, SyncStatusContext, type SyncStatusContextValue, UPLOAD_BACKOFF_DELAYS, UPLOAD_MAX_RETRIES, type UploadBlockedReasonResult, type UploadStatusResult, useAttachmentQueue, useAttachmentQueueReady, useCompletedTransactions, useCompletedTransactionsContext, useConnectionHealth, useConnectionStatus, useDatabase, useDownloadProgress, useEntitySyncStatus, useFailedTransactions, useFailedTransactionsContext, useIsSyncing, useOnlineStatus, usePendingMutations, usePendingMutationsContext, usePlatform, usePowerSync, useRetryCountdown, useSyncActivity, useSyncActivityContext, useSyncControl, useSyncMetrics, useSyncMode, useSyncModeContext, useSyncStatus, useUploadBlockedReason, useUploadRetry, useUploadStatus };
1758
+ export { AttachmentQueueContext, type BackgroundSyncCallbacks, type BackgroundSyncConfig, type BackgroundSyncStatus, CompletedTransactionsContext, type CompletedTransactionsContextValue, ConnectionHealthContext, type ConnectionHealthContextValue, ConnectionStatusContext, type ConnectionStatusContextValue, DEFAULT_CONNECTION_HEALTH, DEFAULT_SYNC_CONFIG, DEFAULT_SYNC_METRICS, DEFAULT_SYNC_STATUS, type DataLayerConfig, type DataLayerIntegration, type EntitySyncStatusResult, FailedTransactionsContext, type FailedTransactionsContextValue, type OfflineDataAttachmentConfig, type OfflineDataProviderConfig, type OfflineDataProviderProps, PendingMutationsContext, type PendingMutationsContextValue, type PowerSyncConfig, PowerSyncContext, type PowerSyncContextValue, PowerSyncProvider, type PowerSyncProviderProps, type PowerSyncSyncStatusSnapshot, ProviderBridge, type ProviderBridgeProps, type ResetSyncOptions, type RetryCountdownResult, SyncActivityContext, type SyncActivityContextValue, type SyncActivityResult, type SyncConfig, SyncMetricsContext, type SyncMetricsContextValue, SyncModeContext, type SyncModeContextValue, SyncStatusContext, type SyncStatusContextValue, UPLOAD_BACKOFF_DELAYS, UPLOAD_MAX_RETRIES, type UploadBlockedReasonResult, type UploadStatusResult, useAttachmentQueue, useAttachmentQueueReady, useCompletedTransactions, useCompletedTransactionsContext, useConnectionHealth, useConnectionStatus, useDatabase, useDownloadProgress, useEntitySyncStatus, useFailedTransactions, useFailedTransactionsContext, useIsSyncing, useOnlineStatus, usePendingMutations, usePendingMutationsContext, usePlatform, usePowerSync, useRetryCountdown, useSyncActivity, useSyncActivityContext, useSyncControl, useSyncMetrics, useSyncMode, useSyncModeContext, useSyncStatus, useUploadBlockedReason, useUploadRetry, useUploadStatus };
@@ -1,20 +1,17 @@
1
1
  import {
2
- OfflineDataProvider,
3
2
  PowerSyncProvider,
4
3
  ProviderBridge,
5
4
  UPLOAD_BACKOFF_DELAYS,
6
5
  UPLOAD_MAX_RETRIES
7
- } from "../chunk-JCGOZVWL.js";
8
- import "../chunk-YHTZ7VMV.js";
9
- import "../chunk-P6WOZO7H.js";
10
- import "../chunk-CACKC6XG.js";
11
- import "../chunk-RE5HWLCB.js";
6
+ } from "../chunk-P4D6BQ4X.js";
7
+ import "../chunk-PGEDE6IM.js";
12
8
  import {
13
9
  DEFAULT_CONNECTION_HEALTH,
14
10
  DEFAULT_SYNC_CONFIG,
15
11
  DEFAULT_SYNC_METRICS,
16
12
  DEFAULT_SYNC_STATUS
17
- } from "../chunk-FNYQFILT.js";
13
+ } from "../chunk-2RDWLXJW.js";
14
+ import "../chunk-OGUFUZSY.js";
18
15
  import {
19
16
  AttachmentQueueContext,
20
17
  CompletedTransactionsContext,
@@ -55,15 +52,14 @@ import {
55
52
  useUploadBlockedReason,
56
53
  useUploadRetry,
57
54
  useUploadStatus
58
- } from "../chunk-C2ACBYBZ.js";
59
- import "../chunk-CAB26E6F.js";
60
- import "../chunk-XAEII4ZX.js";
61
- import "../chunk-Z6VOBGTU.js";
55
+ } from "../chunk-74TBHWJ4.js";
56
+ import "../chunk-NUGQOTEM.js";
57
+ import "../chunk-UOMHWUHV.js";
62
58
  import "../chunk-FV2HXEIY.js";
63
59
  import "../chunk-CGL33PL4.js";
64
- import "../chunk-WN5ZJ3E2.js";
65
- import "../chunk-BC2SRII2.js";
60
+ import "../chunk-65A3SYJZ.js";
66
61
  import "../chunk-I2AYMY5O.js";
62
+ import "../chunk-5WRI5ZAA.js";
67
63
  export {
68
64
  AttachmentQueueContext,
69
65
  CompletedTransactionsContext,
@@ -74,7 +70,6 @@ export {
74
70
  DEFAULT_SYNC_METRICS,
75
71
  DEFAULT_SYNC_STATUS,
76
72
  FailedTransactionsContext,
77
- OfflineDataProvider,
78
73
  PendingMutationsContext,
79
74
  PowerSyncContext,
80
75
  PowerSyncProvider,