@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.
Files changed (99) 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 +709 -6
  4. package/dist/attachments/index.js +133 -5
  5. package/dist/chunk-24RDMMCL.js +44 -0
  6. package/dist/chunk-24RDMMCL.js.map +1 -0
  7. package/dist/chunk-4TXTAEF2.js +2060 -0
  8. package/dist/chunk-4TXTAEF2.js.map +1 -0
  9. package/dist/chunk-63PXSPIN.js +358 -0
  10. package/dist/chunk-63PXSPIN.js.map +1 -0
  11. package/dist/chunk-654ERHA7.js +1 -0
  12. package/dist/{chunk-BREGB4WL.js → chunk-BRXQNASY.js} +287 -335
  13. package/dist/chunk-BRXQNASY.js.map +1 -0
  14. package/dist/{chunk-DHYUBVP7.js → chunk-CAB26E6F.js} +20 -9
  15. package/dist/chunk-CAB26E6F.js.map +1 -0
  16. package/dist/{chunk-H772V6XQ.js → chunk-CUCAYK7Z.js} +7 -43
  17. package/dist/chunk-CUCAYK7Z.js.map +1 -0
  18. package/dist/{chunk-4C3RY5SU.js → chunk-HWSNV45P.js} +76 -1
  19. package/dist/chunk-HWSNV45P.js.map +1 -0
  20. package/dist/{chunk-HFOFLW5F.js → chunk-KN2IZERF.js} +139 -6
  21. package/dist/chunk-KN2IZERF.js.map +1 -0
  22. package/dist/{chunk-UEYRTLKE.js → chunk-P4HZA6ZT.js} +20 -9
  23. package/dist/chunk-P4HZA6ZT.js.map +1 -0
  24. package/dist/chunk-T4AO7JIG.js +1 -0
  25. package/dist/{chunk-XQAJM2MW.js → chunk-VACPAAQZ.js} +33 -2
  26. package/dist/{chunk-XQAJM2MW.js.map → chunk-VACPAAQZ.js.map} +1 -1
  27. package/dist/{chunk-53WH2JJV.js → chunk-WN5ZJ3E2.js} +5 -8
  28. package/dist/chunk-WN5ZJ3E2.js.map +1 -0
  29. package/dist/chunk-XAEII4ZX.js +456 -0
  30. package/dist/chunk-XAEII4ZX.js.map +1 -0
  31. package/dist/chunk-XOY2CJ67.js +289 -0
  32. package/dist/chunk-XOY2CJ67.js.map +1 -0
  33. package/dist/chunk-YHTZ7VMV.js +1 -0
  34. package/dist/{chunk-MKD2VCX3.js → chunk-Z6VOBGTU.js} +8 -8
  35. package/dist/chunk-Z6VOBGTU.js.map +1 -0
  36. package/dist/chunk-ZM4ENYMF.js +230 -0
  37. package/dist/chunk-ZM4ENYMF.js.map +1 -0
  38. package/dist/connector/index.d.ts +56 -3
  39. package/dist/connector/index.js +8 -5
  40. package/dist/core/index.d.ts +12 -1
  41. package/dist/core/index.js +3 -2
  42. package/dist/error/index.js +0 -1
  43. package/dist/index.d.ts +12 -10
  44. package/dist/index.js +191 -29
  45. package/dist/index.native.d.ts +11 -9
  46. package/dist/index.native.js +191 -29
  47. package/dist/index.web.d.ts +11 -9
  48. package/dist/index.web.js +191 -29
  49. package/dist/maintenance/index.js +0 -1
  50. package/dist/platform/index.js +0 -2
  51. package/dist/platform/index.js.map +1 -1
  52. package/dist/platform/index.native.js +1 -2
  53. package/dist/platform/index.web.js +0 -1
  54. package/dist/pol-attachment-queue-BVAIueoP.d.ts +817 -0
  55. package/dist/provider/index.d.ts +38 -34
  56. package/dist/provider/index.js +11 -12
  57. package/dist/react/index.d.ts +372 -0
  58. package/dist/react/index.js +25 -0
  59. package/dist/storage/index.d.ts +3 -3
  60. package/dist/storage/index.js +22 -8
  61. package/dist/storage/index.native.d.ts +3 -3
  62. package/dist/storage/index.native.js +21 -7
  63. package/dist/storage/index.web.d.ts +3 -3
  64. package/dist/storage/index.web.js +21 -7
  65. package/dist/storage/upload/index.d.ts +7 -8
  66. package/dist/storage/upload/index.js +3 -3
  67. package/dist/storage/upload/index.native.d.ts +7 -8
  68. package/dist/storage/upload/index.native.js +4 -3
  69. package/dist/storage/upload/index.web.d.ts +1 -4
  70. package/dist/storage/upload/index.web.js +3 -3
  71. package/dist/supabase-connector-T9vHq_3i.d.ts +202 -0
  72. package/dist/sync/index.js +3 -3
  73. package/dist/{supabase-connector-qLm-WHkM.d.ts → types-B212hgfA.d.ts} +48 -170
  74. package/dist/{types-BVacP54t.d.ts → types-CyvBaAl8.d.ts} +12 -4
  75. package/dist/types-D0WcHrq6.d.ts +234 -0
  76. package/package.json +18 -4
  77. package/dist/CacheSettingsManager-1exbOC6S.d.ts +0 -261
  78. package/dist/chunk-4C3RY5SU.js.map +0 -1
  79. package/dist/chunk-53WH2JJV.js.map +0 -1
  80. package/dist/chunk-BREGB4WL.js.map +0 -1
  81. package/dist/chunk-DGUM43GV.js +0 -11
  82. package/dist/chunk-DHYUBVP7.js.map +0 -1
  83. package/dist/chunk-GKF7TOMT.js +0 -1
  84. package/dist/chunk-H772V6XQ.js.map +0 -1
  85. package/dist/chunk-HFOFLW5F.js.map +0 -1
  86. package/dist/chunk-KGSFAE5B.js +0 -1
  87. package/dist/chunk-LNL64IJZ.js +0 -1
  88. package/dist/chunk-MKD2VCX3.js.map +0 -1
  89. package/dist/chunk-UEYRTLKE.js.map +0 -1
  90. package/dist/chunk-WQ5MPAVC.js +0 -449
  91. package/dist/chunk-WQ5MPAVC.js.map +0 -1
  92. package/dist/chunk-ZEOKPWUC.js +0 -1165
  93. package/dist/chunk-ZEOKPWUC.js.map +0 -1
  94. package/dist/pol-attachment-queue-C7YNXXhK.d.ts +0 -676
  95. package/dist/types-Bgvx7-E8.d.ts +0 -187
  96. /package/dist/{chunk-DGUM43GV.js.map → chunk-654ERHA7.js.map} +0 -0
  97. /package/dist/{chunk-GKF7TOMT.js.map → chunk-T4AO7JIG.js.map} +0 -0
  98. /package/dist/{chunk-KGSFAE5B.js.map → chunk-YHTZ7VMV.js.map} +0 -0
  99. /package/dist/{chunk-LNL64IJZ.js.map → react/index.js.map} +0 -0
@@ -1,261 +0,0 @@
1
- import { FileSystemAdapter, LoggerAdapter, AsyncStorageAdapter } from './platform/index.js';
2
- import { R as RemoteStorageAdapter, P as PowerSyncStorageAdapter, b as SupabaseStorageAdapterOptions } from './types-Bgvx7-E8.js';
3
-
4
- /**
5
- * Supabase Storage Adapter for @pol-studios/powersync
6
- *
7
- * Provides attachment storage operations using Supabase Storage with
8
- * platform-agnostic file system operations via PlatformAdapter.
9
- *
10
- * Key features:
11
- * - Memory-efficient downloads using signed URLs + native file system
12
- * - Multi-bucket support via BucketConfig/BucketResolver
13
- * - Platform-agnostic via FileSystemAdapter interface
14
- * - Compatible with PowerSync attachments interface
15
- */
16
-
17
- /**
18
- * Supabase Storage adapter for attachment downloads and local file operations.
19
- *
20
- * Uses PlatformAdapter's fileSystem for I/O operations to remain platform-agnostic.
21
- *
22
- * IMPORTANT: This adapter downloads files using signed URLs + platform file system
23
- * operations to avoid loading entire files into memory. This prevents OOM crashes
24
- * on large files that occurred with the previous blob-based approach.
25
- *
26
- * @example
27
- * ```typescript
28
- * const adapter = new SupabaseStorageAdapter(
29
- * {
30
- * client: supabaseClient,
31
- * bucketConfig: {
32
- * defaultBucket: 'attachments',
33
- * bucketMap: new Map([['avatars/', 'user-avatars']]),
34
- * },
35
- * },
36
- * platform.fileSystem
37
- * );
38
- *
39
- * // Download to local path
40
- * await adapter.download('photos/image.jpg', '/local/path/image.jpg');
41
- *
42
- * // Get signed URL for direct access
43
- * const url = await adapter.getDownloadUrl('photos/image.jpg');
44
- * ```
45
- */
46
- declare class SupabaseStorageAdapter implements RemoteStorageAdapter, PowerSyncStorageAdapter {
47
- private client;
48
- private bucketConfig;
49
- private signedUrlExpiry;
50
- private fileSystem?;
51
- private logger?;
52
- constructor(options: SupabaseStorageAdapterOptions, fileSystem?: FileSystemAdapter);
53
- /**
54
- * Set the file system adapter (can be set after construction).
55
- */
56
- setFileSystem(fileSystem: FileSystemAdapter): void;
57
- /**
58
- * Resolve the storage bucket for a given file path.
59
- */
60
- resolveBucket(filePath: string): string;
61
- /**
62
- * Download a file from Supabase Storage to a local path.
63
- *
64
- * Uses the platform's streaming downloadFile method to avoid loading
65
- * the entire file into memory (prevents OOM on large files).
66
- */
67
- download(remotePath: string, localPath: string): Promise<void>;
68
- /**
69
- * Get a signed download URL for a remote file.
70
- */
71
- getDownloadUrl(remotePath: string): Promise<string>;
72
- /**
73
- * Check if a file exists in remote storage.
74
- */
75
- exists(remotePath: string): Promise<boolean>;
76
- /**
77
- * No-op for uploads. Use SupabaseUploadHandler for upload operations.
78
- *
79
- * Uploads are handled separately by the upload manager pipeline to support
80
- * background uploads and proper queue management.
81
- */
82
- uploadFile(filename: string, _data: ArrayBuffer, _options?: {
83
- mediaType?: string;
84
- }): Promise<void>;
85
- /**
86
- * Download a file from Supabase Storage and return as a Blob.
87
- *
88
- * Uses signed URL + fetch to download the file efficiently.
89
- * This method is required by the PowerSync attachments interface.
90
- *
91
- * Note: This loads the file into memory as a Blob. For very large files,
92
- * consider using download() to save directly to disk instead.
93
- */
94
- downloadFile(filePath: string): Promise<Blob>;
95
- /**
96
- * Write data to a local file.
97
- */
98
- writeFile(fileURI: string, data: string, options?: {
99
- encoding?: 'utf8' | 'base64';
100
- }): Promise<void>;
101
- /**
102
- * Read data from a local file.
103
- */
104
- readFile(fileURI: string, options?: {
105
- encoding?: 'utf8' | 'base64';
106
- mediaType?: string;
107
- }): Promise<ArrayBuffer>;
108
- /**
109
- * Delete a local file.
110
- */
111
- deleteFile(uri: string, _options?: {
112
- filename?: string;
113
- }): Promise<void>;
114
- /**
115
- * Check if a local file exists.
116
- */
117
- fileExists(fileURI: string): Promise<boolean>;
118
- /**
119
- * Create a directory.
120
- */
121
- makeDir(uri: string): Promise<void>;
122
- /**
123
- * Copy a file.
124
- */
125
- copyFile(sourceUri: string, targetUri: string): Promise<void>;
126
- /**
127
- * Get the user storage directory.
128
- */
129
- getUserStorageDirectory(): string;
130
- }
131
- /**
132
- * Create a SupabaseStorageAdapter with simplified configuration.
133
- *
134
- * @example
135
- * ```typescript
136
- * const adapter = createSupabaseStorageAdapter(
137
- * supabaseClient,
138
- * 'attachments',
139
- * platform.fileSystem
140
- * );
141
- * ```
142
- */
143
- declare function createSupabaseStorageAdapter(client: any, defaultBucket: string, fileSystem?: FileSystemAdapter, options?: {
144
- bucketMap?: Map<string, string>;
145
- signedUrlExpiry?: number;
146
- logger?: LoggerAdapter;
147
- }): SupabaseStorageAdapter;
148
-
149
- /**
150
- * Cache Settings Types for @pol-studios/powersync
151
- *
152
- * Defines types for cache configuration storage.
153
- * Note: UI-specific options (labels, descriptions) should be defined in the app.
154
- */
155
- /**
156
- * Cache settings stored via AsyncStorageAdapter.
157
- */
158
- interface CacheSettings {
159
- /**
160
- * Maximum cache size in megabytes.
161
- * A value of 0 indicates unlimited cache size.
162
- */
163
- maxCacheSizeMb: number;
164
- /**
165
- * Compression quality for cached images (0.0 to 1.0).
166
- * Higher values mean better quality but larger file sizes.
167
- */
168
- compressionQuality: number;
169
- }
170
- /**
171
- * Options for creating a CacheSettingsManager.
172
- */
173
- interface CacheSettingsManagerOptions {
174
- /**
175
- * Prefix for storage keys.
176
- * Useful for namespacing when multiple apps share storage.
177
- * @default '@pol-studios/cache'
178
- */
179
- storageKeyPrefix?: string;
180
- /**
181
- * Default values for cache settings.
182
- */
183
- defaults?: Partial<CacheSettings>;
184
- }
185
- /**
186
- * Default cache settings values.
187
- */
188
- declare const DEFAULT_CACHE_SETTINGS: CacheSettings;
189
-
190
- /**
191
- * Cache Settings Manager for @pol-studios/powersync
192
- *
193
- * Manages persistence of cache settings via AsyncStorageAdapter.
194
- * Uses platform-agnostic storage interface for cross-platform support.
195
- */
196
-
197
- /**
198
- * Manages cache settings persistence using AsyncStorageAdapter.
199
- *
200
- * @example
201
- * ```typescript
202
- * const manager = new CacheSettingsManager(platform.storage, {
203
- * storageKeyPrefix: '@myapp/cache',
204
- * defaults: { maxCacheSizeMb: 2048 },
205
- * });
206
- *
207
- * const settings = await manager.getSettings();
208
- * await manager.setMaxCacheSizeMb(1024);
209
- * ```
210
- */
211
- declare class CacheSettingsManager {
212
- private storage;
213
- private keyPrefix;
214
- private defaults;
215
- constructor(storage: AsyncStorageAdapter, options?: CacheSettingsManagerOptions);
216
- /**
217
- * Get the full storage key for a setting.
218
- */
219
- private getKey;
220
- /**
221
- * Get all cache settings.
222
- */
223
- getSettings(): Promise<CacheSettings>;
224
- /**
225
- * Get the maximum cache size in megabytes.
226
- * Returns 0 for unlimited.
227
- */
228
- getMaxCacheSizeMb(): Promise<number>;
229
- /**
230
- * Set the maximum cache size in megabytes.
231
- * Use 0 for unlimited.
232
- *
233
- * @param mb - Maximum cache size in megabytes
234
- */
235
- setMaxCacheSizeMb(mb: number): Promise<void>;
236
- /**
237
- * Get the maximum cache size in bytes.
238
- * Returns Number.MAX_SAFE_INTEGER for unlimited.
239
- */
240
- getMaxCacheSizeBytes(): Promise<number>;
241
- /**
242
- * Get the compression quality (0.0 to 1.0).
243
- */
244
- getCompressionQuality(): Promise<number>;
245
- /**
246
- * Set the compression quality.
247
- *
248
- * @param quality - Compression quality (0.0 to 1.0)
249
- */
250
- setCompressionQuality(quality: number): Promise<void>;
251
- /**
252
- * Reset all settings to defaults.
253
- */
254
- resetToDefaults(): Promise<void>;
255
- /**
256
- * Clear all stored settings.
257
- */
258
- clear(): Promise<void>;
259
- }
260
-
261
- export { CacheSettingsManager as C, DEFAULT_CACHE_SETTINGS as D, SupabaseStorageAdapter as S, type CacheSettings as a, type CacheSettingsManagerOptions as b, createSupabaseStorageAdapter as c };
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/connector/circuit-breaker.ts"],"sourcesContent":["/**\n * Circuit Breaker Pattern for PowerSync Connector\n *\n * Prevents cascading failures by temporarily stopping requests when\n * a service is experiencing high failure rates.\n *\n * States:\n * - CLOSED: Normal operation, requests flow through\n * - OPEN: Service is failing, requests are blocked\n * - HALF_OPEN: Testing if service has recovered\n *\n * Transitions:\n * - CLOSED -> OPEN: After failureThreshold failures within failureWindowMs\n * - OPEN -> HALF_OPEN: After timeout (exponential backoff)\n * - HALF_OPEN -> CLOSED: On successful request\n * - HALF_OPEN -> OPEN: On failed request (with reset backoff multiplier)\n */\n\n/**\n * Circuit breaker states\n */\nexport type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';\n\n/**\n * Configuration for the circuit breaker\n */\nexport interface CircuitBreakerConfig {\n /**\n * Number of failures required to trip the circuit\n * @default 5\n */\n failureThreshold: number;\n\n /**\n * Time window in ms for counting failures\n * @default 60000 (60 seconds)\n */\n failureWindowMs: number;\n\n /**\n * Initial delay before transitioning from OPEN to HALF_OPEN\n * @default 1000 (1 second)\n */\n initialRecoveryDelayMs: number;\n\n /**\n * Maximum delay for exponential backoff\n * @default 32000 (32 seconds)\n */\n maxRecoveryDelayMs: number;\n\n /**\n * Multiplier for exponential backoff\n * @default 2\n */\n backoffMultiplier: number;\n\n /**\n * Optional callback when state changes\n */\n onStateChange?: (state: CircuitState, previousState: CircuitState) => void;\n\n /**\n * Optional logger\n */\n logger?: {\n debug: (...args: unknown[]) => void;\n info: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n };\n}\n\n/**\n * Default circuit breaker configuration\n */\nexport const DEFAULT_CIRCUIT_BREAKER_CONFIG: CircuitBreakerConfig = {\n failureThreshold: 5,\n failureWindowMs: 60000,\n initialRecoveryDelayMs: 1000,\n maxRecoveryDelayMs: 32000,\n backoffMultiplier: 2\n};\n\n/**\n * Statistics about the circuit breaker state\n */\nexport interface CircuitBreakerStats {\n /** Current state */\n state: CircuitState;\n /** Number of failures in current window */\n failureCount: number;\n /** Number of successful requests since last state change */\n successCount: number;\n /** Number of times circuit has opened */\n openCount: number;\n /** Time when circuit last opened */\n lastOpenedAt: Date | null;\n /** Time when circuit last closed */\n lastClosedAt: Date | null;\n /** Current recovery delay (when OPEN) */\n currentRecoveryDelayMs: number;\n /** Time until next HALF_OPEN attempt (when OPEN) */\n timeUntilHalfOpenMs: number | null;\n}\n\n/**\n * Error thrown when circuit is open\n */\nexport class CircuitOpenError extends Error {\n constructor(public readonly timeUntilRetryMs: number, public readonly stats: CircuitBreakerStats) {\n super(`Circuit breaker is OPEN. Service is unavailable. ` + `Retry in ${Math.ceil(timeUntilRetryMs / 1000)}s after ${stats.openCount} failures.`);\n this.name = 'CircuitOpenError';\n }\n}\n\n/**\n * Circuit Breaker implementation\n *\n * @example\n * ```typescript\n * const breaker = new CircuitBreaker({\n * failureThreshold: 5,\n * failureWindowMs: 60000,\n * onStateChange: (state) => console.log('Circuit state:', state),\n * });\n *\n * // Wrap your async operations\n * try {\n * const result = await breaker.execute(() => fetchData());\n * } catch (error) {\n * if (error instanceof CircuitOpenError) {\n * console.log('Service unavailable, retry later');\n * }\n * }\n * ```\n */\nexport class CircuitBreaker {\n private state: CircuitState = 'CLOSED';\n private failures: number[] = []; // Timestamps of failures within window\n private successCount = 0;\n private openCount = 0;\n private lastOpenedAt: Date | null = null;\n private lastClosedAt: Date | null = null;\n private currentRecoveryDelay: number;\n private halfOpenTimer: ReturnType<typeof setTimeout> | null = null;\n private halfOpenScheduledAt: number | null = null;\n private readonly config: Required<Pick<CircuitBreakerConfig, 'failureThreshold' | 'failureWindowMs' | 'initialRecoveryDelayMs' | 'maxRecoveryDelayMs' | 'backoffMultiplier'>> & Pick<CircuitBreakerConfig, 'onStateChange' | 'logger'>;\n constructor(config: Partial<CircuitBreakerConfig> = {}) {\n this.config = {\n ...DEFAULT_CIRCUIT_BREAKER_CONFIG,\n ...config\n };\n this.currentRecoveryDelay = this.config.initialRecoveryDelayMs;\n }\n\n /**\n * Get current state\n */\n getState(): CircuitState {\n return this.state;\n }\n\n /**\n * Get circuit breaker statistics\n */\n getStats(): CircuitBreakerStats {\n return {\n state: this.state,\n failureCount: this.failures.length,\n successCount: this.successCount,\n openCount: this.openCount,\n lastOpenedAt: this.lastOpenedAt,\n lastClosedAt: this.lastClosedAt,\n currentRecoveryDelayMs: this.currentRecoveryDelay,\n timeUntilHalfOpenMs: this.getTimeUntilHalfOpen()\n };\n }\n\n /**\n * Check if requests are allowed through the circuit\n */\n isAllowed(): boolean {\n this.cleanupOldFailures();\n switch (this.state) {\n case 'CLOSED':\n return true;\n case 'HALF_OPEN':\n return true;\n // Allow test request\n case 'OPEN':\n return false;\n }\n }\n\n /**\n * Check if request can proceed, throws if not\n */\n checkAllowed(): void {\n if (!this.isAllowed()) {\n throw new CircuitOpenError(this.getTimeUntilHalfOpen() ?? 0, this.getStats());\n }\n }\n\n /**\n * Record a successful operation\n */\n recordSuccess(): void {\n this.successCount++;\n if (this.state === 'HALF_OPEN') {\n // Success in HALF_OPEN means service is recovered\n this.transition('CLOSED');\n this.currentRecoveryDelay = this.config.initialRecoveryDelayMs;\n this.failures = [];\n }\n this.log('debug', '[CircuitBreaker] Success recorded, state:', this.state);\n }\n\n /**\n * Record a failed operation\n */\n recordFailure(): void {\n const now = Date.now();\n this.failures.push(now);\n this.cleanupOldFailures();\n if (this.state === 'HALF_OPEN') {\n // Failure in HALF_OPEN means service is still down\n this.transition('OPEN');\n this.scheduleHalfOpen();\n return;\n }\n if (this.state === 'CLOSED') {\n // Check if threshold exceeded\n if (this.failures.length >= this.config.failureThreshold) {\n this.log('warn', `[CircuitBreaker] Failure threshold (${this.config.failureThreshold}) ` + `exceeded in ${this.config.failureWindowMs}ms window. Opening circuit.`);\n this.transition('OPEN');\n this.scheduleHalfOpen();\n }\n }\n }\n\n /**\n * Execute an async operation through the circuit breaker\n */\n async execute<T>(operation: () => Promise<T>): Promise<T> {\n this.checkAllowed();\n try {\n const result = await operation();\n this.recordSuccess();\n return result;\n } catch (error) {\n this.recordFailure();\n throw error;\n }\n }\n\n /**\n * Manually reset the circuit breaker to CLOSED state\n */\n reset(): void {\n this.clearHalfOpenTimer();\n this.failures = [];\n this.successCount = 0;\n this.currentRecoveryDelay = this.config.initialRecoveryDelayMs;\n this.transition('CLOSED');\n }\n\n /**\n * Force the circuit to OPEN state (e.g., for manual intervention)\n */\n forceOpen(): void {\n this.clearHalfOpenTimer();\n this.transition('OPEN');\n this.scheduleHalfOpen();\n }\n\n /**\n * Dispose the circuit breaker (clear timers)\n */\n dispose(): void {\n this.clearHalfOpenTimer();\n }\n\n // ─── Private Methods ─────────────────────────────────────────────────────────\n\n private transition(newState: CircuitState): void {\n if (this.state === newState) return;\n const previousState = this.state;\n this.state = newState;\n if (newState === 'OPEN') {\n this.openCount++;\n this.lastOpenedAt = new Date();\n // Exponential backoff for repeated failures\n this.currentRecoveryDelay = Math.min(this.currentRecoveryDelay * this.config.backoffMultiplier, this.config.maxRecoveryDelayMs);\n } else if (newState === 'CLOSED') {\n this.lastClosedAt = new Date();\n this.successCount = 0;\n }\n this.log('info', `[CircuitBreaker] State transition: ${previousState} -> ${newState}`);\n this.config.onStateChange?.(newState, previousState);\n }\n private scheduleHalfOpen(): void {\n this.clearHalfOpenTimer();\n this.halfOpenScheduledAt = Date.now() + this.currentRecoveryDelay;\n this.log('debug', `[CircuitBreaker] Scheduling HALF_OPEN in ${this.currentRecoveryDelay}ms`);\n this.halfOpenTimer = setTimeout(() => {\n this.halfOpenTimer = null;\n this.halfOpenScheduledAt = null;\n this.transition('HALF_OPEN');\n this.log('info', '[CircuitBreaker] Circuit is now HALF_OPEN, allowing test request');\n }, this.currentRecoveryDelay);\n }\n private clearHalfOpenTimer(): void {\n if (this.halfOpenTimer) {\n clearTimeout(this.halfOpenTimer);\n this.halfOpenTimer = null;\n this.halfOpenScheduledAt = null;\n }\n }\n private getTimeUntilHalfOpen(): number | null {\n if (this.state !== 'OPEN' || !this.halfOpenScheduledAt) {\n return null;\n }\n return Math.max(0, this.halfOpenScheduledAt - Date.now());\n }\n private cleanupOldFailures(): void {\n const cutoff = Date.now() - this.config.failureWindowMs;\n this.failures = this.failures.filter(timestamp => timestamp > cutoff);\n }\n private log(level: 'debug' | 'info' | 'warn' | 'error', ...args: unknown[]): void {\n this.config.logger?.[level]?.(...args);\n }\n}"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/platform/index.native.ts"],"sourcesContent":["/**\n * React Native Platform Adapter for @pol-studios/powersync\n *\n * Implements the PlatformAdapter interface using React Native specific APIs:\n * - @powersync/react-native for SQLite database\n * - expo-file-system for file operations (new class-based API)\n * - @react-native-async-storage/async-storage for key-value storage\n * - @react-native-community/netinfo for network monitoring\n * - expo-image-manipulator for image compression\n */\n\nimport type { PlatformAdapter, DatabaseOptions, FileSystemAdapter, AsyncStorageAdapter, NetworkAdapter, LoggerAdapter, ImageProcessorAdapter, FileInfo, CompressedImage, CompressionOptions, ConnectionType } from './types';\nimport type { AbstractPowerSyncDatabase } from '../core/types';\n\n// Import new expo-file-system API types\nimport type { File as ExpoFile, Directory as ExpoDirectory, Paths as ExpoPaths } from 'expo-file-system';\n\n/**\n * Create a React Native platform adapter\n *\n * @param logger - Logger implementation to use\n * @returns Platform adapter configured for React Native\n *\n * @example\n * ```typescript\n * import { createNativePlatformAdapter } from '@pol-studios/powersync/platform';\n *\n * const logger = {\n * debug: console.log,\n * info: console.log,\n * warn: console.warn,\n * error: console.error,\n * };\n *\n * const platform = createNativePlatformAdapter(logger);\n * ```\n */\nexport function createNativePlatformAdapter(logger: LoggerAdapter): PlatformAdapter {\n // Lazy imports to avoid loading these modules until needed\n // This also helps with tree-shaking in web builds\n let PowerSyncDatabase: typeof import('@powersync/react-native').PowerSyncDatabase;\n let OPSqliteOpenFactory: typeof import('@powersync/op-sqlite').OPSqliteOpenFactory;\n // New expo-file-system API classes\n let File: typeof ExpoFile;\n let Directory: typeof ExpoDirectory;\n let Paths: typeof ExpoPaths;\n let AsyncStorage: typeof import('@react-native-async-storage/async-storage').default;\n let NetInfo: typeof import('@react-native-community/netinfo').default;\n let ImageManipulator: typeof import('expo-image-manipulator');\n const loadDependencies = async () => {\n if (!PowerSyncDatabase) {\n const psModule = await import('@powersync/react-native');\n PowerSyncDatabase = psModule.PowerSyncDatabase;\n }\n if (!OPSqliteOpenFactory) {\n const opSqliteModule = await import('@powersync/op-sqlite');\n OPSqliteOpenFactory = opSqliteModule.OPSqliteOpenFactory;\n }\n if (!File || !Directory || !Paths) {\n const fsModule = await import('expo-file-system');\n File = fsModule.File;\n Directory = fsModule.Directory;\n Paths = fsModule.Paths;\n }\n if (!AsyncStorage) {\n const asModule = await import('@react-native-async-storage/async-storage');\n AsyncStorage = asModule.default;\n }\n if (!NetInfo) {\n const niModule = await import('@react-native-community/netinfo');\n NetInfo = niModule.default;\n }\n if (!ImageManipulator) {\n ImageManipulator = await import('expo-image-manipulator');\n }\n };\n\n // File system adapter implementation using new expo-file-system class-based API\n const fileSystem: FileSystemAdapter = {\n async readFile(uri: string, encoding: 'base64' | 'utf8' = 'utf8'): Promise<string> {\n if (!File) await loadDependencies();\n const file = new File!(uri);\n if (encoding === 'base64') {\n return file.base64();\n }\n return file.text();\n },\n async writeFile(uri: string, data: string, encoding: 'base64' | 'utf8' = 'utf8'): Promise<void> {\n if (!File || !Directory) await loadDependencies();\n // Ensure parent directory exists (use idempotent to avoid errors if exists)\n const parentDir = uri.substring(0, uri.lastIndexOf('/'));\n if (parentDir) {\n const dir = new Directory!(parentDir);\n dir.create({\n intermediates: true,\n idempotent: true\n });\n }\n const file = new File!(uri);\n if (encoding === 'base64') {\n // Decode base64 to binary and write as Uint8Array\n const binaryString = atob(data);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n file.write(bytes);\n } else {\n // Write text directly\n file.write(data);\n }\n },\n async deleteFile(uri: string): Promise<void> {\n if (!File) await loadDependencies();\n const file = new File!(uri);\n try {\n if (file.exists) {\n file.delete();\n }\n } catch {\n // File may not exist, treat as idempotent\n }\n },\n async copyFile(source: string, destination: string): Promise<void> {\n if (!File) await loadDependencies();\n const sourceFile = new File!(source);\n const destFile = new File!(destination);\n sourceFile.copy(destFile);\n },\n async moveFile(source: string, destination: string): Promise<void> {\n if (!File) await loadDependencies();\n const sourceFile = new File!(source);\n const destFile = new File!(destination);\n sourceFile.move(destFile);\n },\n async getFileInfo(uri: string): Promise<FileInfo | null> {\n if (!File || !Paths) await loadDependencies();\n try {\n // Use Paths.info() to check if it's a directory or file\n const pathInfo = Paths!.info(uri);\n if (!pathInfo.exists) return null;\n if (pathInfo.isDirectory) {\n const dir = new Directory!(uri);\n const dirInfo = dir.info();\n return {\n exists: true,\n size: dirInfo.size ?? 0,\n isDirectory: true,\n modificationTime: dirInfo.modificationTime ? new Date(dirInfo.modificationTime) : undefined\n };\n } else {\n const file = new File!(uri);\n const fileInfo = file.info();\n return {\n exists: true,\n size: fileInfo.size ?? 0,\n isDirectory: false,\n modificationTime: fileInfo.modificationTime ? new Date(fileInfo.modificationTime) : undefined\n };\n }\n } catch {\n return null;\n }\n },\n async makeDirectory(uri: string, options?: {\n intermediates?: boolean;\n }): Promise<void> {\n if (!Directory) await loadDependencies();\n const dir = new Directory!(uri);\n dir.create({\n intermediates: options?.intermediates ?? true,\n idempotent: true\n });\n },\n getDocumentsDirectory(): string {\n if (!Paths) {\n throw new Error('[Platform] Paths not loaded. Call an async method first to initialize dependencies.');\n }\n // Ensure trailing slash for consistency with legacy FileSystem.documentDirectory\n const dir = Paths.document.uri;\n return dir.endsWith('/') ? dir : `${dir}/`;\n },\n getCacheDirectory(): string {\n if (!Paths) {\n throw new Error('[Platform] Paths not loaded. Call an async method first to initialize dependencies.');\n }\n // Ensure trailing slash for consistency with legacy FileSystem.cacheDirectory\n const dir = Paths.cache.uri;\n return dir.endsWith('/') ? dir : `${dir}/`;\n },\n async getFreeDiskSpace(): Promise<number> {\n if (!Paths) await loadDependencies();\n // New API provides this as a property on Paths\n return Paths!.availableDiskSpace;\n },\n async downloadFile(url: string, localPath: string): Promise<void> {\n if (!File || !Directory) await loadDependencies();\n\n // Ensure parent directory exists\n const parentDir = localPath.substring(0, localPath.lastIndexOf('/'));\n if (parentDir) {\n const dir = new Directory!(parentDir);\n dir.create({\n intermediates: true,\n idempotent: true\n });\n }\n\n // Use expo-file-system's downloadAsync for memory-efficient streaming download\n const {\n downloadAsync\n } = await import('expo-file-system');\n const result = await downloadAsync(url, localPath);\n if (result.status !== 200) {\n throw new Error(`Download failed with status ${result.status}: ${url}`);\n }\n }\n };\n\n // Async storage adapter implementation\n const storage: AsyncStorageAdapter = {\n async getItem(key: string): Promise<string | null> {\n if (!AsyncStorage) await loadDependencies();\n return AsyncStorage!.getItem(key);\n },\n async setItem(key: string, value: string): Promise<void> {\n if (!AsyncStorage) await loadDependencies();\n await AsyncStorage!.setItem(key, value);\n },\n async removeItem(key: string): Promise<void> {\n if (!AsyncStorage) await loadDependencies();\n await AsyncStorage!.removeItem(key);\n },\n async multiGet(keys: string[]): Promise<[string, string | null][]> {\n if (!AsyncStorage) await loadDependencies();\n const result = await AsyncStorage!.multiGet(keys);\n return result as [string, string | null][];\n },\n async multiSet(entries: [string, string][]): Promise<void> {\n if (!AsyncStorage) await loadDependencies();\n await AsyncStorage!.multiSet(entries);\n }\n };\n\n // Network adapter implementation\n const network: NetworkAdapter = {\n async isConnected(): Promise<boolean> {\n if (!NetInfo) await loadDependencies();\n const state = await NetInfo!.fetch();\n return state.isConnected ?? false;\n },\n async getConnectionType(): Promise<ConnectionType> {\n if (!NetInfo) await loadDependencies();\n const state = await NetInfo!.fetch();\n const type = state.type;\n if (type === 'wifi') return 'wifi';\n if (type === 'cellular') return 'cellular';\n if (type === 'ethernet') return 'ethernet';\n if (type === 'none') return 'none';\n return 'unknown';\n },\n addConnectionListener(callback: (isConnected: boolean) => void): () => void {\n if (!NetInfo) {\n logger.warn('[Platform] NetInfo not loaded, setting up listener asynchronously');\n let realUnsubscribe: (() => void) | null = null;\n let cancelled = false;\n loadDependencies().then(() => {\n if (cancelled) return;\n realUnsubscribe = NetInfo!.addEventListener(state => {\n callback(state.isConnected ?? false);\n });\n });\n return () => {\n cancelled = true;\n realUnsubscribe?.();\n };\n }\n const unsubscribe = NetInfo.addEventListener(state => {\n callback(state.isConnected ?? false);\n });\n return unsubscribe;\n }\n };\n\n // Image processor adapter implementation\n const imageProcessor: ImageProcessorAdapter = {\n async compress(uri: string, options: CompressionOptions): Promise<CompressedImage> {\n if (!ImageManipulator) await loadDependencies();\n const actions: import('expo-image-manipulator').Action[] = [];\n\n // Add resize action if maxWidth or maxHeight specified\n if (options.maxWidth || options.maxHeight) {\n actions.push({\n resize: {\n width: options.maxWidth,\n height: options.maxHeight\n }\n });\n }\n\n // Determine output format\n let format: import('expo-image-manipulator').SaveFormat;\n switch (options.format) {\n case 'png':\n format = ImageManipulator!.SaveFormat.PNG;\n break;\n case 'webp':\n format = ImageManipulator!.SaveFormat.WEBP;\n break;\n case 'jpeg':\n default:\n format = ImageManipulator!.SaveFormat.JPEG;\n break;\n }\n const result = await ImageManipulator!.manipulateAsync(uri, actions, {\n compress: options.quality,\n format\n });\n return {\n uri: result.uri,\n width: result.width,\n height: result.height\n };\n }\n };\n\n // Main platform adapter\n return {\n async createDatabase(options: DatabaseOptions): Promise<AbstractPowerSyncDatabase> {\n if (!PowerSyncDatabase) await loadDependencies();\n logger.info('[Platform] Creating PowerSync database:', options.dbFilename);\n const db = new PowerSyncDatabase!({\n schema: options.schema as any,\n database: new OPSqliteOpenFactory!({\n dbFilename: options.dbFilename\n })\n });\n logger.info('[Platform] Initializing database...');\n await db.init();\n\n // Verify database is queryable before returning\n // This prevents race conditions where db.connect() is called before SQLite is truly ready\n const maxAttempts = 3;\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n await db.get('SELECT 1');\n logger.info('[Platform] Database initialized and verified');\n return db as unknown as AbstractPowerSyncDatabase;\n } catch (err) {\n if (attempt < maxAttempts - 1) {\n logger.warn(`[Platform] Database readiness check failed (attempt ${attempt + 1}/${maxAttempts}), retrying...`);\n await new Promise(r => setTimeout(r, 100 * Math.pow(2, attempt))); // 100ms, 200ms, 400ms\n } else {\n logger.error('[Platform] Database failed readiness verification after all attempts');\n throw new Error(`Database failed readiness verification: ${err instanceof Error ? err.message : err}`);\n }\n }\n }\n\n // TypeScript: unreachable but needed for return type\n throw new Error('Database readiness verification failed');\n },\n fileSystem,\n storage,\n network,\n logger,\n imageProcessor\n };\n}\n\n// Re-export types for convenience\nexport type { PlatformAdapter, LoggerAdapter } from './types';"],"mappings":"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","names":[]}