@pol-studios/powersync 1.0.6 → 1.0.10

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 (128) hide show
  1. package/README.md +933 -0
  2. package/dist/CacheSettingsManager-uz-kbnRH.d.ts +461 -0
  3. package/dist/attachments/index.d.ts +745 -332
  4. package/dist/attachments/index.js +152 -6
  5. package/dist/{types-Cd7RhNqf.d.ts → background-sync-ChCXW-EV.d.ts} +53 -2
  6. package/dist/chunk-24RDMMCL.js +44 -0
  7. package/dist/chunk-24RDMMCL.js.map +1 -0
  8. package/dist/chunk-4TXTAEF2.js +2060 -0
  9. package/dist/chunk-4TXTAEF2.js.map +1 -0
  10. package/dist/chunk-63PXSPIN.js +358 -0
  11. package/dist/chunk-63PXSPIN.js.map +1 -0
  12. package/dist/chunk-654ERHA7.js +1 -0
  13. package/dist/chunk-A4IBBWGO.js +377 -0
  14. package/dist/chunk-A4IBBWGO.js.map +1 -0
  15. package/dist/chunk-BRXQNASY.js +1720 -0
  16. package/dist/chunk-BRXQNASY.js.map +1 -0
  17. package/dist/chunk-CAB26E6F.js +142 -0
  18. package/dist/chunk-CAB26E6F.js.map +1 -0
  19. package/dist/{chunk-EJ23MXPQ.js → chunk-CGL33PL4.js} +3 -1
  20. package/dist/chunk-CGL33PL4.js.map +1 -0
  21. package/dist/{chunk-R4YFWQ3Q.js → chunk-CUCAYK7Z.js} +309 -92
  22. package/dist/chunk-CUCAYK7Z.js.map +1 -0
  23. package/dist/chunk-FV2HXEIY.js +124 -0
  24. package/dist/chunk-FV2HXEIY.js.map +1 -0
  25. package/dist/chunk-HWSNV45P.js +279 -0
  26. package/dist/chunk-HWSNV45P.js.map +1 -0
  27. package/dist/{chunk-62J2DPKX.js → chunk-KN2IZERF.js} +530 -413
  28. package/dist/chunk-KN2IZERF.js.map +1 -0
  29. package/dist/{chunk-7EMDVIZX.js → chunk-N75DEF5J.js} +19 -1
  30. package/dist/chunk-N75DEF5J.js.map +1 -0
  31. package/dist/chunk-P4HZA6ZT.js +83 -0
  32. package/dist/chunk-P4HZA6ZT.js.map +1 -0
  33. package/dist/chunk-P6WOZO7H.js +49 -0
  34. package/dist/chunk-P6WOZO7H.js.map +1 -0
  35. package/dist/chunk-T4AO7JIG.js +1 -0
  36. package/dist/chunk-TGBT5XBE.js +1 -0
  37. package/dist/{chunk-FPTDATY5.js → chunk-VACPAAQZ.js} +54 -12
  38. package/dist/chunk-VACPAAQZ.js.map +1 -0
  39. package/dist/chunk-WGHNIAF7.js +329 -0
  40. package/dist/chunk-WGHNIAF7.js.map +1 -0
  41. package/dist/{chunk-3AYXHQ4W.js → chunk-WN5ZJ3E2.js} +108 -47
  42. package/dist/chunk-WN5ZJ3E2.js.map +1 -0
  43. package/dist/chunk-XAEII4ZX.js +456 -0
  44. package/dist/chunk-XAEII4ZX.js.map +1 -0
  45. package/dist/chunk-XOY2CJ67.js +289 -0
  46. package/dist/chunk-XOY2CJ67.js.map +1 -0
  47. package/dist/chunk-YHTZ7VMV.js +1 -0
  48. package/dist/chunk-YSTEESEG.js +676 -0
  49. package/dist/chunk-YSTEESEG.js.map +1 -0
  50. package/dist/chunk-Z6VOBGTU.js +32 -0
  51. package/dist/chunk-Z6VOBGTU.js.map +1 -0
  52. package/dist/chunk-ZM4ENYMF.js +230 -0
  53. package/dist/chunk-ZM4ENYMF.js.map +1 -0
  54. package/dist/connector/index.d.ts +236 -4
  55. package/dist/connector/index.js +15 -4
  56. package/dist/core/index.d.ts +16 -3
  57. package/dist/core/index.js +6 -2
  58. package/dist/error/index.d.ts +54 -0
  59. package/dist/error/index.js +7 -0
  60. package/dist/error/index.js.map +1 -0
  61. package/dist/index.d.ts +102 -12
  62. package/dist/index.js +309 -37
  63. package/dist/index.native.d.ts +22 -10
  64. package/dist/index.native.js +309 -38
  65. package/dist/index.web.d.ts +22 -10
  66. package/dist/index.web.js +310 -38
  67. package/dist/maintenance/index.d.ts +118 -0
  68. package/dist/maintenance/index.js +16 -0
  69. package/dist/maintenance/index.js.map +1 -0
  70. package/dist/platform/index.d.ts +16 -1
  71. package/dist/platform/index.js.map +1 -1
  72. package/dist/platform/index.native.d.ts +2 -2
  73. package/dist/platform/index.native.js +1 -1
  74. package/dist/platform/index.web.d.ts +1 -1
  75. package/dist/platform/index.web.js +1 -1
  76. package/dist/pol-attachment-queue-BVAIueoP.d.ts +817 -0
  77. package/dist/provider/index.d.ts +451 -21
  78. package/dist/provider/index.js +32 -13
  79. package/dist/react/index.d.ts +372 -0
  80. package/dist/react/index.js +25 -0
  81. package/dist/react/index.js.map +1 -0
  82. package/dist/storage/index.d.ts +6 -0
  83. package/dist/storage/index.js +42 -0
  84. package/dist/storage/index.js.map +1 -0
  85. package/dist/storage/index.native.d.ts +6 -0
  86. package/dist/storage/index.native.js +40 -0
  87. package/dist/storage/index.native.js.map +1 -0
  88. package/dist/storage/index.web.d.ts +6 -0
  89. package/dist/storage/index.web.js +40 -0
  90. package/dist/storage/index.web.js.map +1 -0
  91. package/dist/storage/upload/index.d.ts +54 -0
  92. package/dist/storage/upload/index.js +15 -0
  93. package/dist/storage/upload/index.js.map +1 -0
  94. package/dist/storage/upload/index.native.d.ts +56 -0
  95. package/dist/storage/upload/index.native.js +15 -0
  96. package/dist/storage/upload/index.native.js.map +1 -0
  97. package/dist/storage/upload/index.web.d.ts +2 -0
  98. package/dist/storage/upload/index.web.js +14 -0
  99. package/dist/storage/upload/index.web.js.map +1 -0
  100. package/dist/supabase-connector-T9vHq_3i.d.ts +202 -0
  101. package/dist/sync/index.d.ts +288 -23
  102. package/dist/sync/index.js +22 -10
  103. package/dist/{index-l3iL9Jte.d.ts → types-B212hgfA.d.ts} +101 -158
  104. package/dist/{types-afHtE1U_.d.ts → types-CDqWh56B.d.ts} +2 -0
  105. package/dist/types-CyvBaAl8.d.ts +60 -0
  106. package/dist/types-D0WcHrq6.d.ts +234 -0
  107. package/package.json +89 -5
  108. package/dist/chunk-32OLICZO.js +0 -1
  109. package/dist/chunk-3AYXHQ4W.js.map +0 -1
  110. package/dist/chunk-5FIMA26D.js +0 -1
  111. package/dist/chunk-62J2DPKX.js.map +0 -1
  112. package/dist/chunk-7EMDVIZX.js.map +0 -1
  113. package/dist/chunk-EJ23MXPQ.js.map +0 -1
  114. package/dist/chunk-FPTDATY5.js.map +0 -1
  115. package/dist/chunk-KCDG2MNP.js +0 -1431
  116. package/dist/chunk-KCDG2MNP.js.map +0 -1
  117. package/dist/chunk-OLHGI472.js +0 -1
  118. package/dist/chunk-PAFBKNL3.js +0 -99
  119. package/dist/chunk-PAFBKNL3.js.map +0 -1
  120. package/dist/chunk-R4YFWQ3Q.js.map +0 -1
  121. package/dist/chunk-V6LJ6MR2.js +0 -740
  122. package/dist/chunk-V6LJ6MR2.js.map +0 -1
  123. package/dist/chunk-VJCL2SWD.js +0 -1
  124. package/dist/failed-upload-store-C0cLxxPz.d.ts +0 -33
  125. /package/dist/{chunk-32OLICZO.js.map → chunk-654ERHA7.js.map} +0 -0
  126. /package/dist/{chunk-5FIMA26D.js.map → chunk-T4AO7JIG.js.map} +0 -0
  127. /package/dist/{chunk-OLHGI472.js.map → chunk-TGBT5XBE.js.map} +0 -0
  128. /package/dist/{chunk-VJCL2SWD.js.map → chunk-YHTZ7VMV.js.map} +0 -0
@@ -1,7 +1,6 @@
1
1
  import { SupabaseClient } from '@supabase/supabase-js';
2
- import { C as CrudEntry, i as ClassifiedError, P as PowerSyncBackendConnector, A as AbstractPowerSyncDatabase } from './types-afHtE1U_.js';
2
+ import { C as CrudEntry, i as ClassifiedError } from './types-CDqWh56B.js';
3
3
  import { LoggerAdapter } from './platform/index.js';
4
- import { F as FailedUpload } from './failed-upload-store-C0cLxxPz.js';
5
4
 
6
5
  /**
7
6
  * Conflict Types for @pol-studios/powersync
@@ -86,10 +85,13 @@ type ResolutionListener = (table: string, recordId: string, resolution: Conflict
86
85
  * 4. Connector subscribes via bus.onResolution() -> triggers re-upload
87
86
  */
88
87
  declare class ConflictBus {
88
+ private static MAX_PENDING;
89
89
  private conflictListeners;
90
90
  private resolutionListeners;
91
+ private pendingConflicts;
91
92
  /**
92
93
  * Subscribe to conflict detection events.
94
+ * Flushes any pending conflicts to ALL listeners (including the new one).
93
95
  * @returns Unsubscribe function
94
96
  */
95
97
  onConflict(listener: ConflictListener): () => void;
@@ -100,6 +102,7 @@ declare class ConflictBus {
100
102
  onResolution(listener: ResolutionListener): () => void;
101
103
  /**
102
104
  * Emit a conflict detection event (called by connector).
105
+ * If no listeners are subscribed, queues the conflict for later delivery.
103
106
  */
104
107
  emitConflict(conflict: ConflictCheckResult): void;
105
108
  /**
@@ -107,9 +110,13 @@ declare class ConflictBus {
107
110
  */
108
111
  emitResolution(table: string, recordId: string, resolution: ConflictResolution): void;
109
112
  /**
110
- * Clear all listeners (for cleanup).
113
+ * Clear all listeners and pending conflicts (for cleanup).
111
114
  */
112
115
  destroy(): void;
116
+ /**
117
+ * Get the number of pending conflicts (useful for debugging/testing).
118
+ */
119
+ get pendingCount(): number;
113
120
  }
114
121
 
115
122
  /**
@@ -118,6 +125,37 @@ declare class ConflictBus {
118
125
  * Defines interfaces for PowerSync backend connectors.
119
126
  */
120
127
 
128
+ /**
129
+ * Circuit breaker configuration for the connector.
130
+ * Prevents cascading failures by stopping requests when service is down.
131
+ */
132
+ interface ConnectorCircuitBreakerConfig {
133
+ /**
134
+ * Enable circuit breaker pattern.
135
+ * @default false
136
+ */
137
+ enabled: boolean;
138
+ /**
139
+ * Number of failures required to trip the circuit.
140
+ * @default 5
141
+ */
142
+ failureThreshold?: number;
143
+ /**
144
+ * Time window in ms for counting failures.
145
+ * @default 60000 (60 seconds)
146
+ */
147
+ failureWindowMs?: number;
148
+ /**
149
+ * Initial delay before transitioning from OPEN to HALF_OPEN.
150
+ * @default 1000 (1 second)
151
+ */
152
+ initialRecoveryDelayMs?: number;
153
+ /**
154
+ * Maximum delay for exponential backoff.
155
+ * @default 32000 (32 seconds)
156
+ */
157
+ maxRecoveryDelayMs?: number;
158
+ }
121
159
  /**
122
160
  * Options for creating a SupabaseConnector
123
161
  */
@@ -168,6 +206,13 @@ interface SupabaseConnectorOptions {
168
206
  * @default DEFAULT_RETRY_CONFIG
169
207
  */
170
208
  retryConfig?: Partial<RetryConfig>;
209
+ /**
210
+ * Optional: Configuration for circuit breaker pattern.
211
+ * When enabled, prevents cascading failures by stopping requests when
212
+ * the service is experiencing high failure rates.
213
+ * @default { enabled: false }
214
+ */
215
+ circuitBreaker?: ConnectorCircuitBreakerConfig;
171
216
  }
172
217
  /**
173
218
  * Configuration passed to PowerSyncProvider for connector setup
@@ -279,182 +324,80 @@ interface RetryStrategyConfig {
279
324
  interface RetryConfig {
280
325
  /** Retry config for transient errors (network, server 5xx) */
281
326
  transient: RetryStrategyConfig;
282
- /** Retry config for permanent errors (RLS, validation, constraints) */
327
+ /** Retry config for permanent errors (validation, constraints) */
283
328
  permanent: RetryStrategyConfig;
329
+ /** Retry config for RLS/permission errors (42501, row-level security violations) */
330
+ rls: RetryStrategyConfig;
284
331
  }
285
332
  /**
286
333
  * Default retry configuration
334
+ *
335
+ * Uses fast exponential backoff for transient errors (network issues):
336
+ * - Transient: 1s → 2s → 4s
337
+ *
338
+ * RLS/permission errors (42501, row-level security violations) use extended delays
339
+ * because parent data may need time to sync before child records can be inserted.
340
+ * - RLS: 30s → 60s → 120s → 120s → 120s (5 retries over ~7.5 minutes)
341
+ *
342
+ * Other permanent errors (validation, constraints) get NO retries
343
+ * because they will never succeed - fail fast and surface to user.
344
+ * PowerSync's native retry mechanism will re-attempt on next sync cycle.
287
345
  */
288
346
  declare const DEFAULT_RETRY_CONFIG: RetryConfig;
289
-
290
347
  /**
291
- * Supabase Connector for PowerSync
292
- *
293
- * A generic, configurable connector that handles:
294
- * - Authentication with Supabase JWT tokens
295
- * - Uploading local changes back to Supabase
296
- * - Schema routing for multi-schema databases
297
- * - Custom CRUD handling for complex operations
298
- * - Version-based conflict detection (when enabled)
348
+ * Session representation for authentication.
349
+ * Used by AuthProvider to communicate auth state.
299
350
  */
300
-
351
+ interface Session {
352
+ /** Access token for API requests */
353
+ accessToken: string;
354
+ /** When the token expires (optional) */
355
+ expiresAt?: Date;
356
+ /** User information (optional) */
357
+ user?: {
358
+ id: string;
359
+ };
360
+ }
301
361
  /**
302
- * Generic Supabase connector for PowerSync.
303
- *
304
- * This connector handles authentication and CRUD uploads to Supabase.
305
- * It supports configurable schema routing and custom CRUD handlers
306
- * for complex use cases.
362
+ * Authentication provider interface.
363
+ * Abstracts auth for the connector - works with any auth backend.
307
364
  *
308
- * @example Basic usage
365
+ * @example
309
366
  * ```typescript
310
- * const connector = new SupabaseConnector({
311
- * supabaseClient: supabase,
312
- * powerSyncUrl: 'https://your-powersync-instance.com',
313
- * });
314
- * ```
367
+ * // Using built-in Supabase adapter
368
+ * const auth = createSupabaseAuth(supabaseClient);
315
369
  *
316
- * @example With schema routing
317
- * ```typescript
318
- * const connector = new SupabaseConnector({
319
- * supabaseClient: supabase,
320
- * powerSyncUrl: 'https://your-powersync-instance.com',
321
- * schemaRouter: (table) => {
322
- * if (['Profile', 'Comment', 'CommentSection'].includes(table)) {
323
- * return 'core';
324
- * }
325
- * return 'public';
370
+ * // Custom implementation
371
+ * const auth: AuthProvider = {
372
+ * getSession: async () => ({ accessToken: myToken }),
373
+ * refreshSession: async () => {
374
+ * const newToken = await myAuthService.refresh();
375
+ * return { accessToken: newToken };
326
376
  * },
327
- * });
328
- * ```
329
- *
330
- * @example With custom CRUD handler
331
- * ```typescript
332
- * const connector = new SupabaseConnector({
333
- * supabaseClient: supabase,
334
- * powerSyncUrl: 'https://your-powersync-instance.com',
335
- * crudHandler: {
336
- * async handlePut(entry, supabase, schema) {
337
- * // Custom handling for specific tables
338
- * if (entry.table === 'SpecialTable') {
339
- * await myCustomUpsert(entry);
340
- * return true; // Handled
341
- * }
342
- * return false; // Use default
343
- * },
377
+ * onAuthStateChange: (cb) => {
378
+ * return myAuthService.subscribe(cb);
344
379
  * },
345
- * });
380
+ * };
346
381
  * ```
347
382
  */
348
- declare class SupabaseConnector implements PowerSyncBackendConnector {
349
- private readonly supabase;
350
- private readonly powerSyncUrl;
351
- private readonly schemaRouter;
352
- private readonly crudHandler?;
353
- private readonly logger?;
354
- private readonly onTransactionSuccess?;
355
- private readonly onTransactionFailure?;
356
- private readonly onTransactionComplete?;
357
- private readonly shouldUploadFn?;
358
- private readonly conflictDetection?;
359
- private readonly conflictHandler?;
360
- private readonly conflictBus?;
361
- private versionColumnCache;
362
- private activeProjectIds;
363
- private resolvedConflicts;
364
- private unsubscribeResolution?;
365
- private retryConfig;
366
- private autoRetryPaused;
367
- constructor(options: SupabaseConnectorOptions);
383
+ interface AuthProvider {
368
384
  /**
369
- * Clean up resources (unsubscribe from event listeners).
370
- * Call this when the connector is no longer needed.
385
+ * Get the current session.
386
+ * @returns Current session or null if not authenticated
371
387
  */
372
- destroy(): void;
388
+ getSession(): Promise<Session | null>;
373
389
  /**
374
- * Pause automatic retry of failed uploads.
375
- * Use this when the user goes offline intentionally or wants manual control.
390
+ * Refresh the current session.
391
+ * @throws Error if refresh fails (e.g., refresh token expired)
392
+ * @returns New session with fresh access token
376
393
  */
377
- pauseAutoRetry(): void;
394
+ refreshSession(): Promise<Session>;
378
395
  /**
379
- * Resume automatic retry of failed uploads.
380
- */
381
- resumeAutoRetry(): void;
382
- /**
383
- * Manually retry all failed uploads that are ready for retry.
384
- * This processes entries from the failed upload store.
385
- */
386
- retryFailedUploads(): Promise<void>;
387
- /**
388
- * Clear all failed uploads from the store.
389
- * Use with caution - this discards all pending retries.
390
- */
391
- clearFailedUploads(): void;
392
- /**
393
- * Get all failed uploads from the store.
394
- */
395
- getFailedUploads(): FailedUpload[];
396
- /**
397
- * Process a single CRUD entry with exponential backoff retry.
398
- *
399
- * @param entry - The CRUD entry to process
400
- * @throws Error if all retries exhausted (for critical failures)
401
- */
402
- private processWithRetry;
403
- /**
404
- * Set the active project IDs for scoped sync.
405
- * Call this when user selects/opens projects.
406
- */
407
- setActiveProjectIds(projectIds: string[]): void;
408
- /**
409
- * Get the current active project IDs.
410
- */
411
- getActiveProjectIds(): string[];
412
- /**
413
- * Get credentials for PowerSync connection.
414
- * Uses Supabase session token.
415
- *
416
- * Note: Token refresh is handled by Supabase's startAutoRefresh() which must be
417
- * called on app initialization. getSession() returns the auto-refreshed token.
418
- */
419
- fetchCredentials(): Promise<PowerSyncCredentials>;
420
- /**
421
- * Upload local changes to Supabase.
422
- * Called automatically by PowerSync when there are pending uploads.
423
- *
424
- * When conflict detection is enabled:
425
- * 1. Checks if table has _version column (cached)
426
- * 2. If yes, compares local vs server version
427
- * 3. On version mismatch, queries AuditLog for field conflicts
428
- * 4. If conflicts found, calls handler or publishes to conflict bus
429
- * 5. Applies resolution or skips entry based on handler response
430
- */
431
- uploadData(database: AbstractPowerSyncDatabase): Promise<void>;
432
- /**
433
- * Process a transaction without conflict detection.
434
- * Used when conflict detection is disabled.
435
- */
436
- private processTransaction;
437
- /**
438
- * Check if a table has a _version column (cached).
439
- */
440
- private checkVersionColumn;
441
- /**
442
- * Filter opData to only include specified fields.
443
- * Used for partial sync resolution.
444
- */
445
- private filterFields;
446
- /**
447
- * Process a single CRUD operation.
448
- *
449
- * UUID-native tables (public schema, post-migration) use `id` as the UUID column.
450
- * Core schema tables (Profile, Comment, CommentSection) still use a separate `uuid` column.
451
- */
452
- /**
453
- * Process a single CRUD operation.
454
- *
455
- * All synced tables use `id` as their UUID primary key column.
396
+ * Subscribe to auth state changes.
397
+ * @param cb - Callback fired when auth state changes
398
+ * @returns Unsubscribe function
456
399
  */
457
- private processCrudEntry;
400
+ onAuthStateChange(cb: (session: Session | null) => void): () => void;
458
401
  }
459
402
 
460
- export { type ConnectorConfig as C, DEFAULT_RETRY_CONFIG as D, type FieldConflict as F, type PowerSyncCredentials as P, type RetryStrategyConfig as R, SupabaseConnector as S, type SupabaseConnectorOptions as a, type SchemaRouter as b, type CrudHandler as c, defaultSchemaRouter as d, type RetryConfig as e, ConflictBus as f, type ConflictCheckResult as g, type ConflictResolution as h, type ConflictHandler as i, type ConflictDetectionConfig as j, type ConflictListener as k, type ResolutionListener as l };
403
+ export { type AuthProvider as A, type ConnectorCircuitBreakerConfig as C, DEFAULT_RETRY_CONFIG as D, type FieldConflict as F, type PowerSyncCredentials as P, type RetryStrategyConfig as R, type SupabaseConnectorOptions as S, type ConnectorConfig as a, type SchemaRouter as b, type CrudHandler as c, defaultSchemaRouter as d, type RetryConfig as e, type Session as f, ConflictBus as g, type ConflictCheckResult as h, type ConflictResolution as i, type ConflictHandler as j, type ConflictDetectionConfig as k, type ConflictListener as l, type ResolutionListener as m };
@@ -39,6 +39,8 @@ interface CrudEntry {
39
39
  opData?: Record<string, unknown>;
40
40
  /** Transaction ID for grouping operations */
41
41
  transactionId?: number;
42
+ /** When this mutation was created (for display purposes) */
43
+ createdAt?: Date;
42
44
  }
43
45
  /**
44
46
  * Download progress information during sync
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Upload Handler Types for @pol-studios/powersync
3
+ *
4
+ * Defines types for platform-specific upload handlers.
5
+ */
6
+ /**
7
+ * Bucket configuration for multi-bucket routing.
8
+ */
9
+ interface BucketConfig {
10
+ /** Default bucket for storage operations */
11
+ defaultBucket: string;
12
+ /** Map of path prefixes to bucket names */
13
+ bucketMap?: Map<string, string>;
14
+ /** Custom bucket resolver function */
15
+ resolver?: (storagePath: string) => string | undefined;
16
+ }
17
+ /**
18
+ * Options for creating a SupabaseUploadHandler.
19
+ */
20
+ interface SupabaseUploadHandlerOptions {
21
+ /** Supabase client instance */
22
+ supabaseClient: any;
23
+ /** Bucket configuration for multi-bucket routing */
24
+ bucketConfig: BucketConfig;
25
+ }
26
+ /**
27
+ * Event handlers for upload progress tracking.
28
+ */
29
+ interface UploadEventHandlers {
30
+ /** Called with progress updates during upload */
31
+ onProgress?: (progress: {
32
+ loaded: number;
33
+ total: number;
34
+ }) => void;
35
+ /** Called when upload completes successfully */
36
+ onComplete?: () => void;
37
+ /** Called when upload fails */
38
+ onError?: (error: Error) => void;
39
+ }
40
+ /**
41
+ * Configuration for native upload notifications (Android).
42
+ */
43
+ interface UploadNotificationConfig {
44
+ /** Whether to show upload notifications */
45
+ enabled: boolean;
46
+ /** Whether to auto-clear notification on completion */
47
+ autoClear: boolean;
48
+ /** Title shown during upload progress */
49
+ onProgressTitle: string;
50
+ /** Title shown when upload completes */
51
+ onCompleteTitle: string;
52
+ /** Title shown when upload fails */
53
+ onErrorTitle: string;
54
+ }
55
+ /**
56
+ * Default notification configuration for Android uploads.
57
+ */
58
+ declare const DEFAULT_UPLOAD_NOTIFICATION: UploadNotificationConfig;
59
+
60
+ export { type BucketConfig as B, DEFAULT_UPLOAD_NOTIFICATION as D, type SupabaseUploadHandlerOptions as S, type UploadEventHandlers as U, type UploadNotificationConfig as a };
@@ -0,0 +1,234 @@
1
+ import { FileSystemAdapter, LoggerAdapter } from './platform/index.js';
2
+
3
+ /**
4
+ * Unified Storage Types for @pol-studios/powersync
5
+ *
6
+ * Single storage interface for all Supabase storage operations.
7
+ * Consolidates the previous 6 fragmented interfaces into one:
8
+ * - AttachmentStorageAdapter (attachments/types.ts)
9
+ * - RemoteStorageAdapter (storage/types.ts - removed)
10
+ * - StorageAdapter (@powersync/attachments)
11
+ * - PowerSyncStorageAdapter (storage/types.ts - removed)
12
+ * - StorageUploadHandler (storage/types.ts - removed)
13
+ * - UploadHandler (attachments/types.ts)
14
+ */
15
+ /**
16
+ * Unified storage interface for Supabase storage operations.
17
+ * Handles both upload and download for attachments.
18
+ *
19
+ * This is the ONLY storage interface consumers need to implement.
20
+ * It replaces all previous storage adapter interfaces.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const storage: SupabaseStorage = {
25
+ * async download(path) {
26
+ * const { data } = await supabase.storage
27
+ * .from('attachments')
28
+ * .createSignedUrl(path, 60);
29
+ * // Download to temp file and return URI
30
+ * return tempFileUri;
31
+ * },
32
+ *
33
+ * async upload(path, localUri, mediaType) {
34
+ * const file = await readFile(localUri);
35
+ * await supabase.storage
36
+ * .from('attachments')
37
+ * .upload(path, file, { contentType: mediaType });
38
+ * },
39
+ * };
40
+ * ```
41
+ */
42
+ interface SupabaseStorage {
43
+ /**
44
+ * Download a file and return the local file:// URI.
45
+ *
46
+ * @param path - Remote storage path
47
+ * @returns Local file:// URI pointing to the downloaded file
48
+ */
49
+ download(path: string): Promise<string>;
50
+ /**
51
+ * Upload a local file to remote storage.
52
+ *
53
+ * @param path - Remote storage path
54
+ * @param localUri - Local file:// URI to upload from
55
+ * @param mediaType - MIME type of the file
56
+ * @param signal - Optional AbortSignal for cancellation
57
+ */
58
+ upload(path: string, localUri: string, mediaType: string, signal?: AbortSignal): Promise<void>;
59
+ /**
60
+ * Delete a file from remote storage.
61
+ * Optional - not all implementations need deletion.
62
+ *
63
+ * @param path - Remote storage path to delete
64
+ */
65
+ delete?(path: string): Promise<void>;
66
+ /**
67
+ * Resolve which bucket a path belongs to.
68
+ * Optional - useful for multi-bucket configurations.
69
+ *
70
+ * @param path - Remote storage path
71
+ * @returns The bucket name
72
+ */
73
+ resolveBucket?(path: string): string;
74
+ }
75
+ /**
76
+ * Download result discriminated union.
77
+ * Native platforms return file URIs, web returns blobs.
78
+ */
79
+ type DownloadResult = {
80
+ type: 'file';
81
+ uri: string;
82
+ } | {
83
+ type: 'blob';
84
+ data: Blob;
85
+ };
86
+ /**
87
+ * Storage backend returned by createSupabaseStorage factory.
88
+ * This is a more flexible interface that returns discriminated unions
89
+ * to handle both native (file URI) and web (blob) download results.
90
+ *
91
+ * For simpler use cases, use SupabaseStorage interface directly.
92
+ */
93
+ interface StorageBackend {
94
+ /** Download a file, returns discriminated union based on platform */
95
+ download(path: string): Promise<DownloadResult>;
96
+ /** Upload a local file to remote storage */
97
+ upload(path: string, localUri: string, contentType: string, options?: StorageUploadOptions): Promise<void>;
98
+ /** Delete a file from remote storage */
99
+ delete(path: string): Promise<void>;
100
+ /** Resolve which bucket a path belongs to */
101
+ resolveBucket(path: string): string;
102
+ }
103
+ /**
104
+ * Progress information for upload operations.
105
+ */
106
+ interface UploadProgress {
107
+ /** Bytes uploaded so far */
108
+ loaded: number;
109
+ /** Total bytes to upload */
110
+ total: number;
111
+ }
112
+ /**
113
+ * Options for upload operations.
114
+ */
115
+ interface StorageUploadOptions {
116
+ /** AbortSignal for cancellation support */
117
+ signal?: AbortSignal;
118
+ /** Progress callback */
119
+ onProgress?: (progress: UploadProgress) => void;
120
+ }
121
+
122
+ /**
123
+ * Options for creating a Supabase storage backend.
124
+ */
125
+ interface SupabaseStorageOptions {
126
+ /** Supabase client instance */
127
+ client: SupabaseClient;
128
+ /** Default storage bucket */
129
+ defaultBucket: string;
130
+ /**
131
+ * Map of path prefixes to bucket names.
132
+ * Checked in iteration order (use Map to preserve order).
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * bucketMap: new Map([
137
+ * ['avatars/', 'user-avatars'],
138
+ * ['docs/', 'documents'],
139
+ * ])
140
+ * ```
141
+ */
142
+ bucketMap?: Map<string, string>;
143
+ /**
144
+ * Custom bucket resolver function.
145
+ * Takes precedence over bucketMap.
146
+ * Return undefined to fall through to bucketMap/defaultBucket.
147
+ */
148
+ bucketResolver?: (storagePath: string) => string | undefined;
149
+ /**
150
+ * Signed URL expiry in seconds.
151
+ * @default 60 (short-lived for security)
152
+ */
153
+ signedUrlExpiry?: number;
154
+ /**
155
+ * File system adapter for native file operations.
156
+ * Required for native platforms to enable file-based downloads.
157
+ */
158
+ fileSystem?: FileSystemAdapter;
159
+ /**
160
+ * Optional logger for diagnostic messages.
161
+ */
162
+ logger?: LoggerAdapter;
163
+ }
164
+ /**
165
+ * Transform options for Supabase image transformation.
166
+ * See: https://supabase.com/docs/guides/storage/serving/image-transformations
167
+ */
168
+ interface SupabaseTransformOptions {
169
+ width?: number;
170
+ height?: number;
171
+ resize?: 'cover' | 'contain' | 'fill';
172
+ format?: 'origin' | 'avif' | 'webp';
173
+ quality?: number;
174
+ }
175
+ /**
176
+ * Minimal Supabase client interface for storage operations.
177
+ * Using a minimal interface to avoid version conflicts with @supabase/supabase-js.
178
+ */
179
+ interface SupabaseClient {
180
+ storage: {
181
+ from(bucket: string): {
182
+ createSignedUrl(path: string, expiresIn: number, options?: {
183
+ download?: string | boolean;
184
+ transform?: SupabaseTransformOptions;
185
+ }): Promise<{
186
+ data: {
187
+ signedUrl: string;
188
+ } | null;
189
+ error: Error | null;
190
+ }>;
191
+ upload(path: string, file: Blob | ArrayBuffer | FormData, options?: {
192
+ contentType?: string;
193
+ upsert?: boolean;
194
+ }): Promise<{
195
+ data: {
196
+ path: string;
197
+ } | null;
198
+ error: Error | null;
199
+ }>;
200
+ remove(paths: string[]): Promise<{
201
+ data: {
202
+ name: string;
203
+ }[] | null;
204
+ error: Error | null;
205
+ }>;
206
+ list(path?: string, options?: {
207
+ search?: string;
208
+ limit?: number;
209
+ }): Promise<{
210
+ data: {
211
+ name: string;
212
+ }[] | null;
213
+ error: Error | null;
214
+ }>;
215
+ };
216
+ };
217
+ auth: {
218
+ refreshSession(): Promise<{
219
+ data: unknown;
220
+ error: Error | null;
221
+ }>;
222
+ };
223
+ }
224
+ /**
225
+ * Resolve bucket from storage path using SupabaseStorageOptions.
226
+ *
227
+ * Resolution order:
228
+ * 1. Custom bucketResolver (if provided and returns a value)
229
+ * 2. bucketMap prefix matching (if provided)
230
+ * 3. defaultBucket
231
+ */
232
+ declare function resolveBucket(options: Pick<SupabaseStorageOptions, 'defaultBucket' | 'bucketMap' | 'bucketResolver'>, storagePath: string): string;
233
+
234
+ export { type DownloadResult as D, type SupabaseStorage as S, type UploadProgress as U, type StorageBackend as a, type StorageUploadOptions as b, type SupabaseStorageOptions as c, type SupabaseClient as d, type SupabaseTransformOptions as e, resolveBucket as r };