@pol-studios/powersync 1.0.7 → 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.
- package/README.md +933 -0
- package/dist/CacheSettingsManager-uz-kbnRH.d.ts +461 -0
- package/dist/attachments/index.d.ts +709 -6
- package/dist/attachments/index.js +133 -5
- package/dist/chunk-24RDMMCL.js +44 -0
- package/dist/chunk-24RDMMCL.js.map +1 -0
- package/dist/chunk-4TXTAEF2.js +2060 -0
- package/dist/chunk-4TXTAEF2.js.map +1 -0
- package/dist/chunk-63PXSPIN.js +358 -0
- package/dist/chunk-63PXSPIN.js.map +1 -0
- package/dist/chunk-654ERHA7.js +1 -0
- package/dist/{chunk-BREGB4WL.js → chunk-BRXQNASY.js} +287 -335
- package/dist/chunk-BRXQNASY.js.map +1 -0
- package/dist/{chunk-DHYUBVP7.js → chunk-CAB26E6F.js} +20 -9
- package/dist/chunk-CAB26E6F.js.map +1 -0
- package/dist/{chunk-H772V6XQ.js → chunk-CUCAYK7Z.js} +7 -43
- package/dist/chunk-CUCAYK7Z.js.map +1 -0
- package/dist/{chunk-4C3RY5SU.js → chunk-HWSNV45P.js} +76 -1
- package/dist/chunk-HWSNV45P.js.map +1 -0
- package/dist/{chunk-HFOFLW5F.js → chunk-KN2IZERF.js} +139 -6
- package/dist/chunk-KN2IZERF.js.map +1 -0
- package/dist/{chunk-UEYRTLKE.js → chunk-P4HZA6ZT.js} +20 -9
- package/dist/chunk-P4HZA6ZT.js.map +1 -0
- package/dist/chunk-T4AO7JIG.js +1 -0
- package/dist/{chunk-XQAJM2MW.js → chunk-VACPAAQZ.js} +33 -2
- package/dist/{chunk-XQAJM2MW.js.map → chunk-VACPAAQZ.js.map} +1 -1
- package/dist/{chunk-53WH2JJV.js → chunk-WN5ZJ3E2.js} +5 -8
- package/dist/chunk-WN5ZJ3E2.js.map +1 -0
- package/dist/chunk-XAEII4ZX.js +456 -0
- package/dist/chunk-XAEII4ZX.js.map +1 -0
- package/dist/chunk-XOY2CJ67.js +289 -0
- package/dist/chunk-XOY2CJ67.js.map +1 -0
- package/dist/chunk-YHTZ7VMV.js +1 -0
- package/dist/{chunk-MKD2VCX3.js → chunk-Z6VOBGTU.js} +8 -8
- package/dist/chunk-Z6VOBGTU.js.map +1 -0
- package/dist/chunk-ZM4ENYMF.js +230 -0
- package/dist/chunk-ZM4ENYMF.js.map +1 -0
- package/dist/connector/index.d.ts +56 -3
- package/dist/connector/index.js +8 -5
- package/dist/core/index.d.ts +12 -1
- package/dist/core/index.js +3 -2
- package/dist/error/index.js +0 -1
- package/dist/index.d.ts +12 -10
- package/dist/index.js +191 -29
- package/dist/index.native.d.ts +11 -9
- package/dist/index.native.js +191 -29
- package/dist/index.web.d.ts +11 -9
- package/dist/index.web.js +191 -29
- package/dist/maintenance/index.js +0 -1
- package/dist/platform/index.js +0 -2
- package/dist/platform/index.js.map +1 -1
- package/dist/platform/index.native.js +1 -2
- package/dist/platform/index.web.js +0 -1
- package/dist/pol-attachment-queue-BVAIueoP.d.ts +817 -0
- package/dist/provider/index.d.ts +38 -34
- package/dist/provider/index.js +11 -12
- package/dist/react/index.d.ts +372 -0
- package/dist/react/index.js +25 -0
- package/dist/storage/index.d.ts +3 -3
- package/dist/storage/index.js +22 -8
- package/dist/storage/index.native.d.ts +3 -3
- package/dist/storage/index.native.js +21 -7
- package/dist/storage/index.web.d.ts +3 -3
- package/dist/storage/index.web.js +21 -7
- package/dist/storage/upload/index.d.ts +7 -8
- package/dist/storage/upload/index.js +3 -3
- package/dist/storage/upload/index.native.d.ts +7 -8
- package/dist/storage/upload/index.native.js +4 -3
- package/dist/storage/upload/index.web.d.ts +1 -4
- package/dist/storage/upload/index.web.js +3 -3
- package/dist/supabase-connector-T9vHq_3i.d.ts +202 -0
- package/dist/sync/index.js +3 -3
- package/dist/{supabase-connector-qLm-WHkM.d.ts → types-B212hgfA.d.ts} +48 -170
- package/dist/{types-BVacP54t.d.ts → types-CyvBaAl8.d.ts} +12 -4
- package/dist/types-D0WcHrq6.d.ts +234 -0
- package/package.json +18 -4
- package/dist/CacheSettingsManager-1exbOC6S.d.ts +0 -261
- package/dist/chunk-4C3RY5SU.js.map +0 -1
- package/dist/chunk-53WH2JJV.js.map +0 -1
- package/dist/chunk-BREGB4WL.js.map +0 -1
- package/dist/chunk-DGUM43GV.js +0 -11
- package/dist/chunk-DHYUBVP7.js.map +0 -1
- package/dist/chunk-GKF7TOMT.js +0 -1
- package/dist/chunk-H772V6XQ.js.map +0 -1
- package/dist/chunk-HFOFLW5F.js.map +0 -1
- package/dist/chunk-KGSFAE5B.js +0 -1
- package/dist/chunk-LNL64IJZ.js +0 -1
- package/dist/chunk-MKD2VCX3.js.map +0 -1
- package/dist/chunk-UEYRTLKE.js.map +0 -1
- package/dist/chunk-WQ5MPAVC.js +0 -449
- package/dist/chunk-WQ5MPAVC.js.map +0 -1
- package/dist/chunk-ZEOKPWUC.js +0 -1165
- package/dist/chunk-ZEOKPWUC.js.map +0 -1
- package/dist/pol-attachment-queue-C7YNXXhK.d.ts +0 -676
- package/dist/types-Bgvx7-E8.d.ts +0 -187
- /package/dist/{chunk-DGUM43GV.js.map → chunk-654ERHA7.js.map} +0 -0
- /package/dist/{chunk-GKF7TOMT.js.map → chunk-T4AO7JIG.js.map} +0 -0
- /package/dist/{chunk-KGSFAE5B.js.map → chunk-YHTZ7VMV.js.map} +0 -0
- /package/dist/{chunk-LNL64IJZ.js.map → react/index.js.map} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CrudEntry, i as ClassifiedError, P as PowerSyncBackendConnector, A as AbstractPowerSyncDatabase } from './types-CDqWh56B.js';
|
|
2
1
|
import { SupabaseClient } from '@supabase/supabase-js';
|
|
2
|
+
import { C as CrudEntry, i as ClassifiedError } from './types-CDqWh56B.js';
|
|
3
3
|
import { LoggerAdapter } from './platform/index.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -324,8 +324,10 @@ interface RetryStrategyConfig {
|
|
|
324
324
|
interface RetryConfig {
|
|
325
325
|
/** Retry config for transient errors (network, server 5xx) */
|
|
326
326
|
transient: RetryStrategyConfig;
|
|
327
|
-
/** Retry config for permanent errors (
|
|
327
|
+
/** Retry config for permanent errors (validation, constraints) */
|
|
328
328
|
permanent: RetryStrategyConfig;
|
|
329
|
+
/** Retry config for RLS/permission errors (42501, row-level security violations) */
|
|
330
|
+
rls: RetryStrategyConfig;
|
|
329
331
|
}
|
|
330
332
|
/**
|
|
331
333
|
* Default retry configuration
|
|
@@ -333,193 +335,69 @@ interface RetryConfig {
|
|
|
333
335
|
* Uses fast exponential backoff for transient errors (network issues):
|
|
334
336
|
* - Transient: 1s → 2s → 4s
|
|
335
337
|
*
|
|
336
|
-
*
|
|
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
|
|
337
343
|
* because they will never succeed - fail fast and surface to user.
|
|
338
344
|
* PowerSync's native retry mechanism will re-attempt on next sync cycle.
|
|
339
345
|
*/
|
|
340
346
|
declare const DEFAULT_RETRY_CONFIG: RetryConfig;
|
|
341
|
-
|
|
342
347
|
/**
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
* A generic, configurable connector that handles:
|
|
346
|
-
* - Authentication with Supabase JWT tokens
|
|
347
|
-
* - Uploading local changes back to Supabase
|
|
348
|
-
* - Schema routing for multi-schema databases
|
|
349
|
-
* - Custom CRUD handling for complex operations
|
|
350
|
-
* - Version-based conflict detection (when enabled)
|
|
348
|
+
* Session representation for authentication.
|
|
349
|
+
* Used by AuthProvider to communicate auth state.
|
|
351
350
|
*/
|
|
352
|
-
|
|
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
|
+
}
|
|
353
361
|
/**
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
* This connector handles authentication and CRUD uploads to Supabase.
|
|
357
|
-
* It supports configurable schema routing and custom CRUD handlers
|
|
358
|
-
* for complex use cases.
|
|
362
|
+
* Authentication provider interface.
|
|
363
|
+
* Abstracts auth for the connector - works with any auth backend.
|
|
359
364
|
*
|
|
360
|
-
* @example
|
|
365
|
+
* @example
|
|
361
366
|
* ```typescript
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
* powerSyncUrl: 'https://your-powersync-instance.com',
|
|
365
|
-
* });
|
|
366
|
-
* ```
|
|
367
|
+
* // Using built-in Supabase adapter
|
|
368
|
+
* const auth = createSupabaseAuth(supabaseClient);
|
|
367
369
|
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
370
|
-
*
|
|
371
|
-
*
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
* if (['Profile', 'Comment', 'CommentSection'].includes(table)) {
|
|
375
|
-
* return 'core';
|
|
376
|
-
* }
|
|
377
|
-
* 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 };
|
|
378
376
|
* },
|
|
379
|
-
*
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
* @example With custom CRUD handler
|
|
383
|
-
* ```typescript
|
|
384
|
-
* const connector = new SupabaseConnector({
|
|
385
|
-
* supabaseClient: supabase,
|
|
386
|
-
* powerSyncUrl: 'https://your-powersync-instance.com',
|
|
387
|
-
* crudHandler: {
|
|
388
|
-
* async handlePut(entry, supabase, schema) {
|
|
389
|
-
* // Custom handling for specific tables
|
|
390
|
-
* if (entry.table === 'SpecialTable') {
|
|
391
|
-
* await myCustomUpsert(entry);
|
|
392
|
-
* return true; // Handled
|
|
393
|
-
* }
|
|
394
|
-
* return false; // Use default
|
|
395
|
-
* },
|
|
377
|
+
* onAuthStateChange: (cb) => {
|
|
378
|
+
* return myAuthService.subscribe(cb);
|
|
396
379
|
* },
|
|
397
|
-
* }
|
|
380
|
+
* };
|
|
398
381
|
* ```
|
|
399
382
|
*/
|
|
400
|
-
|
|
401
|
-
private readonly supabase;
|
|
402
|
-
private readonly powerSyncUrl;
|
|
403
|
-
private readonly schemaRouter;
|
|
404
|
-
private readonly crudHandler?;
|
|
405
|
-
private readonly logger?;
|
|
406
|
-
private readonly onTransactionSuccess?;
|
|
407
|
-
private readonly onTransactionFailure?;
|
|
408
|
-
private readonly onTransactionComplete?;
|
|
409
|
-
private readonly shouldUploadFn?;
|
|
410
|
-
private readonly conflictDetection?;
|
|
411
|
-
private readonly conflictHandler?;
|
|
412
|
-
private readonly conflictBus?;
|
|
413
|
-
private versionColumnCache;
|
|
414
|
-
private activeProjectIds;
|
|
415
|
-
private resolvedConflicts;
|
|
416
|
-
private unsubscribeResolution?;
|
|
417
|
-
private versionColumnPromises;
|
|
418
|
-
private isDestroyed;
|
|
419
|
-
private retryConfig;
|
|
420
|
-
private autoRetryPaused;
|
|
421
|
-
constructor(options: SupabaseConnectorOptions);
|
|
422
|
-
/**
|
|
423
|
-
* Clean up resources (unsubscribe from event listeners).
|
|
424
|
-
* Call this when the connector is no longer needed.
|
|
425
|
-
*/
|
|
426
|
-
destroy(): void;
|
|
427
|
-
/**
|
|
428
|
-
* Pause automatic retry of failed uploads.
|
|
429
|
-
* Use this when the user goes offline intentionally or wants manual control.
|
|
430
|
-
*/
|
|
431
|
-
pauseAutoRetry(): void;
|
|
432
|
-
/**
|
|
433
|
-
* Resume automatic retry of failed uploads.
|
|
434
|
-
*/
|
|
435
|
-
resumeAutoRetry(): void;
|
|
436
|
-
/**
|
|
437
|
-
* Process a single CRUD entry with exponential backoff retry.
|
|
438
|
-
*
|
|
439
|
-
* This method uses a two-phase approach:
|
|
440
|
-
* 1. First attempt - try the operation to classify the error type
|
|
441
|
-
* 2. Retry phase - use the appropriate config (transient vs permanent) based on classification
|
|
442
|
-
*
|
|
443
|
-
* This fixes the issue where reassigning selectedConfig inside withExponentialBackoff's
|
|
444
|
-
* callback had no effect because the config was already destructured at call time.
|
|
445
|
-
*
|
|
446
|
-
* @param entry - The CRUD entry to process
|
|
447
|
-
* @throws Error if all retries exhausted (for critical failures)
|
|
448
|
-
*/
|
|
449
|
-
private processWithRetry;
|
|
450
|
-
/**
|
|
451
|
-
* Set the active project IDs for scoped sync.
|
|
452
|
-
* Call this when user selects/opens projects.
|
|
453
|
-
*/
|
|
454
|
-
setActiveProjectIds(projectIds: string[]): void;
|
|
455
|
-
/**
|
|
456
|
-
* Get the current active project IDs.
|
|
457
|
-
*/
|
|
458
|
-
getActiveProjectIds(): string[];
|
|
383
|
+
interface AuthProvider {
|
|
459
384
|
/**
|
|
460
|
-
* Get
|
|
461
|
-
*
|
|
462
|
-
*
|
|
463
|
-
* Note: Token refresh is handled by Supabase's startAutoRefresh() which must be
|
|
464
|
-
* called on app initialization. getSession() returns the auto-refreshed token.
|
|
465
|
-
*/
|
|
466
|
-
fetchCredentials(): Promise<PowerSyncCredentials>;
|
|
467
|
-
/**
|
|
468
|
-
* Upload local changes to Supabase.
|
|
469
|
-
* Called automatically by PowerSync when there are pending uploads.
|
|
470
|
-
*
|
|
471
|
-
* When conflict detection is enabled:
|
|
472
|
-
* 1. Checks if table has _version column (cached)
|
|
473
|
-
* 2. If yes, compares local vs server version
|
|
474
|
-
* 3. On version mismatch, queries AuditLog for field conflicts
|
|
475
|
-
* 4. If conflicts found, calls handler or publishes to conflict bus
|
|
476
|
-
* 5. Applies resolution or skips entry based on handler response
|
|
385
|
+
* Get the current session.
|
|
386
|
+
* @returns Current session or null if not authenticated
|
|
477
387
|
*/
|
|
478
|
-
|
|
388
|
+
getSession(): Promise<Session | null>;
|
|
479
389
|
/**
|
|
480
|
-
*
|
|
481
|
-
*
|
|
482
|
-
*
|
|
483
|
-
* @param context - The finalization context containing results and transaction
|
|
390
|
+
* Refresh the current session.
|
|
391
|
+
* @throws Error if refresh fails (e.g., refresh token expired)
|
|
392
|
+
* @returns New session with fresh access token
|
|
484
393
|
*/
|
|
485
|
-
|
|
394
|
+
refreshSession(): Promise<Session>;
|
|
486
395
|
/**
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
|
|
490
|
-
private processTransaction;
|
|
491
|
-
/**
|
|
492
|
-
* Process batched PUT (upsert) operations for a single table.
|
|
493
|
-
* Falls back to individual processing if batch fails.
|
|
494
|
-
* CRITICAL: Throws on first failure to maintain transaction atomicity.
|
|
495
|
-
* @returns Array of successfully processed entries
|
|
496
|
-
* @throws Error on first failure - keeps entire transaction in ps_crud
|
|
497
|
-
*/
|
|
498
|
-
private processBatchedPuts;
|
|
499
|
-
/**
|
|
500
|
-
* Process batched DELETE operations for a single table.
|
|
501
|
-
* Falls back to individual processing if batch fails.
|
|
502
|
-
* CRITICAL: Throws on first failure to maintain transaction atomicity.
|
|
503
|
-
* @returns Array of successfully processed entries
|
|
504
|
-
* @throws Error on first failure - keeps entire transaction in ps_crud
|
|
505
|
-
*/
|
|
506
|
-
private processBatchedDeletes;
|
|
507
|
-
/**
|
|
508
|
-
* Check if a table has a _version column (cached).
|
|
509
|
-
* P4.1: Uses Promise-based locking to prevent duplicate concurrent queries.
|
|
510
|
-
*/
|
|
511
|
-
private checkVersionColumn;
|
|
512
|
-
/**
|
|
513
|
-
* Filter opData to only include specified fields.
|
|
514
|
-
* Used for partial sync resolution.
|
|
515
|
-
*/
|
|
516
|
-
private filterFields;
|
|
517
|
-
/**
|
|
518
|
-
* Process a single CRUD operation.
|
|
519
|
-
*
|
|
520
|
-
* 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
|
|
521
399
|
*/
|
|
522
|
-
|
|
400
|
+
onAuthStateChange(cb: (session: Session | null) => void): () => void;
|
|
523
401
|
}
|
|
524
402
|
|
|
525
|
-
export { type ConnectorCircuitBreakerConfig as C, DEFAULT_RETRY_CONFIG as D, type FieldConflict as F, type PowerSyncCredentials as P, type RetryStrategyConfig as R,
|
|
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 };
|
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
import { a as BucketConfig } from './types-Bgvx7-E8.js';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Upload Handler Types for @pol-studios/powersync
|
|
5
3
|
*
|
|
6
4
|
* Defines types for platform-specific upload handlers.
|
|
7
5
|
*/
|
|
8
|
-
|
|
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
|
+
}
|
|
9
17
|
/**
|
|
10
18
|
* Options for creating a SupabaseUploadHandler.
|
|
11
19
|
*/
|
|
@@ -49,4 +57,4 @@ interface UploadNotificationConfig {
|
|
|
49
57
|
*/
|
|
50
58
|
declare const DEFAULT_UPLOAD_NOTIFICATION: UploadNotificationConfig;
|
|
51
59
|
|
|
52
|
-
export { DEFAULT_UPLOAD_NOTIFICATION as D, type SupabaseUploadHandlerOptions as S, type UploadEventHandlers as U, type UploadNotificationConfig as a };
|
|
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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pol-studios/powersync",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"description": "Enterprise PowerSync integration for offline-first applications",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -110,6 +110,20 @@
|
|
|
110
110
|
"import": "./dist/error/index.js",
|
|
111
111
|
"types": "./dist/error/index.d.ts"
|
|
112
112
|
}
|
|
113
|
+
},
|
|
114
|
+
"./react": {
|
|
115
|
+
"react-native": {
|
|
116
|
+
"import": "./dist/react/index.js",
|
|
117
|
+
"types": "./dist/react/index.d.ts"
|
|
118
|
+
},
|
|
119
|
+
"browser": {
|
|
120
|
+
"import": "./dist/react/index.js",
|
|
121
|
+
"types": "./dist/react/index.d.ts"
|
|
122
|
+
},
|
|
123
|
+
"default": {
|
|
124
|
+
"import": "./dist/react/index.js",
|
|
125
|
+
"types": "./dist/react/index.d.ts"
|
|
126
|
+
}
|
|
113
127
|
}
|
|
114
128
|
},
|
|
115
129
|
"files": [
|
|
@@ -121,6 +135,9 @@
|
|
|
121
135
|
"typecheck": "tsc --noEmit",
|
|
122
136
|
"prepublishOnly": "pnpm build"
|
|
123
137
|
},
|
|
138
|
+
"dependencies": {
|
|
139
|
+
"@pol-studios/db": "workspace:*"
|
|
140
|
+
},
|
|
124
141
|
"peerDependencies": {
|
|
125
142
|
"@powersync/react-native": ">=1.0.8",
|
|
126
143
|
"@powersync/op-sqlite": ">=0.8.0",
|
|
@@ -176,9 +193,6 @@
|
|
|
176
193
|
"optional": true
|
|
177
194
|
}
|
|
178
195
|
},
|
|
179
|
-
"dependencies": {
|
|
180
|
-
"@pol-studios/db": "workspace:*"
|
|
181
|
-
},
|
|
182
196
|
"devDependencies": {
|
|
183
197
|
"@babel/core": "^7.28.0",
|
|
184
198
|
"@powersync/common": "^1.0.0",
|