@pol-studios/powersync 1.0.25 → 1.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +0 -1
  2. package/dist/{CacheSettingsManager-uz-kbnRH.d.ts → CacheSettingsManager-0H_7thHW.d.ts} +21 -3
  3. package/dist/attachments/index.d.ts +30 -30
  4. package/dist/attachments/index.js +13 -4
  5. package/dist/{background-sync-ChCXW-EV.d.ts → background-sync-BujnI3IR.d.ts} +1 -1
  6. package/dist/{chunk-55DKCJV4.js → chunk-2RDWLXJW.js} +408 -78
  7. package/dist/chunk-2RDWLXJW.js.map +1 -0
  8. package/dist/{chunk-P4HZA6ZT.js → chunk-4665ZSE5.js} +2 -2
  9. package/dist/chunk-4665ZSE5.js.map +1 -0
  10. package/dist/{chunk-XOY2CJ67.js → chunk-4F5B5CZ7.js} +3 -3
  11. package/dist/chunk-5WRI5ZAA.js +31 -0
  12. package/dist/{chunk-BGBQYQV3.js → chunk-65A3SYJZ.js} +193 -299
  13. package/dist/chunk-65A3SYJZ.js.map +1 -0
  14. package/dist/chunk-6SZ64KCZ.js +755 -0
  15. package/dist/chunk-6SZ64KCZ.js.map +1 -0
  16. package/dist/{chunk-YSTEESEG.js → chunk-74TBHWJ4.js} +122 -11
  17. package/dist/chunk-74TBHWJ4.js.map +1 -0
  18. package/dist/chunk-ANXWYQEJ.js +1 -0
  19. package/dist/chunk-ANXWYQEJ.js.map +1 -0
  20. package/dist/{chunk-CAB26E6F.js → chunk-C4J4MLER.js} +29 -24
  21. package/dist/chunk-C4J4MLER.js.map +1 -0
  22. package/dist/{chunk-C5ODS3XH.js → chunk-EOW7JK7Q.js} +9 -16
  23. package/dist/chunk-EOW7JK7Q.js.map +1 -0
  24. package/dist/chunk-HRAVPIAZ.js +220 -0
  25. package/dist/chunk-HRAVPIAZ.js.map +1 -0
  26. package/dist/{chunk-XAEII4ZX.js → chunk-NUGQOTEM.js} +32 -4
  27. package/dist/chunk-NUGQOTEM.js.map +1 -0
  28. package/dist/chunk-OGUFUZSY.js +5415 -0
  29. package/dist/chunk-OGUFUZSY.js.map +1 -0
  30. package/dist/{chunk-VB737IVN.js → chunk-P4D6BQ4X.js} +328 -706
  31. package/dist/chunk-P4D6BQ4X.js.map +1 -0
  32. package/dist/{chunk-CACKC6XG.js → chunk-PGEDE6IM.js} +136 -89
  33. package/dist/chunk-PGEDE6IM.js.map +1 -0
  34. package/dist/{chunk-A4IBBWGO.js → chunk-RALHHPTU.js} +1 -1
  35. package/dist/chunk-RIDSPLE5.js +42 -0
  36. package/dist/chunk-RIDSPLE5.js.map +1 -0
  37. package/dist/{chunk-Z6VOBGTU.js → chunk-UOMHWUHV.js} +2 -12
  38. package/dist/chunk-UOMHWUHV.js.map +1 -0
  39. package/dist/{chunk-WGHNIAF7.js → chunk-YONQYTVH.js} +2 -2
  40. package/dist/chunk-ZAN22NGL.js +13 -0
  41. package/dist/chunk-ZAN22NGL.js.map +1 -0
  42. package/dist/config/index.d.ts +200 -0
  43. package/dist/config/index.js +23 -0
  44. package/dist/config/index.js.map +1 -0
  45. package/dist/connector/index.d.ts +23 -5
  46. package/dist/connector/index.js +4 -2
  47. package/dist/core/index.d.ts +2 -2
  48. package/dist/core/index.js +1 -0
  49. package/dist/error/index.js +1 -0
  50. package/dist/generator/index.js +2 -0
  51. package/dist/generator/index.js.map +1 -1
  52. package/dist/index.d.ts +19 -16
  53. package/dist/index.js +88 -46
  54. package/dist/index.native.d.ts +18 -14
  55. package/dist/index.native.js +93 -44
  56. package/dist/index.web.d.ts +17 -14
  57. package/dist/index.web.js +88 -46
  58. package/dist/maintenance/index.d.ts +2 -2
  59. package/dist/maintenance/index.js +3 -2
  60. package/dist/platform/index.d.ts +1 -1
  61. package/dist/platform/index.js +2 -0
  62. package/dist/platform/index.js.map +1 -1
  63. package/dist/platform/index.native.d.ts +1 -1
  64. package/dist/platform/index.native.js +1 -0
  65. package/dist/platform/index.web.d.ts +1 -1
  66. package/dist/platform/index.web.js +1 -0
  67. package/dist/pol-attachment-queue-DqBvLAEY.d.ts +255 -0
  68. package/dist/provider/index.d.ts +319 -124
  69. package/dist/provider/index.js +21 -16
  70. package/dist/provider/index.native.d.ts +108 -0
  71. package/dist/provider/index.native.js +121 -0
  72. package/dist/provider/index.native.js.map +1 -0
  73. package/dist/provider/index.web.d.ts +16 -0
  74. package/dist/provider/index.web.js +112 -0
  75. package/dist/provider/index.web.js.map +1 -0
  76. package/dist/react/index.d.ts +16 -65
  77. package/dist/react/index.js +2 -9
  78. package/dist/storage/index.d.ts +5 -4
  79. package/dist/storage/index.js +12 -9
  80. package/dist/storage/index.native.d.ts +5 -4
  81. package/dist/storage/index.native.js +8 -5
  82. package/dist/storage/index.web.d.ts +5 -4
  83. package/dist/storage/index.web.js +11 -8
  84. package/dist/storage/upload/index.d.ts +4 -3
  85. package/dist/storage/upload/index.js +4 -2
  86. package/dist/storage/upload/index.native.d.ts +4 -3
  87. package/dist/storage/upload/index.native.js +4 -2
  88. package/dist/storage/upload/index.web.d.ts +2 -1
  89. package/dist/storage/upload/index.web.js +4 -2
  90. package/dist/{supabase-connector-D2oIl2t8.d.ts → supabase-connector-HMxBA9Kg.d.ts} +23 -25
  91. package/dist/sync/index.d.ts +183 -11
  92. package/dist/sync/index.js +13 -3
  93. package/dist/{types-CyvBaAl8.d.ts → types-6QHGELuY.d.ts} +4 -1
  94. package/dist/{types-CDqWh56B.d.ts → types-B9MptP7E.d.ts} +13 -1
  95. package/dist/types-BhAEsJj-.d.ts +330 -0
  96. package/dist/{types-D0WcHrq6.d.ts → types-CGMibJKD.d.ts} +8 -0
  97. package/dist/{types-DiBvmGEi.d.ts → types-DqJnP50o.d.ts} +22 -24
  98. package/dist/{pol-attachment-queue-BE2HU3Us.d.ts → types-JCEhw2Lf.d.ts} +139 -346
  99. package/package.json +18 -4
  100. package/dist/chunk-24RDMMCL.js +0 -44
  101. package/dist/chunk-24RDMMCL.js.map +0 -1
  102. package/dist/chunk-55DKCJV4.js.map +0 -1
  103. package/dist/chunk-654ERHA7.js +0 -1
  104. package/dist/chunk-BGBQYQV3.js.map +0 -1
  105. package/dist/chunk-C5ODS3XH.js.map +0 -1
  106. package/dist/chunk-CAB26E6F.js.map +0 -1
  107. package/dist/chunk-CACKC6XG.js.map +0 -1
  108. package/dist/chunk-P4HZA6ZT.js.map +0 -1
  109. package/dist/chunk-TIFL2KWE.js +0 -358
  110. package/dist/chunk-TIFL2KWE.js.map +0 -1
  111. package/dist/chunk-VB737IVN.js.map +0 -1
  112. package/dist/chunk-XAEII4ZX.js.map +0 -1
  113. package/dist/chunk-YSTEESEG.js.map +0 -1
  114. package/dist/chunk-Z6VOBGTU.js.map +0 -1
  115. /package/dist/{chunk-XOY2CJ67.js.map → chunk-4F5B5CZ7.js.map} +0 -0
  116. /package/dist/{chunk-654ERHA7.js.map → chunk-5WRI5ZAA.js.map} +0 -0
  117. /package/dist/{chunk-A4IBBWGO.js.map → chunk-RALHHPTU.js.map} +0 -0
  118. /package/dist/{chunk-WGHNIAF7.js.map → chunk-YONQYTVH.js.map} +0 -0
@@ -17,8 +17,8 @@ var PolStorageAdapter = class {
17
17
  this.remoteStorage = options.remoteStorage;
18
18
  this.attachmentDirectoryName = options.attachmentDirectoryName ?? "attachments";
19
19
  this.logger = options.logger;
20
- const cacheDir = this.platform.fileSystem.getCacheDirectory();
21
- this.userStorageDirectory = cacheDir.endsWith("/") ? `${cacheDir}${this.attachmentDirectoryName}/` : `${cacheDir}/${this.attachmentDirectoryName}/`;
20
+ const documentsDir = this.platform.fileSystem.getDocumentsDirectory();
21
+ this.userStorageDirectory = documentsDir.endsWith("/") ? `${documentsDir}${this.attachmentDirectoryName}/` : `${documentsDir}/${this.attachmentDirectoryName}/`;
22
22
  }
23
23
  // ─── Remote Operations ──────────────────────────────────────────────────────
24
24
  /**
@@ -31,6 +31,23 @@ var PolStorageAdapter = class {
31
31
  const base64 = this._arrayBufferToBase64(data);
32
32
  await this.remoteStorage.uploadFile(filePath, base64);
33
33
  }
34
+ /**
35
+ * Convert base64 string to Blob with error handling.
36
+ * Throws a descriptive error if the base64 data is malformed.
37
+ */
38
+ _base64ToBlob(base64String, filePath) {
39
+ try {
40
+ const binaryString = atob(base64String);
41
+ const bytes = new Uint8Array(binaryString.length);
42
+ for (let i = 0; i < binaryString.length; i++) {
43
+ bytes[i] = binaryString.charCodeAt(i);
44
+ }
45
+ return new Blob([bytes]);
46
+ } catch (error) {
47
+ const message = error instanceof Error ? error.message : String(error);
48
+ throw new Error(`[PolStorageAdapter] Failed to decode base64 for file "${filePath}": ${message}. The file data may be corrupted or incorrectly encoded.`);
49
+ }
50
+ }
34
51
  /**
35
52
  * Download a file from remote storage.
36
53
  *
@@ -47,19 +64,9 @@ var PolStorageAdapter = class {
47
64
  if (result.startsWith("file://")) {
48
65
  this.logger?.warn(`[PolStorageAdapter] PERFORMANCE WARNING: file:// path hit in downloadFile() - reading entire file into memory. This should be avoided; use direct file copy instead. File: ${filePath}`);
49
66
  const base64Content = await this.platform.fileSystem.readFile(result, "base64");
50
- const binaryString2 = atob(base64Content);
51
- const bytes2 = new Uint8Array(binaryString2.length);
52
- for (let i = 0; i < binaryString2.length; i++) {
53
- bytes2[i] = binaryString2.charCodeAt(i);
54
- }
55
- return new Blob([bytes2]);
67
+ return this._base64ToBlob(base64Content, filePath);
56
68
  }
57
- const binaryString = atob(result);
58
- const bytes = new Uint8Array(binaryString.length);
59
- for (let i = 0; i < binaryString.length; i++) {
60
- bytes[i] = binaryString.charCodeAt(i);
61
- }
62
- return new Blob([bytes]);
69
+ return this._base64ToBlob(result, filePath);
63
70
  }
64
71
  return result;
65
72
  }
@@ -120,7 +127,7 @@ var PolStorageAdapter = class {
120
127
  }
121
128
  /**
122
129
  * Get the user's storage directory for attachments.
123
- * Returns the cache directory path ending with '/'.
130
+ * Returns the documents directory path ending with '/'.
124
131
  */
125
132
  getUserStorageDirectory() {
126
133
  return this.userStorageDirectory;
@@ -141,12 +148,17 @@ var PolStorageAdapter = class {
141
148
  return btoa(chunks.join(""));
142
149
  }
143
150
  _base64ToArrayBuffer(base64) {
144
- const binaryString = atob(base64);
145
- const bytes = new Uint8Array(binaryString.length);
146
- for (let i = 0; i < binaryString.length; i++) {
147
- bytes[i] = binaryString.charCodeAt(i);
151
+ try {
152
+ const binaryString = atob(base64);
153
+ const bytes = new Uint8Array(binaryString.length);
154
+ for (let i = 0; i < binaryString.length; i++) {
155
+ bytes[i] = binaryString.charCodeAt(i);
156
+ }
157
+ return bytes.buffer;
158
+ } catch (error) {
159
+ const message = error instanceof Error ? error.message : String(error);
160
+ throw new Error(`[PolStorageAdapter] Failed to decode base64 data: ${message}. The data may be corrupted or incorrectly encoded.`);
148
161
  }
149
- return bytes.buffer;
150
162
  }
151
163
  };
152
164
 
@@ -161,7 +173,6 @@ var PolAttachmentState = /* @__PURE__ */ ((PolAttachmentState2) => {
161
173
  PolAttachmentState2[PolAttachmentState2["SYNCED"] = 3] = "SYNCED";
162
174
  PolAttachmentState2[PolAttachmentState2["ARCHIVED"] = 4] = "ARCHIVED";
163
175
  PolAttachmentState2[PolAttachmentState2["FAILED_PERMANENT"] = 5] = "FAILED_PERMANENT";
164
- PolAttachmentState2[PolAttachmentState2["DOWNLOAD_SKIPPED"] = 6] = "DOWNLOAD_SKIPPED";
165
176
  return PolAttachmentState2;
166
177
  })(PolAttachmentState || {});
167
178
  var DEFAULT_COMPRESSION_CONFIG = {
@@ -221,6 +232,27 @@ function formatCacheSize(bytes) {
221
232
  }
222
233
  return `${bytes} bytes`;
223
234
  }
235
+ function resolveBucketFromConfig(config) {
236
+ if (config.source && config.source.type === "supabase-bucket") {
237
+ return config.source.bucket;
238
+ }
239
+ return void 0;
240
+ }
241
+ function isSignedUrlSource(config) {
242
+ if (config.source && config.source.type === "supabase-bucket") {
243
+ return config.source.signed !== false;
244
+ }
245
+ return true;
246
+ }
247
+ function isCustomSource(config) {
248
+ return config.source?.type === "custom";
249
+ }
250
+ function getCustomUrlResolver(config) {
251
+ if (config.source?.type === "custom") {
252
+ return config.source.getUrl;
253
+ }
254
+ return void 0;
255
+ }
224
256
 
225
257
  // src/attachments/state-machine.ts
226
258
  import { AttachmentState as AttachmentState2 } from "@powersync/attachments";
@@ -482,17 +514,21 @@ async function downloadRecord(deps, record) {
482
514
  deps.notify(true);
483
515
  return true;
484
516
  } catch (e) {
517
+ const errorMessage = e instanceof Error ? e.message : String(e);
518
+ logger.warn(`[DownloadManager] Download failed for "${record.id}": ${errorMessage}`);
485
519
  if (deps.onDownloadError) {
486
520
  const {
487
521
  retry
488
522
  } = await deps.onDownloadError(record, e);
489
523
  if (!retry) {
524
+ logger.info(`[DownloadManager] Archiving "${record.id}" after download error (retry=false)`);
490
525
  await deps.update({
491
526
  ...record,
492
527
  state: AttachmentState3.ARCHIVED
493
528
  });
494
529
  return true;
495
530
  }
531
+ logger.debug(`[DownloadManager] Will retry "${record.id}" on next cycle (retry=true)`);
496
532
  }
497
533
  }
498
534
  return false;
@@ -514,6 +550,9 @@ function isPermanentError(error) {
514
550
  }
515
551
  return false;
516
552
  }
553
+ function hasStatusCode(e) {
554
+ return e instanceof Error && ("status" in e || "statusCode" in e);
555
+ }
517
556
  function extractErrorCode(error) {
518
557
  const message = error.message;
519
558
  const patterns = [
@@ -532,8 +571,13 @@ function extractErrorCode(error) {
532
571
  return match[1];
533
572
  }
534
573
  }
535
- if ("status" in error && typeof error.status === "number") {
536
- return String(error.status);
574
+ if (hasStatusCode(error)) {
575
+ if (typeof error.status === "number") {
576
+ return String(error.status);
577
+ }
578
+ if (typeof error.statusCode === "string") {
579
+ return error.statusCode;
580
+ }
537
581
  }
538
582
  return void 0;
539
583
  }
@@ -1028,20 +1072,22 @@ async function getLocalUriForStoragePath(deps, storagePath, storage) {
1028
1072
  return null;
1029
1073
  }
1030
1074
  } catch (e) {
1031
- logger.warn(`[CacheManager] Failed to verify file exists: ${storagePath}`, e);
1075
+ logger.warn(`[CacheManager] Failed to verify file exists, returning null: ${storagePath}`, e);
1076
+ return null;
1032
1077
  }
1033
1078
  return uri;
1034
1079
  }
1035
1080
  async function copyToManagedCache(platform, logger, sourceUri, storagePath) {
1036
1081
  const localPath = storagePath.replace(/[^a-zA-Z0-9._-]/g, "_");
1037
- const cacheDir = platform.fileSystem.getCacheDirectory();
1038
- const targetUri = `${cacheDir}upload_queue/${localPath}`;
1082
+ const docsDir = platform.fileSystem.getDocumentsDirectory();
1083
+ const basePath = docsDir.endsWith("/") ? docsDir : `${docsDir}/`;
1084
+ const targetUri = `${basePath}upload_queue/${localPath}`;
1039
1085
  const dir = targetUri.substring(0, targetUri.lastIndexOf("/"));
1040
1086
  await platform.fileSystem.makeDirectory(dir, {
1041
1087
  intermediates: true
1042
1088
  });
1043
1089
  await platform.fileSystem.copyFile(sourceUri, targetUri);
1044
- logger.info(`[CacheManager] Copied to managed cache: ${targetUri}`);
1090
+ logger.info(`[CacheManager] Copied to documents for upload: ${targetUri}`);
1045
1091
  return targetUri;
1046
1092
  }
1047
1093
  function createCacheManagerDeps(partial) {
@@ -1064,6 +1110,7 @@ var PolAttachmentQueue = class extends AbstractAttachmentQueue2 {
1064
1110
  polLogger;
1065
1111
  source;
1066
1112
  remoteStorage;
1113
+ supabaseClient;
1067
1114
  uploadHandler;
1068
1115
  uploadConfig;
1069
1116
  downloadConfig;
@@ -1075,10 +1122,12 @@ var PolAttachmentQueue = class extends AbstractAttachmentQueue2 {
1075
1122
  _disposed = false;
1076
1123
  _initialized = false;
1077
1124
  _watchGeneration = 0;
1078
- _watchIdsCleanup = void 0;
1125
+ _watchCleanup = void 0;
1079
1126
  _watchMutex = Promise.resolve();
1080
1127
  _networkListenerCleanup = void 0;
1081
1128
  _wasConnected = null;
1129
+ _cacheCapacityRetries = 0;
1130
+ // Track cache capacity retries to prevent infinite loops
1082
1131
  // Notification state
1083
1132
  _progressCallbacks = /* @__PURE__ */ new Set();
1084
1133
  _lastNotifyTime = 0;
@@ -1103,6 +1152,7 @@ var PolAttachmentQueue = class extends AbstractAttachmentQueue2 {
1103
1152
  this.polLogger = options.platform.logger;
1104
1153
  this.source = options.source;
1105
1154
  this.remoteStorage = options.remoteStorage;
1155
+ this.supabaseClient = options.supabaseClient;
1106
1156
  this.uploadHandler = options.uploadHandler;
1107
1157
  this.uploadConfig = {
1108
1158
  ...DEFAULT_UPLOAD_CONFIG,
@@ -1132,7 +1182,7 @@ var PolAttachmentQueue = class extends AbstractAttachmentQueue2 {
1132
1182
  * The parent implementation deletes SYNCED/ARCHIVED records beyond cacheLimit,
1133
1183
  * which caused a bug where downloads would reset because:
1134
1184
  * 1. expireCache deleted records beyond cacheLimit (default 100)
1135
- * 2. watchIds still emitted those IDs
1185
+ * 2. watchPaths still emitted those IDs
1136
1186
  * 3. They got re-created as QUEUED_DOWNLOAD
1137
1187
  * 4. Downloads restarted in an infinite loop
1138
1188
  *
@@ -1172,7 +1222,20 @@ var PolAttachmentQueue = class extends AbstractAttachmentQueue2 {
1172
1222
  if (hasMaxSize) {
1173
1223
  const nearCapacity = await isCacheNearCapacity(this._getCacheManagerDeps());
1174
1224
  if (nearCapacity) {
1175
- this.polLogger?.warn?.(`[PolAttachmentQueue] Cache at ${Math.round(this.cacheConfig.downloadStopThreshold * 100)}% capacity, pausing downloads`);
1225
+ this._cacheCapacityRetries++;
1226
+ const maxRetries = 3;
1227
+ if (this._cacheCapacityRetries >= maxRetries) {
1228
+ this.polLogger?.warn?.(`[PolAttachmentQueue] Cache at capacity, max retries (${maxRetries}) reached. ${this.downloadQueue.size} items pending, waiting for next watchPaths emission.`);
1229
+ this._cacheCapacityRetries = 0;
1230
+ } else {
1231
+ const delay = 5e3 * this._cacheCapacityRetries;
1232
+ this.polLogger?.warn?.(`[PolAttachmentQueue] Cache at ${Math.round(this.cacheConfig.downloadStopThreshold * 100)}% capacity. ${this.downloadQueue.size} items pending, retry ${this._cacheCapacityRetries}/${maxRetries} in ${delay / 1e3}s.`);
1233
+ setTimeout(() => {
1234
+ if (!this._disposed && this.downloadQueue.size > 0) {
1235
+ this._downloadRecordsConcurrent();
1236
+ }
1237
+ }, delay);
1238
+ }
1176
1239
  break;
1177
1240
  }
1178
1241
  }
@@ -1191,6 +1254,13 @@ var PolAttachmentQueue = class extends AbstractAttachmentQueue2 {
1191
1254
  }
1192
1255
  } catch (err) {
1193
1256
  this.polLogger?.warn?.(`[PolAttachmentQueue] Download failed for ${id}:`, err);
1257
+ const error = err instanceof Error ? err : new Error(String(err));
1258
+ if (isPermanentError(error)) {
1259
+ this.polLogger?.info?.(`[PolAttachmentQueue] Not retrying ${id} (permanent error)`);
1260
+ } else {
1261
+ this.polLogger?.debug?.(`[PolAttachmentQueue] Re-queuing ${id} for retry (transient error)`);
1262
+ this.downloadQueue.add(id);
1263
+ }
1194
1264
  }
1195
1265
  });
1196
1266
  await Promise.all(downloadPromises);
@@ -1207,45 +1277,23 @@ var PolAttachmentQueue = class extends AbstractAttachmentQueue2 {
1207
1277
  }
1208
1278
  async watchAttachmentIds() {
1209
1279
  this.onAttachmentIdsChange(async (ids) => {
1210
- const generation = ++this._watchGeneration;
1211
- this.polLogger?.debug?.(`[PolAttachmentQueue] Received ${ids.length} attachment IDs from watch`);
1212
- let filteredIds = ids;
1213
- let skippedIds = [];
1214
- if (this.source.skipDownload && ids.length > 0) {
1215
- try {
1216
- const context = {
1217
- ids,
1218
- db: this.powersync
1219
- };
1220
- skippedIds = await this.source.skipDownload(context);
1221
- if (generation !== this._watchGeneration) {
1222
- this.polLogger?.debug?.("[PolAttachmentQueue] Stale watch callback, ignoring");
1223
- return;
1224
- }
1225
- const skipSet = new Set(skippedIds);
1226
- filteredIds = ids.filter((id) => !skipSet.has(id));
1227
- this.polLogger?.info?.(`[PolAttachmentQueue] Pre-filtered: ${ids.length} total, ${skippedIds.length} skipped, ${filteredIds.length} to sync`);
1228
- } catch (error) {
1229
- this.polLogger?.warn?.("[PolAttachmentQueue] skipDownload filter failed, using all IDs:", error);
1230
- filteredIds = ids;
1231
- skippedIds = [];
1232
- }
1233
- }
1234
- this.polLogger?.debug?.(`[PolAttachmentQueue] Syncing attachment IDs: [${filteredIds.length} items]`);
1280
+ this.polLogger?.debug?.(`[PolAttachmentQueue] Received ${ids.length} attachment paths from watch`);
1281
+ this.polLogger?.debug?.(`[PolAttachmentQueue] Syncing attachment paths: [${ids.length} items]`);
1282
+ this._cacheCapacityRetries = 0;
1235
1283
  if (this.initialSync) {
1236
1284
  this.initialSync = false;
1237
- if (filteredIds.length > 0) {
1238
- const placeholders = filteredIds.map(() => "?").join(",");
1285
+ if (ids.length > 0) {
1286
+ const placeholders = ids.map(() => "?").join(",");
1239
1287
  await this.powersync.execute(`UPDATE ${this.table}
1240
1288
  SET state = ${AttachmentState6.QUEUED_SYNC}
1241
1289
  WHERE state < ${AttachmentState6.SYNCED}
1242
- AND state NOT IN (${AttachmentState6.QUEUED_UPLOAD}, ${5 /* FAILED_PERMANENT */}, ${6 /* DOWNLOAD_SKIPPED */})
1243
- AND id IN (${placeholders})`, filteredIds);
1290
+ AND state NOT IN (${AttachmentState6.QUEUED_UPLOAD}, ${5 /* FAILED_PERMANENT */})
1291
+ AND id IN (${placeholders})`, ids);
1244
1292
  }
1245
1293
  }
1246
1294
  const attachmentsInDatabase = await this.powersync.getAll(`SELECT * FROM ${this.table} WHERE state < ${AttachmentState6.ARCHIVED}`);
1247
1295
  const attachmentsMap = new Map(attachmentsInDatabase.map((r) => [r.id, r]));
1248
- for (const id of filteredIds) {
1296
+ for (const id of ids) {
1249
1297
  const record = attachmentsMap.get(id);
1250
1298
  if (!record) {
1251
1299
  const newRecord = await this.newAttachmentRecord({
@@ -1257,7 +1305,6 @@ var PolAttachmentQueue = class extends AbstractAttachmentQueue2 {
1257
1305
  }
1258
1306
  if (PROTECTED_UPLOAD_STATES.has(record.state)) continue;
1259
1307
  if (record.upload_source_uri) continue;
1260
- if (record.state === 6 /* DOWNLOAD_SKIPPED */) continue;
1261
1308
  if (record.local_uri == null || !await this.storage.fileExists(this.getLocalUri(record.local_uri))) {
1262
1309
  await this.update({
1263
1310
  ...record,
@@ -1265,22 +1312,14 @@ var PolAttachmentQueue = class extends AbstractAttachmentQueue2 {
1265
1312
  });
1266
1313
  }
1267
1314
  }
1268
- if (skippedIds.length > 0) {
1269
- const placeholders = skippedIds.map(() => "?").join(",");
1270
- await this.powersync.execute(`UPDATE ${this.table}
1271
- SET state = ${6 /* DOWNLOAD_SKIPPED */}
1272
- WHERE id IN (${placeholders})
1273
- AND state NOT IN (${AttachmentState6.QUEUED_UPLOAD}, ${5 /* FAILED_PERMANENT */}, ${AttachmentState6.SYNCED})`, skippedIds);
1274
- }
1275
- const allValidIds = [.../* @__PURE__ */ new Set([...filteredIds, ...skippedIds])];
1276
- if (allValidIds.length > 0) {
1277
- const placeholders = allValidIds.map(() => "?").join(",");
1315
+ if (ids.length > 0) {
1316
+ const placeholders = ids.map(() => "?").join(",");
1278
1317
  await this.powersync.execute(`UPDATE ${this.table}
1279
1318
  SET state = ${AttachmentState6.ARCHIVED}
1280
1319
  WHERE state < ${AttachmentState6.ARCHIVED}
1281
1320
  AND state NOT IN (${AttachmentState6.QUEUED_UPLOAD}, ${5 /* FAILED_PERMANENT */})
1282
1321
  AND upload_source_uri IS NULL
1283
- AND id NOT IN (${placeholders})`, allValidIds);
1322
+ AND id NOT IN (${placeholders})`, ids);
1284
1323
  }
1285
1324
  this._invalidateStatsCache();
1286
1325
  this._notify(true);
@@ -1314,21 +1353,25 @@ var PolAttachmentQueue = class extends AbstractAttachmentQueue2 {
1314
1353
  onAttachmentIdsChange(onUpdate) {
1315
1354
  this._watchMutex = this._watchMutex.then(async () => {
1316
1355
  if (this._disposed) return;
1317
- if (this._watchIdsCleanup) {
1356
+ if (this._watchCleanup) {
1318
1357
  try {
1319
- this._watchIdsCleanup();
1358
+ this._watchCleanup();
1320
1359
  } catch (error) {
1321
1360
  this.polLogger?.warn?.("[PolAttachmentQueue] Watch cleanup failed:", error);
1322
1361
  }
1323
- this._watchIdsCleanup = void 0;
1362
+ this._watchCleanup = void 0;
1324
1363
  }
1325
1364
  try {
1326
- const cleanup = this.source.watchIds(this.powersync, onUpdate);
1365
+ if (!this.source.watchPaths) {
1366
+ this.polLogger?.warn?.("[PolAttachmentQueue] No watchPaths callback provided");
1367
+ return;
1368
+ }
1369
+ const cleanup = this.source.watchPaths(this.powersync, this.supabaseClient, onUpdate);
1327
1370
  if (typeof cleanup === "function") {
1328
- this._watchIdsCleanup = cleanup;
1371
+ this._watchCleanup = cleanup;
1329
1372
  }
1330
1373
  } catch (error) {
1331
- this.polLogger?.warn?.("[PolAttachmentQueue] watchIds failed:", error);
1374
+ this.polLogger?.warn?.("[PolAttachmentQueue] watchPaths callback failed:", error);
1332
1375
  }
1333
1376
  }).catch((err) => {
1334
1377
  this.polLogger?.warn?.("[PolAttachmentQueue] Watch mutex error:", err);
@@ -1413,13 +1456,13 @@ var PolAttachmentQueue = class extends AbstractAttachmentQueue2 {
1413
1456
  dispose() {
1414
1457
  this._disposed = true;
1415
1458
  this._uploadState.abortController.abort();
1416
- if (this._watchIdsCleanup) {
1459
+ if (this._watchCleanup) {
1417
1460
  try {
1418
- this._watchIdsCleanup();
1461
+ this._watchCleanup();
1419
1462
  } catch (error) {
1420
- this.polLogger?.warn?.("[PolAttachmentQueue] watchIds cleanup failed:", error);
1463
+ this.polLogger?.warn?.("[PolAttachmentQueue] watchPaths cleanup failed:", error);
1421
1464
  }
1422
- this._watchIdsCleanup = void 0;
1465
+ this._watchCleanup = void 0;
1423
1466
  }
1424
1467
  if (this._networkListenerCleanup) {
1425
1468
  try {
@@ -1756,7 +1799,7 @@ var PolAttachmentQueue = class extends AbstractAttachmentQueue2 {
1756
1799
  }
1757
1800
  const rows = await this.powersync.getAll(`SELECT state, COUNT(*) as cnt, COALESCE(SUM(size), 0) as sz
1758
1801
  FROM ${this.table} GROUP BY state`);
1759
- let synced = 0, syncedSize = 0, pending = 0, pendingUpload = 0, failedPermanent = 0, skippedDownloadCount = 0;
1802
+ let synced = 0, syncedSize = 0, pending = 0, pendingUpload = 0, failedPermanent = 0;
1760
1803
  for (const r of rows) {
1761
1804
  if (r.state === AttachmentState6.SYNCED) {
1762
1805
  synced = r.cnt;
@@ -1765,7 +1808,6 @@ var PolAttachmentQueue = class extends AbstractAttachmentQueue2 {
1765
1808
  if (r.state === AttachmentState6.QUEUED_DOWNLOAD || r.state === AttachmentState6.QUEUED_SYNC) pending += r.cnt;
1766
1809
  if (r.state === AttachmentState6.QUEUED_UPLOAD) pendingUpload = r.cnt;
1767
1810
  if (r.state === 5 /* FAILED_PERMANENT */) failedPermanent = r.cnt;
1768
- if (r.state === 6 /* DOWNLOAD_SKIPPED */) skippedDownloadCount = r.cnt;
1769
1811
  }
1770
1812
  const staleUploads = await this.getStaleUploads();
1771
1813
  const stats = {
@@ -1786,7 +1828,8 @@ var PolAttachmentQueue = class extends AbstractAttachmentQueue2 {
1786
1828
  failedPermanentCount: failedPermanent,
1787
1829
  staleUploadCount: staleUploads.length,
1788
1830
  activeUploads: this.activeUploads,
1789
- skippedDownloadCount
1831
+ skippedDownloadCount: 0
1832
+ // No longer tracked - filtering should happen in watchPaths
1790
1833
  };
1791
1834
  this._cachedStats = stats;
1792
1835
  this._cachedStatsTimestamp = now;
@@ -1970,10 +2013,10 @@ function createPolAttachmentQueue(powersync, platform, config) {
1970
2013
  storage: void 0,
1971
2014
  platform,
1972
2015
  remoteStorage: config.remoteStorage,
2016
+ supabaseClient: config.supabaseClient,
1973
2017
  source: {
1974
- bucket: config.bucket,
1975
- watchIds: config.watchIds,
1976
- skipDownload: config.skipDownload
2018
+ source: config.source,
2019
+ watchPaths: config.watchPaths
1977
2020
  },
1978
2021
  attachmentDirectoryName: "attachments",
1979
2022
  attachmentTableName: "attachments",
@@ -2003,6 +2046,10 @@ export {
2003
2046
  DEFAULT_CACHE_CONFIG,
2004
2047
  CACHE_SIZE_PRESETS,
2005
2048
  formatCacheSize,
2049
+ resolveBucketFromConfig,
2050
+ isSignedUrlSource,
2051
+ isCustomSource,
2052
+ getCustomUrlResolver,
2006
2053
  ATTACHMENT_TABLE,
2007
2054
  AttachmentState,
2008
2055
  AttachmentTable,
@@ -2058,4 +2105,4 @@ export {
2058
2105
  PolAttachmentQueue,
2059
2106
  createPolAttachmentQueue
2060
2107
  };
2061
- //# sourceMappingURL=chunk-CACKC6XG.js.map
2108
+ //# sourceMappingURL=chunk-PGEDE6IM.js.map