@pol-studios/powersync 1.0.25 → 1.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/dist/{CacheSettingsManager-uz-kbnRH.d.ts → CacheSettingsManager-0H_7thHW.d.ts} +21 -3
- package/dist/attachments/index.d.ts +30 -30
- package/dist/attachments/index.js +13 -4
- package/dist/{background-sync-ChCXW-EV.d.ts → background-sync-BujnI3IR.d.ts} +1 -1
- package/dist/{chunk-55DKCJV4.js → chunk-2RDWLXJW.js} +408 -78
- package/dist/chunk-2RDWLXJW.js.map +1 -0
- package/dist/{chunk-P4HZA6ZT.js → chunk-4665ZSE5.js} +2 -2
- package/dist/chunk-4665ZSE5.js.map +1 -0
- package/dist/{chunk-XOY2CJ67.js → chunk-4F5B5CZ7.js} +3 -3
- package/dist/chunk-5WRI5ZAA.js +31 -0
- package/dist/{chunk-BGBQYQV3.js → chunk-65A3SYJZ.js} +193 -299
- package/dist/chunk-65A3SYJZ.js.map +1 -0
- package/dist/chunk-6SZ64KCZ.js +755 -0
- package/dist/chunk-6SZ64KCZ.js.map +1 -0
- package/dist/{chunk-YSTEESEG.js → chunk-74TBHWJ4.js} +122 -11
- package/dist/chunk-74TBHWJ4.js.map +1 -0
- package/dist/chunk-ANXWYQEJ.js +1 -0
- package/dist/chunk-ANXWYQEJ.js.map +1 -0
- package/dist/{chunk-CAB26E6F.js → chunk-C4J4MLER.js} +29 -24
- package/dist/chunk-C4J4MLER.js.map +1 -0
- package/dist/{chunk-C5ODS3XH.js → chunk-EOW7JK7Q.js} +9 -16
- package/dist/chunk-EOW7JK7Q.js.map +1 -0
- package/dist/chunk-HRAVPIAZ.js +220 -0
- package/dist/chunk-HRAVPIAZ.js.map +1 -0
- package/dist/{chunk-XAEII4ZX.js → chunk-NUGQOTEM.js} +32 -4
- package/dist/chunk-NUGQOTEM.js.map +1 -0
- package/dist/chunk-OGUFUZSY.js +5415 -0
- package/dist/chunk-OGUFUZSY.js.map +1 -0
- package/dist/{chunk-VB737IVN.js → chunk-P4D6BQ4X.js} +328 -706
- package/dist/chunk-P4D6BQ4X.js.map +1 -0
- package/dist/{chunk-CACKC6XG.js → chunk-PGEDE6IM.js} +136 -89
- package/dist/chunk-PGEDE6IM.js.map +1 -0
- package/dist/{chunk-A4IBBWGO.js → chunk-RALHHPTU.js} +1 -1
- package/dist/chunk-RIDSPLE5.js +42 -0
- package/dist/chunk-RIDSPLE5.js.map +1 -0
- package/dist/{chunk-Z6VOBGTU.js → chunk-UOMHWUHV.js} +2 -12
- package/dist/chunk-UOMHWUHV.js.map +1 -0
- package/dist/{chunk-WGHNIAF7.js → chunk-YONQYTVH.js} +2 -2
- package/dist/chunk-ZAN22NGL.js +13 -0
- package/dist/chunk-ZAN22NGL.js.map +1 -0
- package/dist/config/index.d.ts +200 -0
- package/dist/config/index.js +23 -0
- package/dist/config/index.js.map +1 -0
- package/dist/connector/index.d.ts +23 -5
- package/dist/connector/index.js +4 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +1 -0
- package/dist/error/index.js +1 -0
- package/dist/generator/index.js +2 -0
- package/dist/generator/index.js.map +1 -1
- package/dist/index.d.ts +19 -16
- package/dist/index.js +88 -46
- package/dist/index.native.d.ts +18 -14
- package/dist/index.native.js +93 -44
- package/dist/index.web.d.ts +17 -14
- package/dist/index.web.js +88 -46
- package/dist/maintenance/index.d.ts +2 -2
- package/dist/maintenance/index.js +3 -2
- package/dist/platform/index.d.ts +1 -1
- package/dist/platform/index.js +2 -0
- package/dist/platform/index.js.map +1 -1
- package/dist/platform/index.native.d.ts +1 -1
- package/dist/platform/index.native.js +1 -0
- package/dist/platform/index.web.d.ts +1 -1
- package/dist/platform/index.web.js +1 -0
- package/dist/pol-attachment-queue-DqBvLAEY.d.ts +255 -0
- package/dist/provider/index.d.ts +319 -124
- package/dist/provider/index.js +21 -16
- package/dist/provider/index.native.d.ts +108 -0
- package/dist/provider/index.native.js +121 -0
- package/dist/provider/index.native.js.map +1 -0
- package/dist/provider/index.web.d.ts +16 -0
- package/dist/provider/index.web.js +112 -0
- package/dist/provider/index.web.js.map +1 -0
- package/dist/react/index.d.ts +16 -65
- package/dist/react/index.js +2 -9
- package/dist/storage/index.d.ts +5 -4
- package/dist/storage/index.js +12 -9
- package/dist/storage/index.native.d.ts +5 -4
- package/dist/storage/index.native.js +8 -5
- package/dist/storage/index.web.d.ts +5 -4
- package/dist/storage/index.web.js +11 -8
- package/dist/storage/upload/index.d.ts +4 -3
- package/dist/storage/upload/index.js +4 -2
- package/dist/storage/upload/index.native.d.ts +4 -3
- package/dist/storage/upload/index.native.js +4 -2
- package/dist/storage/upload/index.web.d.ts +2 -1
- package/dist/storage/upload/index.web.js +4 -2
- package/dist/{supabase-connector-D2oIl2t8.d.ts → supabase-connector-HMxBA9Kg.d.ts} +23 -25
- package/dist/sync/index.d.ts +183 -11
- package/dist/sync/index.js +13 -3
- package/dist/{types-CyvBaAl8.d.ts → types-6QHGELuY.d.ts} +4 -1
- package/dist/{types-CDqWh56B.d.ts → types-B9MptP7E.d.ts} +13 -1
- package/dist/types-BhAEsJj-.d.ts +330 -0
- package/dist/{types-D0WcHrq6.d.ts → types-CGMibJKD.d.ts} +8 -0
- package/dist/{types-DiBvmGEi.d.ts → types-DqJnP50o.d.ts} +22 -24
- package/dist/{pol-attachment-queue-BE2HU3Us.d.ts → types-JCEhw2Lf.d.ts} +139 -346
- package/package.json +18 -4
- package/dist/chunk-24RDMMCL.js +0 -44
- package/dist/chunk-24RDMMCL.js.map +0 -1
- package/dist/chunk-55DKCJV4.js.map +0 -1
- package/dist/chunk-654ERHA7.js +0 -1
- package/dist/chunk-BGBQYQV3.js.map +0 -1
- package/dist/chunk-C5ODS3XH.js.map +0 -1
- package/dist/chunk-CAB26E6F.js.map +0 -1
- package/dist/chunk-CACKC6XG.js.map +0 -1
- package/dist/chunk-P4HZA6ZT.js.map +0 -1
- package/dist/chunk-TIFL2KWE.js +0 -358
- package/dist/chunk-TIFL2KWE.js.map +0 -1
- package/dist/chunk-VB737IVN.js.map +0 -1
- package/dist/chunk-XAEII4ZX.js.map +0 -1
- package/dist/chunk-YSTEESEG.js.map +0 -1
- package/dist/chunk-Z6VOBGTU.js.map +0 -1
- /package/dist/{chunk-XOY2CJ67.js.map → chunk-4F5B5CZ7.js.map} +0 -0
- /package/dist/{chunk-654ERHA7.js.map → chunk-5WRI5ZAA.js.map} +0 -0
- /package/dist/{chunk-A4IBBWGO.js.map → chunk-RALHHPTU.js.map} +0 -0
- /package/dist/{chunk-WGHNIAF7.js.map → chunk-YONQYTVH.js.map} +0 -0
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { AbstractAttachmentQueue, AttachmentQueueOptions, AttachmentRecord as AttachmentRecord$1 } from '@powersync/attachments';
|
|
2
1
|
import { AbstractPowerSyncDatabase } from '@powersync/common';
|
|
3
|
-
import { PlatformAdapter } from './platform/index.js';
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* Attachment Queue Types for @pol-studios/powersync
|
|
@@ -49,9 +47,7 @@ declare enum PolAttachmentState {
|
|
|
49
47
|
/** Attachment has been orphaned, i.e. the associated record has been deleted */
|
|
50
48
|
ARCHIVED = 4,
|
|
51
49
|
/** Permanently failed (exhausted retries or unrecoverable error) - POL extension */
|
|
52
|
-
FAILED_PERMANENT = 5
|
|
53
|
-
/** Download was skipped due to downloadFilter returning false - POL extension */
|
|
54
|
-
DOWNLOAD_SKIPPED = 6
|
|
50
|
+
FAILED_PERMANENT = 5
|
|
55
51
|
}
|
|
56
52
|
/**
|
|
57
53
|
* Extended attachment record with POL-specific upload tracking fields.
|
|
@@ -94,23 +90,12 @@ interface PolAttachmentRecord {
|
|
|
94
90
|
/**
|
|
95
91
|
* Configuration for watching a source table.
|
|
96
92
|
* Used by query-builder utilities to generate SQL queries.
|
|
97
|
-
*
|
|
98
|
-
* Note: Either `pathColumn` or `idColumn` must be provided.
|
|
99
|
-
* `pathColumn` is the preferred option; `idColumn` is deprecated but still supported.
|
|
100
93
|
*/
|
|
101
94
|
interface WatchConfig {
|
|
102
95
|
/** Source table name */
|
|
103
96
|
table: string;
|
|
104
|
-
/**
|
|
105
|
-
|
|
106
|
-
* Preferred over `idColumn`.
|
|
107
|
-
*/
|
|
108
|
-
pathColumn?: string;
|
|
109
|
-
/**
|
|
110
|
-
* Column containing attachment ID/path.
|
|
111
|
-
* @deprecated Use `pathColumn` instead. Will be removed in a future version.
|
|
112
|
-
*/
|
|
113
|
-
idColumn?: string;
|
|
97
|
+
/** Column containing attachment path */
|
|
98
|
+
pathColumn: string;
|
|
114
99
|
/** Additional columns to include in context */
|
|
115
100
|
selectColumns?: string[];
|
|
116
101
|
/** Optional WHERE clause fragment (e.g., "storagePath IS NOT NULL") */
|
|
@@ -144,20 +129,54 @@ interface SimpleAttachmentConfig {
|
|
|
144
129
|
pathColumn: string;
|
|
145
130
|
}
|
|
146
131
|
/**
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*/
|
|
150
|
-
interface
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
132
|
+
* Supabase bucket source configuration.
|
|
133
|
+
* Uses Supabase Storage as the attachment backend.
|
|
134
|
+
*/
|
|
135
|
+
interface SupabaseBucketSource {
|
|
136
|
+
type: 'supabase-bucket';
|
|
137
|
+
/** Supabase Storage bucket name */
|
|
138
|
+
bucket: string;
|
|
139
|
+
/**
|
|
140
|
+
* Whether to use signed URLs (default: true).
|
|
141
|
+
* Set to false for public buckets to use getPublicUrl instead of createSignedUrl.
|
|
142
|
+
*/
|
|
143
|
+
signed?: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Optional: image compression settings for downloads.
|
|
146
|
+
* Uses Supabase's transform feature to resize/compress images on download.
|
|
147
|
+
* Only applies to supported image formats (jpg, png, webp, avif, gif, heic).
|
|
148
|
+
* Note: Compression is only available for supabase-bucket sources, not custom sources.
|
|
149
|
+
*/
|
|
150
|
+
compression?: Partial<CompressionConfig>;
|
|
160
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Custom source configuration for non-Supabase backends.
|
|
154
|
+
* Provide a getUrl function to resolve download URLs for attachment paths.
|
|
155
|
+
*/
|
|
156
|
+
interface CustomAttachmentSource {
|
|
157
|
+
type: 'custom';
|
|
158
|
+
/**
|
|
159
|
+
* Resolve a download URL for a given attachment path.
|
|
160
|
+
* Called during download to get the URL to fetch the file from.
|
|
161
|
+
*
|
|
162
|
+
* @param path - The attachment storage path
|
|
163
|
+
* @returns The URL to download the file from (can be async)
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```typescript
|
|
167
|
+
* source: {
|
|
168
|
+
* type: 'custom',
|
|
169
|
+
* getUrl: (path) => `https://cdn.example.com/attachments/${path}`,
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
getUrl: (path: string) => Promise<string> | string;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Discriminated union for attachment source configuration.
|
|
177
|
+
* Supports both Supabase Storage and custom backends.
|
|
178
|
+
*/
|
|
179
|
+
type AttachmentSource = SupabaseBucketSource | CustomAttachmentSource;
|
|
161
180
|
/**
|
|
162
181
|
* Configuration for an attachment source.
|
|
163
182
|
*
|
|
@@ -167,57 +186,72 @@ interface BatchFilterContext {
|
|
|
167
186
|
* @example
|
|
168
187
|
* ```typescript
|
|
169
188
|
* const config: AttachmentSourceConfig = {
|
|
170
|
-
*
|
|
189
|
+
* source: {
|
|
190
|
+
* type: 'supabase-bucket',
|
|
191
|
+
* bucket: 'project-assets',
|
|
192
|
+
* },
|
|
171
193
|
*
|
|
172
|
-
* // Reactive source of attachment
|
|
173
|
-
*
|
|
174
|
-
*
|
|
194
|
+
* // Reactive source of attachment paths
|
|
195
|
+
* watchPaths: (db, supabase, onUpdate) => {
|
|
196
|
+
* const controller = new AbortController();
|
|
175
197
|
* db.watch('SELECT storagePath FROM photos WHERE storagePath IS NOT NULL', [], {
|
|
176
198
|
* onResult: (results) => {
|
|
177
199
|
* onUpdate(results.rows._array.map(r => r.storagePath));
|
|
178
200
|
* }
|
|
179
|
-
* });
|
|
201
|
+
* }, { signal: controller.signal });
|
|
202
|
+
* return () => controller.abort();
|
|
180
203
|
* },
|
|
181
|
-
*
|
|
182
|
-
* // Optional: skip downloading videos
|
|
183
|
-
* skipDownload: async ({ ids, db }) => {
|
|
184
|
-
* const videos = await db.getAll<{ path: string }>(
|
|
185
|
-
* `SELECT storagePath as path FROM photos WHERE storagePath IN (${ids.map(() => '?').join(',')}) AND mediaType LIKE 'video/%'`,
|
|
186
|
-
* ids
|
|
187
|
-
* );
|
|
188
|
-
* return videos.map(v => v.path);
|
|
189
|
-
* }
|
|
190
204
|
* };
|
|
191
205
|
* ```
|
|
192
206
|
*/
|
|
193
207
|
interface AttachmentSourceConfig {
|
|
194
208
|
/**
|
|
195
|
-
*
|
|
196
|
-
*
|
|
209
|
+
* Attachment storage source configuration.
|
|
210
|
+
* Supports Supabase Storage buckets or custom backends.
|
|
211
|
+
*
|
|
212
|
+
* For Supabase Storage:
|
|
213
|
+
* ```typescript
|
|
214
|
+
* source: {
|
|
215
|
+
* type: 'supabase-bucket',
|
|
216
|
+
* bucket: 'my-bucket',
|
|
217
|
+
* signed: true, // default, uses createSignedUrl
|
|
218
|
+
* }
|
|
219
|
+
* ```
|
|
220
|
+
*
|
|
221
|
+
* For custom backends:
|
|
222
|
+
* ```typescript
|
|
223
|
+
* source: {
|
|
224
|
+
* type: 'custom',
|
|
225
|
+
* getUrl: (path) => `https://cdn.example.com/${path}`,
|
|
226
|
+
* }
|
|
227
|
+
* ```
|
|
197
228
|
*/
|
|
198
|
-
|
|
229
|
+
source?: AttachmentSource;
|
|
199
230
|
/**
|
|
200
|
-
* Reactive source of attachment
|
|
231
|
+
* Reactive source of attachment paths. Called once during initialization.
|
|
201
232
|
*
|
|
202
233
|
* This callback should set up a reactive subscription that calls `onUpdate`
|
|
203
|
-
* whenever the set of attachment
|
|
204
|
-
* - Queue downloads for new
|
|
205
|
-
* - Queue downloads for
|
|
206
|
-
* - Auto-archive attachments whose
|
|
234
|
+
* whenever the set of attachment paths changes. The queue will:
|
|
235
|
+
* - Queue downloads for new paths on first emission
|
|
236
|
+
* - Queue downloads for paths that appear in subsequent emissions
|
|
237
|
+
* - Auto-archive attachments whose paths disappear from emissions
|
|
207
238
|
*
|
|
208
|
-
*
|
|
209
|
-
* of providing a custom `watchIds` callback.
|
|
239
|
+
* Filtering should happen in this callback - only emit paths you want to download.
|
|
210
240
|
*
|
|
211
241
|
* @param db - PowerSync database instance for querying
|
|
212
|
-
* @param
|
|
242
|
+
* @param supabase - Supabase client for additional queries if needed
|
|
243
|
+
* @param onUpdate - Callback to emit current set of attachment paths
|
|
213
244
|
* @returns Optional cleanup function to dispose of the watch subscription
|
|
214
245
|
*
|
|
215
246
|
* @example
|
|
216
247
|
* ```typescript
|
|
217
|
-
*
|
|
248
|
+
* watchPaths: (db, supabase, onUpdate) => {
|
|
218
249
|
* const abort = new AbortController();
|
|
219
250
|
* db.watch(
|
|
220
|
-
*
|
|
251
|
+
* // Only emit non-video paths (filtering happens here)
|
|
252
|
+
* `SELECT storagePath FROM photos
|
|
253
|
+
* WHERE storagePath IS NOT NULL
|
|
254
|
+
* AND mediaType NOT LIKE 'video/%'`,
|
|
221
255
|
* [],
|
|
222
256
|
* { onResult: (r) => onUpdate(r.rows._array.map(row => row.storagePath)) },
|
|
223
257
|
* { signal: abort.signal }
|
|
@@ -226,16 +260,17 @@ interface AttachmentSourceConfig {
|
|
|
226
260
|
* }
|
|
227
261
|
* ```
|
|
228
262
|
*/
|
|
229
|
-
|
|
263
|
+
watchPaths?: (db: AbstractPowerSyncDatabase, supabase: unknown, // SupabaseClient - using unknown to avoid import
|
|
264
|
+
onUpdate: (paths: string[]) => void) => (() => void) | void;
|
|
230
265
|
/**
|
|
231
266
|
* Source table name for simplified configuration.
|
|
232
|
-
* Use with `pathColumn` as an alternative to providing a custom `
|
|
267
|
+
* Use with `pathColumn` as an alternative to providing a custom `watchPaths` callback.
|
|
233
268
|
* Only for simple single-table cases without JOINs.
|
|
234
269
|
*
|
|
235
270
|
* @example
|
|
236
271
|
* ```typescript
|
|
237
272
|
* const config: AttachmentSourceConfig = {
|
|
238
|
-
* bucket: 'photos',
|
|
273
|
+
* source: { type: 'supabase-bucket', bucket: 'photos' },
|
|
239
274
|
* table: 'EquipmentUnitMediaContent',
|
|
240
275
|
* pathColumn: 'storagePath',
|
|
241
276
|
* };
|
|
@@ -243,74 +278,45 @@ interface AttachmentSourceConfig {
|
|
|
243
278
|
*/
|
|
244
279
|
table?: string;
|
|
245
280
|
/**
|
|
246
|
-
* Column containing the attachment path
|
|
247
|
-
* Use with `table` as an alternative to providing a custom `
|
|
281
|
+
* Column containing the attachment path for simplified configuration.
|
|
282
|
+
* Use with `table` as an alternative to providing a custom `watchPaths` callback.
|
|
248
283
|
*
|
|
249
284
|
* @example
|
|
250
285
|
* ```typescript
|
|
251
286
|
* const config: AttachmentSourceConfig = {
|
|
252
|
-
* bucket: 'photos',
|
|
287
|
+
* source: { type: 'supabase-bucket', bucket: 'photos' },
|
|
253
288
|
* table: 'EquipmentUnitMediaContent',
|
|
254
289
|
* pathColumn: 'storagePath',
|
|
255
290
|
* };
|
|
256
291
|
* ```
|
|
257
292
|
*/
|
|
258
293
|
pathColumn?: string;
|
|
259
|
-
/**
|
|
260
|
-
* Optional batch filter to skip downloading certain attachments.
|
|
261
|
-
*
|
|
262
|
-
* Called with all pending attachment IDs. Return the IDs that should
|
|
263
|
-
* be SKIPPED (not downloaded). Useful for:
|
|
264
|
-
* - Filtering out video files on mobile
|
|
265
|
-
* - Skipping large files
|
|
266
|
-
* - Conditional download based on user preferences
|
|
267
|
-
*
|
|
268
|
-
* @param context - Contains pending IDs and database access
|
|
269
|
-
* @returns Promise resolving to array of IDs to skip
|
|
270
|
-
*
|
|
271
|
-
* @example
|
|
272
|
-
* ```typescript
|
|
273
|
-
* skipDownload: async ({ ids, db }) => {
|
|
274
|
-
* // Skip video files
|
|
275
|
-
* const videos = await db.getAll<{ id: string }>(
|
|
276
|
-
* `SELECT storagePath as id FROM photos
|
|
277
|
-
* WHERE storagePath IN (${ids.map(() => '?').join(',')})
|
|
278
|
-
* AND mediaType LIKE 'video/%'`,
|
|
279
|
-
* ids
|
|
280
|
-
* );
|
|
281
|
-
* return videos.map(v => v.id);
|
|
282
|
-
* }
|
|
283
|
-
* ```
|
|
284
|
-
*/
|
|
285
|
-
skipDownload?: (context: SkipDownloadContext) => Promise<string[]>;
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* Context passed to the skipDownload callback.
|
|
289
|
-
*/
|
|
290
|
-
interface SkipDownloadContext {
|
|
291
|
-
/** All pending attachment IDs to evaluate */
|
|
292
|
-
ids: string[];
|
|
293
|
-
/** PowerSync database instance for queries */
|
|
294
|
-
db: AbstractPowerSyncDatabase;
|
|
295
294
|
}
|
|
296
295
|
/**
|
|
297
296
|
* Full attachment configuration including source configs and handlers.
|
|
298
297
|
* This extends the source config with upload/download handlers and callbacks.
|
|
299
298
|
*/
|
|
300
299
|
interface AttachmentConfig {
|
|
301
|
-
/** Bucket name in Supabase storage */
|
|
302
|
-
bucket: string;
|
|
303
300
|
/**
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
301
|
+
* Attachment storage source configuration.
|
|
302
|
+
* Supports Supabase Storage buckets or custom backends.
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* ```typescript
|
|
306
|
+
* source: {
|
|
307
|
+
* type: 'supabase-bucket',
|
|
308
|
+
* bucket: 'my-bucket',
|
|
309
|
+
* signed: true, // default
|
|
310
|
+
* }
|
|
311
|
+
* ```
|
|
307
312
|
*/
|
|
308
|
-
|
|
313
|
+
source?: AttachmentSource;
|
|
309
314
|
/**
|
|
310
|
-
*
|
|
311
|
-
*
|
|
315
|
+
* Reactive source of attachment paths. Called once during initialization.
|
|
316
|
+
* May return an optional cleanup function to dispose of the watch subscription.
|
|
317
|
+
* @see AttachmentSourceConfig.watchPaths
|
|
312
318
|
*/
|
|
313
|
-
|
|
319
|
+
watchPaths?: AttachmentSourceConfig["watchPaths"];
|
|
314
320
|
/** Optional: callback when upload completes */
|
|
315
321
|
onUploadComplete?: (attachment: AttachmentRecord) => void;
|
|
316
322
|
/** Optional: callback when upload fails */
|
|
@@ -321,12 +327,6 @@ interface AttachmentConfig {
|
|
|
321
327
|
remoteStorage?: AttachmentStorageAdapter;
|
|
322
328
|
/** Optional: upload handler for uploads */
|
|
323
329
|
uploadHandler?: UploadHandler;
|
|
324
|
-
/**
|
|
325
|
-
* Optional: image compression settings for downloads.
|
|
326
|
-
* Uses Supabase's transform feature to resize/compress images on download.
|
|
327
|
-
* Only applies to supported image formats (jpg, png, webp, avif, gif, heic).
|
|
328
|
-
*/
|
|
329
|
-
compression?: Partial<CompressionConfig>;
|
|
330
330
|
/**
|
|
331
331
|
* Optional: download configuration for performance tuning.
|
|
332
332
|
* Adjusts concurrency and timeout for downloads.
|
|
@@ -639,243 +639,36 @@ interface IdRow {
|
|
|
639
639
|
* AttachmentRecord is exported as OfficialAttachmentRecord.
|
|
640
640
|
*/
|
|
641
641
|
type AttachmentRecord = PolAttachmentRecord;
|
|
642
|
-
|
|
643
642
|
/**
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
* Extends the official @powersync/attachments AbstractAttachmentQueue with
|
|
647
|
-
* POL-specific features:
|
|
648
|
-
* - Reactive watchIds callback for attachment ID sources
|
|
649
|
-
* - Optional skipDownload callback for filtering downloads
|
|
650
|
-
* - Durable upload queue with exponential backoff retry
|
|
651
|
-
* - FAILED_PERMANENT state for unrecoverable upload errors
|
|
652
|
-
* - Image compression integration
|
|
653
|
-
* - Upload callbacks (onUploadComplete, onUploadFailed)
|
|
643
|
+
* Resolve the bucket name from an AttachmentConfig or AttachmentSourceConfig.
|
|
654
644
|
*
|
|
655
|
-
* @
|
|
656
|
-
*
|
|
657
|
-
* const queue = new PolAttachmentQueue({
|
|
658
|
-
* powersync: db,
|
|
659
|
-
* storage: storageAdapter,
|
|
660
|
-
* source: {
|
|
661
|
-
* bucket: 'project-assets',
|
|
662
|
-
* watchIds: (db, onUpdate) => {
|
|
663
|
-
* db.watch('SELECT storagePath FROM photos WHERE storagePath IS NOT NULL', [], {
|
|
664
|
-
* onResult: (r) => onUpdate(r.rows._array.map(row => row.storagePath))
|
|
665
|
-
* });
|
|
666
|
-
* },
|
|
667
|
-
* skipDownload: async ({ ids, db }) => {
|
|
668
|
-
* // Return IDs to skip downloading
|
|
669
|
-
* const videos = await db.getAll('SELECT storagePath FROM photos WHERE mediaType LIKE "video/%"');
|
|
670
|
-
* return videos.map(v => v.storagePath);
|
|
671
|
-
* }
|
|
672
|
-
* },
|
|
673
|
-
* });
|
|
674
|
-
*
|
|
675
|
-
* await queue.init();
|
|
676
|
-
* ```
|
|
645
|
+
* @param config - The attachment configuration
|
|
646
|
+
* @returns The bucket name, or undefined if not configured
|
|
677
647
|
*/
|
|
678
|
-
|
|
648
|
+
declare function resolveBucketFromConfig(config: AttachmentConfig | AttachmentSourceConfig): string | undefined;
|
|
679
649
|
/**
|
|
680
|
-
*
|
|
650
|
+
* Check if the attachment source uses signed URLs.
|
|
651
|
+
* Defaults to true for Supabase buckets, not applicable for custom sources.
|
|
652
|
+
*
|
|
653
|
+
* @param config - The attachment configuration
|
|
654
|
+
* @returns true if signed URLs should be used
|
|
681
655
|
*/
|
|
682
|
-
|
|
683
|
-
platform: PlatformAdapter;
|
|
684
|
-
remoteStorage: AttachmentStorageAdapter;
|
|
685
|
-
/** Attachment source configuration with reactive watchIds callback */
|
|
686
|
-
source: AttachmentSourceConfig;
|
|
687
|
-
uploadHandler?: UploadHandler;
|
|
688
|
-
uploadConfig?: Partial<UploadConfig>;
|
|
689
|
-
/** Download configuration for concurrency tuning */
|
|
690
|
-
downloadConfig?: Partial<DownloadConfig>;
|
|
691
|
-
onUploadComplete?: (record: PolAttachmentRecord) => Promise<void>;
|
|
692
|
-
onUploadFailed?: (record: PolAttachmentRecord, error: Error) => void;
|
|
693
|
-
compression?: Partial<CompressionConfig>;
|
|
694
|
-
cache?: Partial<CacheConfig>;
|
|
695
|
-
}
|
|
656
|
+
declare function isSignedUrlSource(config: AttachmentConfig | AttachmentSourceConfig): boolean;
|
|
696
657
|
/**
|
|
697
|
-
*
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
private readonly uploadConfig;
|
|
706
|
-
private readonly downloadConfig;
|
|
707
|
-
private readonly compressionConfig;
|
|
708
|
-
private readonly cacheConfig;
|
|
709
|
-
private _uploadState;
|
|
710
|
-
private _disposed;
|
|
711
|
-
private _initialized;
|
|
712
|
-
private _watchGeneration;
|
|
713
|
-
private _watchIdsCleanup;
|
|
714
|
-
private _watchMutex;
|
|
715
|
-
private _networkListenerCleanup;
|
|
716
|
-
private _wasConnected;
|
|
717
|
-
private _progressCallbacks;
|
|
718
|
-
private _lastNotifyTime;
|
|
719
|
-
private _notifyTimer;
|
|
720
|
-
private _cachedStats;
|
|
721
|
-
private _cachedStatsTimestamp;
|
|
722
|
-
constructor(options: PolAttachmentQueueOptions);
|
|
723
|
-
watchUploads(): void;
|
|
724
|
-
/**
|
|
725
|
-
* Override parent's expireCache to disable count-based cache eviction.
|
|
726
|
-
*
|
|
727
|
-
* The parent implementation deletes SYNCED/ARCHIVED records beyond cacheLimit,
|
|
728
|
-
* which caused a bug where downloads would reset because:
|
|
729
|
-
* 1. expireCache deleted records beyond cacheLimit (default 100)
|
|
730
|
-
* 2. watchIds still emitted those IDs
|
|
731
|
-
* 3. They got re-created as QUEUED_DOWNLOAD
|
|
732
|
-
* 4. Downloads restarted in an infinite loop
|
|
733
|
-
*
|
|
734
|
-
* Our implementation uses size-based cache limits only (via clearCache/cacheConfig.maxSize).
|
|
735
|
-
*/
|
|
736
|
-
expireCache(): Promise<void>;
|
|
737
|
-
/**
|
|
738
|
-
* Override parent's watchDownloads to use concurrent downloads.
|
|
739
|
-
*
|
|
740
|
-
* The parent implementation downloads one file at a time.
|
|
741
|
-
* This override processes downloads in parallel batches for faster sync.
|
|
742
|
-
*/
|
|
743
|
-
watchDownloads(): void;
|
|
744
|
-
/**
|
|
745
|
-
* Process pending downloads with concurrency control.
|
|
746
|
-
* Downloads multiple files in parallel based on downloadConfig.concurrency.
|
|
747
|
-
* Enforces cache size limits after each batch completes.
|
|
748
|
-
*/
|
|
749
|
-
private _downloadRecordsConcurrent;
|
|
750
|
-
uploadAttachment(record: {
|
|
751
|
-
id: string;
|
|
752
|
-
}): Promise<boolean>;
|
|
753
|
-
watchAttachmentIds(): Promise<void>;
|
|
754
|
-
saveToQueue(record: Omit<AttachmentRecord$1, 'timestamp'>): Promise<AttachmentRecord$1>;
|
|
755
|
-
onAttachmentIdsChange(onUpdate: (ids: string[]) => void): void;
|
|
756
|
-
downloadRecord(record: AttachmentRecord$1): Promise<boolean>;
|
|
757
|
-
newAttachmentRecord(record?: Partial<AttachmentRecord$1>): Promise<AttachmentRecord$1>;
|
|
758
|
-
init(): Promise<void>;
|
|
759
|
-
/**
|
|
760
|
-
* Dispose the attachment queue and clean up resources.
|
|
761
|
-
* This method is synchronous to ensure callers don't need to await it,
|
|
762
|
-
* but it fires off async cleanup in the background for graceful shutdown.
|
|
763
|
-
*/
|
|
764
|
-
dispose(): void;
|
|
765
|
-
/**
|
|
766
|
-
* Async cleanup that runs in the background after dispose().
|
|
767
|
-
* Waits for active upload promises to settle gracefully.
|
|
768
|
-
*/
|
|
769
|
-
private _asyncCleanup;
|
|
770
|
-
queueUpload(options: {
|
|
771
|
-
storagePath: string;
|
|
772
|
-
sourceUri: string;
|
|
773
|
-
filename: string;
|
|
774
|
-
mediaType: string;
|
|
775
|
-
bucketId?: string;
|
|
776
|
-
metadata?: Record<string, unknown>;
|
|
777
|
-
}): Promise<void>;
|
|
778
|
-
getPendingUploads(): Promise<PolAttachmentRecord[]>;
|
|
779
|
-
getSoonestRetryTime(): Promise<number | null>;
|
|
780
|
-
getFailedPermanentUploads(): Promise<PolAttachmentRecord[]>;
|
|
781
|
-
getStaleUploads(): Promise<PolAttachmentRecord[]>;
|
|
782
|
-
getSyncedUploadsWithPendingCallback(): Promise<PolAttachmentRecord[]>;
|
|
783
|
-
clearUploadCallback(id: string): Promise<void>;
|
|
784
|
-
retryUpload(id: string): Promise<void>;
|
|
785
|
-
/**
|
|
786
|
-
* Reset all uploads in QUEUED_UPLOAD state so they retry immediately.
|
|
787
|
-
* This clears retry counts and errors, allowing uploads to be retried fresh.
|
|
788
|
-
*
|
|
789
|
-
* @returns The number of uploads that were reset
|
|
790
|
-
*/
|
|
791
|
-
resetUploadRetries(): Promise<number>;
|
|
792
|
-
/**
|
|
793
|
-
* Trigger immediate retry of uploads WITHOUT resetting their retry count.
|
|
794
|
-
* This preserves backoff state for truly failing uploads while allowing
|
|
795
|
-
* uploads that were waiting for network to retry immediately.
|
|
796
|
-
*
|
|
797
|
-
* Only affects uploads that:
|
|
798
|
-
* - Are past their retry time (upload_next_retry_at <= now), OR
|
|
799
|
-
* - Have no retry time set (upload_next_retry_at IS NULL)
|
|
800
|
-
*
|
|
801
|
-
* @returns The number of uploads that will be retried
|
|
802
|
-
*/
|
|
803
|
-
retryUploads(): Promise<number>;
|
|
804
|
-
deleteUpload(id: string): Promise<void>;
|
|
805
|
-
/**
|
|
806
|
-
* Re-queue an upload for an orphaned attachment.
|
|
807
|
-
* Use this when a database record exists with a storagePath but the file was never uploaded.
|
|
808
|
-
*
|
|
809
|
-
* This handles the case where:
|
|
810
|
-
* - User took a photo and the database record was created with a storagePath
|
|
811
|
-
* - The attachment queue record was created but disappeared before upload completed
|
|
812
|
-
* - The photo shows locally but was never uploaded to storage
|
|
813
|
-
*
|
|
814
|
-
* @param options.storagePath - The storage path (e.g., "projectId/fileId.jpg")
|
|
815
|
-
* @param options.localFileUri - URI to the local file to upload
|
|
816
|
-
* @param options.mediaType - MIME type of the file
|
|
817
|
-
* @param options.bucketId - Optional bucket ID for multi-bucket setups
|
|
818
|
-
* @returns true if upload was queued, false if already exists in valid state
|
|
819
|
-
*/
|
|
820
|
-
requeueOrphanedUpload(options: {
|
|
821
|
-
storagePath: string;
|
|
822
|
-
localFileUri: string;
|
|
823
|
-
mediaType: string;
|
|
824
|
-
bucketId?: string;
|
|
825
|
-
}): Promise<boolean>;
|
|
826
|
-
getRecord(id: string): Promise<PolAttachmentRecord | null>;
|
|
827
|
-
getFailedUploads(): Promise<PolAttachmentRecord[]>;
|
|
828
|
-
retryFailedUpload(id: string): Promise<void>;
|
|
829
|
-
deleteFailedUpload(id: string): Promise<void>;
|
|
830
|
-
get activeUploads(): UploadStatus[];
|
|
831
|
-
pauseUploads(): void;
|
|
832
|
-
resumeUploads(): void;
|
|
833
|
-
clearCache(): Promise<void>;
|
|
834
|
-
cacheLocalFile(storagePath: string, sourceUri: string): Promise<void>;
|
|
835
|
-
getLocalUriForStoragePath(storagePath: string): Promise<string | null>;
|
|
836
|
-
/**
|
|
837
|
-
* Purge attachments by their IDs.
|
|
838
|
-
* Archives and deletes local files for the specified attachment IDs.
|
|
839
|
-
* Useful for edge cases where external code needs to force-remove attachments.
|
|
840
|
-
*
|
|
841
|
-
* @param ids - Array of attachment IDs to purge
|
|
842
|
-
*/
|
|
843
|
-
purgeAttachments(ids: string[]): Promise<void>;
|
|
844
|
-
onProgress(callback: (stats: AttachmentSyncStats) => void): () => void;
|
|
845
|
-
getStats(): Promise<AttachmentSyncStats>;
|
|
846
|
-
/**
|
|
847
|
-
* Repair attachment sizes for synced records that have size=0.
|
|
848
|
-
* This backfills sizes from the actual file system for existing downloads.
|
|
849
|
-
* @returns Number of records repaired
|
|
850
|
-
*/
|
|
851
|
-
repairAttachmentSizes(): Promise<number>;
|
|
852
|
-
private _getDownloadManagerDeps;
|
|
853
|
-
private _getUploadManagerDeps;
|
|
854
|
-
private _getCacheManagerDeps;
|
|
855
|
-
private _startUploadProcessing;
|
|
856
|
-
private _createTableIfNotExists;
|
|
857
|
-
private _migrateUploadColumns;
|
|
858
|
-
private _invalidateStatsCache;
|
|
859
|
-
private _getStatus;
|
|
860
|
-
private _notify;
|
|
861
|
-
}
|
|
658
|
+
* Check if the attachment source is a custom (non-Supabase) source.
|
|
659
|
+
*
|
|
660
|
+
* @param config - The attachment configuration
|
|
661
|
+
* @returns true if this is a custom source
|
|
662
|
+
*/
|
|
663
|
+
declare function isCustomSource(config: AttachmentConfig | AttachmentSourceConfig): config is AttachmentConfig & {
|
|
664
|
+
source: CustomAttachmentSource;
|
|
665
|
+
};
|
|
862
666
|
/**
|
|
863
|
-
*
|
|
667
|
+
* Get the URL resolver function for a custom source.
|
|
668
|
+
*
|
|
669
|
+
* @param config - The attachment configuration
|
|
670
|
+
* @returns The getUrl function, or undefined if not a custom source
|
|
864
671
|
*/
|
|
865
|
-
|
|
866
|
-
/** Remote storage adapter for downloading/uploading files */
|
|
867
|
-
remoteStorage: AttachmentStorageAdapter;
|
|
868
|
-
/** Upload handler for processing uploads */
|
|
869
|
-
uploadHandler?: UploadHandler;
|
|
870
|
-
/** Upload configuration */
|
|
871
|
-
uploadConfig?: Partial<UploadConfig>;
|
|
872
|
-
/** Download configuration (concurrency, timeout) */
|
|
873
|
-
downloadConfig?: Partial<DownloadConfig>;
|
|
874
|
-
/** Compression configuration */
|
|
875
|
-
compression?: Partial<CompressionConfig>;
|
|
876
|
-
/** Cache configuration */
|
|
877
|
-
cache?: Partial<CacheConfig>;
|
|
878
|
-
}
|
|
879
|
-
declare function createPolAttachmentQueue(powersync: AbstractPowerSyncDatabase, platform: PlatformAdapter, config: CreateAttachmentQueueOptions): PolAttachmentQueue;
|
|
672
|
+
declare function getCustomUrlResolver(config: AttachmentConfig | AttachmentSourceConfig): ((path: string) => Promise<string> | string) | undefined;
|
|
880
673
|
|
|
881
|
-
export { type
|
|
674
|
+
export { type AttachmentSource as A, resolveBucketFromConfig as B, type CustomAttachmentSource as C, DEFAULT_COMPRESSION_CONFIG as D, type EvictRow as E, isSignedUrlSource as F, isCustomSource as G, getCustomUrlResolver as H, type IdRow as I, PolAttachmentState as P, type SimpleAttachmentConfig as S, type UploadConfig as U, type WatchConfig as W, type PolAttachmentRecord as a, type SupabaseBucketSource as b, type AttachmentSourceConfig as c, type AttachmentConfig as d, type AttachmentStorageAdapter as e, type CompressionConfig as f, DEFAULT_UPLOAD_CONFIG as g, type UploadHandler as h, type DownloadConfig as i, DEFAULT_DOWNLOAD_CONFIG as j, type CacheConfig as k, DEFAULT_CACHE_CONFIG as l, CACHE_SIZE_PRESETS as m, type CacheSizePreset as n, type CacheSizeValue as o, formatCacheSize as p, type DownloadPhase as q, type DownloadStatus as r, type UploadPhase as s, type UploadStatus as t, type AttachmentSyncStatus as u, type AttachmentSyncStats as v, type AttachmentStatsRow as w, type CacheFileRow as x, type CachedSizeRow as y, type AttachmentRecord as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pol-studios/powersync",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.32",
|
|
4
4
|
"description": "Enterprise PowerSync integration for offline-first applications",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -52,8 +52,18 @@
|
|
|
52
52
|
"types": "./dist/attachments/index.d.ts"
|
|
53
53
|
},
|
|
54
54
|
"./provider": {
|
|
55
|
-
"
|
|
56
|
-
|
|
55
|
+
"react-native": {
|
|
56
|
+
"import": "./dist/provider/index.native.js",
|
|
57
|
+
"types": "./dist/provider/index.native.d.ts"
|
|
58
|
+
},
|
|
59
|
+
"browser": {
|
|
60
|
+
"import": "./dist/provider/index.web.js",
|
|
61
|
+
"types": "./dist/provider/index.web.d.ts"
|
|
62
|
+
},
|
|
63
|
+
"default": {
|
|
64
|
+
"import": "./dist/provider/index.js",
|
|
65
|
+
"types": "./dist/provider/index.d.ts"
|
|
66
|
+
}
|
|
57
67
|
},
|
|
58
68
|
"./sync": {
|
|
59
69
|
"import": "./dist/sync/index.js",
|
|
@@ -132,6 +142,10 @@
|
|
|
132
142
|
"./generator": {
|
|
133
143
|
"import": "./dist/generator/index.js",
|
|
134
144
|
"types": "./dist/generator/index.d.ts"
|
|
145
|
+
},
|
|
146
|
+
"./config": {
|
|
147
|
+
"import": "./dist/config/index.js",
|
|
148
|
+
"types": "./dist/config/index.d.ts"
|
|
135
149
|
}
|
|
136
150
|
},
|
|
137
151
|
"files": [
|
|
@@ -141,7 +155,7 @@
|
|
|
141
155
|
"commander": "^12.0.0",
|
|
142
156
|
"jiti": "^2.4.0",
|
|
143
157
|
"picocolors": "^1.0.0",
|
|
144
|
-
"@pol-studios/db": "1.0.
|
|
158
|
+
"@pol-studios/db": "1.0.61"
|
|
145
159
|
},
|
|
146
160
|
"peerDependencies": {
|
|
147
161
|
"@powersync/react-native": ">=1.0.8",
|